@unovis/ts 1.4.0-alpha.9 → 1.4.0-beta.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.
Files changed (99) hide show
  1. package/components/annotations/config.d.ts +19 -0
  2. package/components/annotations/config.js +6 -0
  3. package/components/annotations/config.js.map +1 -0
  4. package/components/annotations/index.d.ts +24 -0
  5. package/components/annotations/index.js +116 -0
  6. package/components/annotations/index.js.map +1 -0
  7. package/components/annotations/style.d.ts +13 -0
  8. package/components/annotations/style.js +43 -0
  9. package/components/annotations/style.js.map +1 -0
  10. package/components/annotations/types.d.ts +43 -0
  11. package/components/annotations/types.js +8 -0
  12. package/components/annotations/types.js.map +1 -0
  13. package/components/area/config.d.ts +1 -1
  14. package/components/area/config.js.map +1 -1
  15. package/components/area/index.js.map +1 -1
  16. package/components/bullet-legend/config.d.ts +4 -2
  17. package/components/bullet-legend/config.js +1 -2
  18. package/components/bullet-legend/config.js.map +1 -1
  19. package/components/bullet-legend/index.js +15 -17
  20. package/components/bullet-legend/index.js.map +1 -1
  21. package/components/bullet-legend/modules/shape.d.ts +1 -2
  22. package/components/bullet-legend/modules/shape.js +39 -48
  23. package/components/bullet-legend/modules/shape.js.map +1 -1
  24. package/components/bullet-legend/style.js +2 -5
  25. package/components/bullet-legend/style.js.map +1 -1
  26. package/components/bullet-legend/types.d.ts +14 -5
  27. package/components/bullet-legend/types.js +4 -6
  28. package/components/bullet-legend/types.js.map +1 -1
  29. package/components/graph/config.d.ts +15 -22
  30. package/components/graph/config.js +2 -4
  31. package/components/graph/config.js.map +1 -1
  32. package/components/graph/index.d.ts +2 -7
  33. package/components/graph/index.js +116 -117
  34. package/components/graph/index.js.map +1 -1
  35. package/components/graph/modules/layout.js +19 -30
  36. package/components/graph/modules/layout.js.map +1 -1
  37. package/components/graph/modules/link/helper.d.ts +6 -4
  38. package/components/graph/modules/link/helper.js +25 -15
  39. package/components/graph/modules/link/helper.js.map +1 -1
  40. package/components/graph/modules/link/index.d.ts +3 -3
  41. package/components/graph/modules/link/index.js +89 -111
  42. package/components/graph/modules/link/index.js.map +1 -1
  43. package/components/graph/modules/link/style.d.ts +5 -5
  44. package/components/graph/modules/link/style.js +22 -26
  45. package/components/graph/modules/link/style.js.map +1 -1
  46. package/components/graph/modules/node/helper.d.ts +0 -1
  47. package/components/graph/modules/node/helper.js +1 -4
  48. package/components/graph/modules/node/helper.js.map +1 -1
  49. package/components/graph/modules/node/index.js +11 -28
  50. package/components/graph/modules/node/index.js.map +1 -1
  51. package/components/graph/modules/node/style.d.ts +1 -1
  52. package/components/graph/modules/node/style.js +6 -13
  53. package/components/graph/modules/node/style.js.map +1 -1
  54. package/components/graph/modules/shape.d.ts +2 -0
  55. package/components/graph/modules/shape.js +9 -7
  56. package/components/graph/modules/shape.js.map +1 -1
  57. package/components/graph/types.d.ts +5 -63
  58. package/components/graph/types.js +0 -1
  59. package/components/graph/types.js.map +1 -1
  60. package/components/stacked-bar/index.js.map +1 -1
  61. package/components/tooltip/config.d.ts +1 -1
  62. package/components/tooltip/config.js.map +1 -1
  63. package/components/tooltip/index.js +1 -3
  64. package/components/tooltip/index.js.map +1 -1
  65. package/components/vis-controls/index.d.ts +0 -3
  66. package/components/vis-controls/index.js +1 -6
  67. package/components/vis-controls/index.js.map +1 -1
  68. package/components.d.ts +2 -0
  69. package/components.js +1 -0
  70. package/components.js.map +1 -1
  71. package/containers/single-container/config.d.ts +3 -0
  72. package/containers/single-container/config.js.map +1 -1
  73. package/containers/single-container/index.js +10 -1
  74. package/containers/single-container/index.js.map +1 -1
  75. package/containers/xy-container/config.d.ts +3 -0
  76. package/containers/xy-container/config.js +1 -1
  77. package/containers/xy-container/config.js.map +1 -1
  78. package/containers/xy-container/index.js +17 -5
  79. package/containers/xy-container/index.js.map +1 -1
  80. package/core/component/index.d.ts +3 -3
  81. package/core/component/index.js +1 -1
  82. package/core/component/index.js.map +1 -1
  83. package/index.js +2 -0
  84. package/index.js.map +1 -1
  85. package/package.json +1 -1
  86. package/types/misc.d.ts +1 -0
  87. package/types/scale.d.ts +3 -2
  88. package/types/scale.js +2 -1
  89. package/types/scale.js.map +1 -1
  90. package/types.d.ts +1 -0
  91. package/types.js +1 -0
  92. package/types.js.map +1 -1
  93. package/utils/misc.d.ts +2 -1
  94. package/utils/misc.js +13 -1
  95. package/utils/misc.js.map +1 -1
  96. package/utils/svg.d.ts +0 -3
  97. package/utils/text.js.map +1 -1
  98. package/utils/svg.js +0 -61
  99. package/utils/svg.js.map +0 -1
@@ -6,21 +6,22 @@ import { drag } from 'd3-drag';
6
6
  import { interval } from 'd3-timer';
7
7
  import { ComponentCore } from '../../core/component/index.js';
8
8
  import { GraphDataModel } from '../../data-models/graph.js';
9
- import { isNumber, clamp, getBoolean, isFunction, shallowDiff } from '../../utils/data.js';
9
+ import { isNumber, clamp, getBoolean, isFunction, shallowDiff, unique, clean } from '../../utils/data.js';
10
+ import { stringToHtmlId } from '../../utils/misc.js';
10
11
  import { smartTransition } from '../../utils/d3.js';
11
12
  import { GraphLayoutType, GraphLinkArrowStyle } from './types.js';
12
13
  import { GraphDefaultConfig } from './config.js';
13
14
  import { background, graphGroup, 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 { links, gLink, gLinkExit, link, greyedOutLink } from './modules/link/style.js';
16
+ import { nodes, gNode, gNodeExit, node, nodeGauge, sideLabelGroup, label } from './modules/node/style.js';
17
+ import { links, gLink, gLinkExit, link } 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
19
  import { createNodes, updateNodes, removeNodes, updateSelectedNodes, zoomNodesThrottled, zoomNodes } from './modules/node/index.js';
19
20
  import { getMaxNodeSize, getX, getY, getNodeSize } from './modules/node/helper.js';
20
21
  import { createLinks, updateLinks, removeLinks, updateSelectedLinks, animateLinkFlow, zoomLinksThrottled, zoomLinks } from './modules/link/index.js';
21
- import { getArrowPath, getDoubleArrowPath } from './modules/link/helper.js';
22
+ import { getLinkColor, getLinkArrow, LINK_MARKER_WIDTH, LINK_MARKER_HEIGHT, getDoubleArrowPath, getArrowPath } from './modules/link/helper.js';
22
23
  import { removePanels, createPanels, updatePanels } from './modules/panel/index.js';
23
- import { updatePanelNumNodes, updatePanelBBoxSize, initPanels, setPanelForNodes } from './modules/panel/helper.js';
24
+ import { initPanels, setPanelForNodes, updatePanelNumNodes, updatePanelBBoxSize } from './modules/panel/helper.js';
24
25
  import { applyLayoutCircular, applyELKLayout, applyLayoutConcentric, applyLayoutForce, applyLayoutDagre, applyLayoutParallel } from './modules/layout.js';
25
26
 
26
27
  class Graph extends ComponentCore {
@@ -60,7 +61,7 @@ class Graph extends ComponentCore {
60
61
  this._linksGroup = this._graphGroup.append('g').attr('class', links);
61
62
  this._nodesGroup = this._graphGroup.append('g').attr('class', nodes);
62
63
  this._defs = this._graphGroup.append('defs');
63
- this._getLinkArrowDefId = this._getLinkArrowDefId.bind(this);
64
+ this._getMarkerId = this._getMarkerId.bind(this);
64
65
  }
65
66
  get selectedNode() {
66
67
  return this._selectedNode;
@@ -79,9 +80,9 @@ class Graph extends ComponentCore {
79
80
  this._addSVGDefs();
80
81
  }
81
82
  setConfig(config) {
82
- super.setConfig(config);
83
- this._shouldRecalculateLayout = this._shouldRecalculateLayout || this._shouldLayoutRecalculate();
83
+ this._shouldRecalculateLayout = this._shouldRecalculateLayout || this._shouldLayoutRecalculate(config);
84
84
  this._shouldFitLayout = this._shouldFitLayout || this._shouldRecalculateLayout;
85
+ super.setConfig(config);
85
86
  this._shouldSetPanels = true;
86
87
  }
87
88
  get bleed() {
@@ -89,7 +90,7 @@ class Graph extends ComponentCore {
89
90
  return { top: extraPadding, bottom: extraPadding, left: extraPadding, right: extraPadding };
90
91
  }
91
92
  _render(customDuration) {
92
- const { config: { disableZoom, duration, layoutAutofit }, datamodel } = this;
93
+ const { config: { disableZoom, duration, layoutAutofit, panels }, datamodel } = this;
93
94
  if (!datamodel.nodes && !datamodel.links)
94
95
  return;
95
96
  const animDuration = isNumber(customDuration) ? customDuration : duration;
@@ -104,17 +105,19 @@ class Graph extends ComponentCore {
104
105
  this._prevHeight = this._height;
105
106
  }
106
107
  // Apply layout and render
107
- if (this._shouldRecalculateLayout || !this._layoutCalculationPromise) {
108
- this._layoutCalculationPromise = this._calculateLayout();
109
- }
110
- this._layoutCalculationPromise.then(() => {
108
+ this._calculateLayout().then((isFirstRender) => {
111
109
  // If the component has been destroyed while the layout calculation
112
110
  // was in progress, we cancel the render
113
111
  if (this.isDestroyed())
114
112
  return;
115
- this._initPanelsData();
116
- // Fit the view
117
- if (this._isFirstRender) {
113
+ if (this._shouldSetPanels) {
114
+ smartTransition(this._panelsGroup, duration / 2)
115
+ .style('opacity', (panels === null || panels === void 0 ? void 0 : panels.length) ? 1 : 0);
116
+ this._panels = initPanels(panels);
117
+ setPanelForNodes(this._panels, datamodel.nodes, this.config);
118
+ this._shouldSetPanels = false;
119
+ }
120
+ if (isFirstRender) {
118
121
  this._fit();
119
122
  this._shouldFitLayout = false;
120
123
  }
@@ -143,8 +146,9 @@ class Graph extends ComponentCore {
143
146
  // Zoom
144
147
  if (disableZoom)
145
148
  this.g.on('.zoom', null);
146
- else {
149
+ else
147
150
  this.g.call(this._zoomBehavior).on('dblclick.zoom', null);
151
+ if (!this._isFirstRender && !disableZoom) {
148
152
  const transform = zoomTransform(this.g.node());
149
153
  this._onZoom(transform);
150
154
  }
@@ -160,8 +164,8 @@ class Graph extends ComponentCore {
160
164
  // calculation and they were not set up properly (see the render function of `ComponentCore`)
161
165
  this._setUpComponentEventsThrottled();
162
166
  this._setCustomAttributesThrottled();
163
- this._isFirstRender = false;
164
167
  });
168
+ this._isFirstRender = false;
165
169
  }
166
170
  _drawNodes(duration) {
167
171
  const { config, datamodel } = this;
@@ -201,17 +205,14 @@ class Graph extends ComponentCore {
201
205
  .attr('class', gLink)
202
206
  .call(createLinks, config, duration);
203
207
  const linkGroupsMerged = linkGroups.merge(linkGroupsEnter);
204
- linkGroupsMerged.call(updateLinks, config, duration, this._scale, this._getLinkArrowDefId);
208
+ linkGroupsMerged.call(updateLinks, config, duration, this._scale, this._getMarkerId);
205
209
  const linkGroupsExit = linkGroups.exit();
206
210
  linkGroupsExit
207
211
  .attr('class', gLinkExit)
208
212
  .call(removeLinks, config, duration);
209
213
  }
210
214
  _drawPanels(nodeUpdateSelection, duration) {
211
- var _a;
212
215
  const { config } = this;
213
- smartTransition(this._panelsGroup, duration / 2)
214
- .style('opacity', ((_a = config.panels) === null || _a === void 0 ? void 0 : _a.length) ? 1 : 0);
215
216
  if (!this._panels)
216
217
  return;
217
218
  const selection = (nodeUpdateSelection.duration)
@@ -238,56 +239,51 @@ class Graph extends ComponentCore {
238
239
  panelToUpdate.call(updatePanels, config, duration);
239
240
  }
240
241
  _calculateLayout() {
241
- var _a, _b;
242
242
  return __awaiter(this, void 0, void 0, function* () {
243
243
  const { config, datamodel } = this;
244
- switch (config.layoutType) {
245
- case GraphLayoutType.Precalculated:
246
- break;
247
- case GraphLayoutType.Parallel:
248
- applyLayoutParallel(datamodel, config, this._width, this._height);
249
- break;
250
- case GraphLayoutType.ParallelHorizontal:
251
- applyLayoutParallel(datamodel, config, this._width, this._height, 'horizontal');
252
- break;
253
- case GraphLayoutType.Dagre:
254
- yield applyLayoutDagre(datamodel, config, this._width);
255
- break;
256
- case GraphLayoutType.Force:
257
- yield applyLayoutForce(datamodel, config, this._width);
258
- break;
259
- case GraphLayoutType.Concentric:
260
- applyLayoutConcentric(datamodel, config, this._width, this._height);
261
- break;
262
- case GraphLayoutType.Elk:
263
- yield applyELKLayout(datamodel, config, this._width);
264
- break;
265
- case GraphLayoutType.Circular:
266
- default:
267
- applyLayoutCircular(datamodel, config, this._width, this._height);
268
- break;
244
+ const firstRender = this._isFirstRender;
245
+ if (this._shouldRecalculateLayout) {
246
+ switch (config.layoutType) {
247
+ case GraphLayoutType.Parallel:
248
+ applyLayoutParallel(datamodel, config, this._width, this._height);
249
+ break;
250
+ case GraphLayoutType.ParallelHorizontal:
251
+ applyLayoutParallel(datamodel, config, this._width, this._height, 'horizontal');
252
+ break;
253
+ case GraphLayoutType.Dagre:
254
+ yield applyLayoutDagre(datamodel, config, this._width);
255
+ break;
256
+ case GraphLayoutType.Force:
257
+ yield applyLayoutForce(datamodel, config, this._width);
258
+ break;
259
+ case GraphLayoutType.Concentric:
260
+ applyLayoutConcentric(datamodel, config, this._width, this._height);
261
+ break;
262
+ case GraphLayoutType.Elk:
263
+ yield applyELKLayout(datamodel, config, this._width);
264
+ break;
265
+ case GraphLayoutType.Circular:
266
+ default:
267
+ applyLayoutCircular(datamodel, config, this._width, this._height);
268
+ break;
269
+ }
270
+ this._shouldRecalculateLayout = false;
269
271
  }
270
- // We need to update the panels data right after the layout calculation
271
- // because we want to have the latest coordinates before calling `onLayoutCalculated`
272
- this._initPanelsData();
273
- (_b = (_a = this.config).onLayoutCalculated) === null || _b === void 0 ? void 0 : _b.call(_a, datamodel.nodes, datamodel.links);
274
- this._shouldRecalculateLayout = false;
272
+ return firstRender;
275
273
  });
276
274
  }
277
- _initPanelsData() {
278
- const { config, datamodel } = this;
279
- if (this._shouldSetPanels) {
280
- this._panels = initPanels(config.panels);
281
- setPanelForNodes(this._panels, datamodel.nodes, this.config);
282
- this._shouldSetPanels = false;
283
- }
284
- }
285
275
  _fit(duration = 0) {
276
+ var _a;
286
277
  const { datamodel: { nodes } } = this;
287
- const transform = this._getTransform(nodes);
288
- smartTransition(this.g, duration)
289
- .call(this._zoomBehavior.transform, transform);
290
- this._onZoom(transform);
278
+ if ((nodes === null || nodes === void 0 ? void 0 : nodes.length) && ((_a = this.g) === null || _a === void 0 ? void 0 : _a.size())) {
279
+ const transform = this._getTransform(nodes);
280
+ smartTransition(this.g, duration)
281
+ .call(this._zoomBehavior.transform, transform);
282
+ this._onZoom(transform);
283
+ }
284
+ else {
285
+ console.warn('Unovis | Graph: Node data is not defined. Check if the component has been initialized.');
286
+ }
291
287
  }
292
288
  _getTransform(nodes) {
293
289
  const { nodeSize, zoomScaleExtent } = this.config;
@@ -296,17 +292,13 @@ class Graph extends ComponentCore {
296
292
  const w = this._width;
297
293
  const h = this._height;
298
294
  const xExtent = [
299
- min(nodes, d => getX(d) - maxNodeSize / 2 - (max((d._panels || []).map(p => p._padding.left)) || 0)),
300
- max(nodes, d => getX(d) + maxNodeSize / 2 + (max((d._panels || []).map(p => p._padding.right)) || 0)),
295
+ min(nodes, d => { var _a; return getX(d) - maxNodeSize / 2 - (max((_a = d._panels) === null || _a === void 0 ? void 0 : _a.map(p => p._padding.left)) || 0); }),
296
+ max(nodes, d => { var _a; return getX(d) + maxNodeSize / 2 + (max((_a = d._panels) === null || _a === void 0 ? void 0 : _a.map(p => p._padding.right)) || 0); }),
301
297
  ];
302
298
  const yExtent = [
303
- min(nodes, d => getY(d) - maxNodeSize / 2 - (max((d._panels || []).map(p => p._padding.top)) || 0)),
304
- max(nodes, d => getY(d) + maxNodeSize / 2 + (max((d._panels || []).map(p => p._padding.bottom)) || 0)),
299
+ min(nodes, d => { var _a; return getY(d) - maxNodeSize / 2 - (max((_a = d._panels) === null || _a === void 0 ? void 0 : _a.map(p => p._padding.top)) || 0); }),
300
+ max(nodes, d => { var _a; return getY(d) + maxNodeSize / 2 + (max((_a = d._panels) === null || _a === void 0 ? void 0 : _a.map(p => p._padding.bottom)) || 0); }),
305
301
  ];
306
- if (xExtent.some(item => item === undefined) || yExtent.some(item => item === undefined)) {
307
- console.warn('Unovis | Graph: Some of the node coordinates are undefined. This can happen if you try to fit the graph before the layout has been calculated.');
308
- return zoomIdentity;
309
- }
310
302
  const xScale = w / (xExtent[1] - xExtent[0] + left + right);
311
303
  const yScale = h / (yExtent[1] - yExtent[0] + top + bottom);
312
304
  const clampedScale = clamp(min([xScale, yScale]), zoomScaleExtent[0], zoomScaleExtent[1]);
@@ -449,8 +441,7 @@ class Graph extends ComponentCore {
449
441
  this._scale = transform.k;
450
442
  this._graphGroup.attr('transform', transform.toString());
451
443
  if (isFunction(config.onZoom))
452
- config.onZoom(this._scale, config.zoomScaleExtent, event);
453
- // console.warn('Unovis | Graph: Zoom: ', transform)
444
+ config.onZoom(this._scale, config.zoomScaleExtent);
454
445
  if (!this._initialTransform)
455
446
  this._initialTransform = transform;
456
447
  // If the event was triggered by a mouse interaction (pan or zoom) we don't
@@ -460,9 +451,7 @@ class Graph extends ComponentCore {
460
451
  const propVal = transform[prop];
461
452
  const initialPropVal = this._initialTransform[prop];
462
453
  const dVal = Math.abs(propVal - initialPropVal);
463
- const scaledDVal = prop === 'k' ? 20 * dVal : dVal / 15;
464
- acc += scaledDVal;
465
- return acc;
454
+ return prop === 'k' ? 2 * dVal : dVal / 50;
466
455
  }, 0);
467
456
  if (diff > config.layoutAutofitTolerance)
468
457
  this._isAutoFitDisabled = true;
@@ -472,18 +461,16 @@ class Graph extends ComponentCore {
472
461
  this._nodesGroup.selectAll(`.${gNode}`)
473
462
  .call((nodes.length > config.zoomThrottledUpdateNodeThreshold ? zoomNodesThrottled : zoomNodes), config, this._scale);
474
463
  this._linksGroup.selectAll(`.${gLink}`)
475
- .call((nodes.length > config.zoomThrottledUpdateNodeThreshold ? zoomLinksThrottled : zoomLinks), config, this._scale, this._getLinkArrowDefId);
464
+ .call((nodes.length > config.zoomThrottledUpdateNodeThreshold ? zoomLinksThrottled : zoomLinks), config, this._scale, this._getMarkerId);
476
465
  }
477
466
  _onDragStarted(d, event, nodeSelection) {
478
- var _a;
479
467
  const { config } = this;
480
468
  this._isDragging = true;
481
469
  d._state.isDragged = true;
482
470
  nodeSelection.call(updateNodes, config, 0, this._scale);
483
- (_a = config.onNodeDragStart) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
484
471
  }
485
472
  _onDragged(d, event, allNodesSelection) {
486
- var _a, _b, _c;
473
+ var _a, _b;
487
474
  const { config } = this;
488
475
  const transform = zoomTransform(this.g.node());
489
476
  const scale = transform.k;
@@ -525,60 +512,79 @@ class Graph extends ComponentCore {
525
512
  const target = l.target;
526
513
  return source._id === d._id || target._id === d._id;
527
514
  });
528
- linksToUpdate.call(updateLinks, config, 0, scale, this._getLinkArrowDefId);
515
+ linksToUpdate.call(updateLinks, config, 0, scale, this._getMarkerId);
529
516
  const linksToAnimate = linksToUpdate.filter(d => d._state.greyout);
530
517
  if (linksToAnimate.size())
531
518
  animateLinkFlow(linksToAnimate, config, this._scale);
532
- (_c = config.onNodeDrag) === null || _c === void 0 ? void 0 : _c.call(config, d, event);
533
519
  }
534
520
  _onDragEnded(d, event, nodeSelection) {
535
- var _a;
536
521
  const { config } = this;
537
522
  this._isDragging = false;
538
523
  d._state.isDragged = false;
539
524
  nodeSelection.call(updateNodes, config, 0, this._scale);
540
- (_a = config.onNodeDragEnd) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
541
525
  }
542
- _shouldLayoutRecalculate() {
543
- const { prevConfig, config } = this;
544
- if (prevConfig.layoutType !== config.layoutType)
526
+ _shouldLayoutRecalculate(nextConfig) {
527
+ const { config } = this;
528
+ if (config.layoutType !== nextConfig.layoutType)
545
529
  return true;
546
- if (prevConfig.layoutNonConnectedAside !== config.layoutNonConnectedAside)
530
+ if (config.layoutNonConnectedAside !== nextConfig.layoutNonConnectedAside)
547
531
  return true;
548
- if (prevConfig.layoutType === GraphLayoutType.Force) {
549
- const forceSettingsDiff = shallowDiff(prevConfig.forceLayoutSettings, config.forceLayoutSettings);
532
+ if (config.layoutType === GraphLayoutType.Force) {
533
+ const forceSettingsDiff = shallowDiff(config.forceLayoutSettings, nextConfig.forceLayoutSettings);
550
534
  if (Object.keys(forceSettingsDiff).length)
551
535
  return true;
552
536
  }
553
- if (prevConfig.layoutType === GraphLayoutType.Dagre) {
554
- const dagreSettingsDiff = shallowDiff(prevConfig.dagreLayoutSettings, config.dagreLayoutSettings);
537
+ if (config.layoutType === GraphLayoutType.Dagre) {
538
+ const dagreSettingsDiff = shallowDiff(config.dagreLayoutSettings, nextConfig.dagreLayoutSettings);
555
539
  if (Object.keys(dagreSettingsDiff).length)
556
540
  return true;
557
541
  }
558
- if (prevConfig.layoutType === GraphLayoutType.Parallel ||
559
- prevConfig.layoutType === GraphLayoutType.ParallelHorizontal ||
560
- prevConfig.layoutType === GraphLayoutType.Concentric) {
561
- if (prevConfig.layoutGroupOrder !== config.layoutGroupOrder)
542
+ if (config.layoutType === GraphLayoutType.Parallel ||
543
+ config.layoutType === GraphLayoutType.ParallelHorizontal ||
544
+ config.layoutType === GraphLayoutType.Concentric) {
545
+ if (config.layoutGroupOrder !== nextConfig.layoutGroupOrder)
562
546
  return true;
563
- if (prevConfig.layoutParallelNodesPerColumn !== config.layoutParallelNodesPerColumn)
547
+ if (config.layoutParallelNodesPerColumn !== nextConfig.layoutParallelNodesPerColumn)
564
548
  return true;
565
- if (prevConfig.layoutParallelSortConnectionsByGroup !== config.layoutParallelSortConnectionsByGroup)
549
+ if (config.layoutParallelSortConnectionsByGroup !== nextConfig.layoutParallelSortConnectionsByGroup)
566
550
  return true;
567
551
  }
568
552
  return false;
569
553
  }
570
- _getLinkArrowDefId(arrow) {
571
- return arrow ? `${this.uid}-${arrow}` : null;
554
+ _getMarkerId(d, color, arrow) {
555
+ const { config } = this;
556
+ const c = color !== null && color !== void 0 ? color : getLinkColor(d, config);
557
+ const a = arrow !== null && arrow !== void 0 ? arrow : getLinkArrow(d, this._scale, config);
558
+ return a && c ? `${this.uid}-${stringToHtmlId(c)}-${a}` : null;
572
559
  }
573
560
  _addSVGDefs() {
561
+ const { datamodel: { links } } = this;
574
562
  // Clean up old defs
575
563
  this._defs.selectAll('*').remove();
576
- // Single Arrow
577
- this._defs.append('path').attr('d', getArrowPath())
578
- .attr('id', this._getLinkArrowDefId(GraphLinkArrowStyle.Single));
579
- // Double Arrow
580
- this._defs.append('path').attr('d', getDoubleArrowPath())
581
- .attr('id', this._getLinkArrowDefId(GraphLinkArrowStyle.Double));
564
+ // Get all variations of link colors to create markers
565
+ const linkColors = unique(clean(links.map(d => getLinkColor(d, this.config))));
566
+ this._defs.selectAll('marker')
567
+ .data([
568
+ ...linkColors.map(d => ({ color: d, arrow: GraphLinkArrowStyle.Single })),
569
+ ...linkColors.map(d => ({ color: d, arrow: GraphLinkArrowStyle.Double })), // Double-sided arrows
570
+ ]).enter()
571
+ .append('marker')
572
+ .attr('id', d => this._getMarkerId(null, d.color, d.arrow))
573
+ .attr('orient', 'auto')
574
+ .attr('markerWidth', d => d.arrow === GraphLinkArrowStyle.Double ? LINK_MARKER_WIDTH * 2 : LINK_MARKER_WIDTH)
575
+ .attr('markerHeight', d => d.arrow === GraphLinkArrowStyle.Double ? LINK_MARKER_HEIGHT * 2 : LINK_MARKER_HEIGHT)
576
+ .attr('markerUnits', 'userSpaceOnUse')
577
+ .attr('refX', LINK_MARKER_WIDTH - LINK_MARKER_HEIGHT / 2)
578
+ .attr('refY', LINK_MARKER_HEIGHT - LINK_MARKER_HEIGHT / 2)
579
+ .html(d => {
580
+ var _a;
581
+ return `
582
+ <path
583
+ d="${d.arrow === GraphLinkArrowStyle.Double ? getDoubleArrowPath() : getArrowPath()}"
584
+ fill="${(_a = d.color) !== null && _a !== void 0 ? _a : null}"
585
+ />
586
+ `;
587
+ });
582
588
  }
583
589
  zoomIn(increment = 0.3) {
584
590
  const scaleBy = 1 + increment;
@@ -594,13 +600,8 @@ class Graph extends ComponentCore {
594
600
  smartTransition(this.g, this.config.duration / 2)
595
601
  .call(this._zoomBehavior.scaleTo, zoomLevel);
596
602
  }
597
- getZoom() {
598
- return zoomTransform(this.g.node()).k;
599
- }
600
- fitView(duration = this.config.duration) {
601
- this._layoutCalculationPromise.then(() => {
602
- this._fit(duration);
603
- });
603
+ fitView() {
604
+ this._fit(this.config.duration / 2);
604
605
  }
605
606
  /** Enable automatic fitting to container if it was disabled due to previous zoom / pan interactions */
606
607
  resetAutofitState() {
@@ -640,10 +641,8 @@ Graph.selectors = {
640
641
  nodeGauge: nodeGauge,
641
642
  nodeSideLabel: sideLabelGroup,
642
643
  nodeLabel: label,
643
- dimmedNode: greyedOutNode,
644
644
  link: gLink,
645
645
  linkLine: link,
646
- dimmedLink: greyedOutLink,
647
646
  panel: gPanel,
648
647
  panelRect: panel,
649
648
  panelSelection: panelSelection,