@unovis/ts 1.4.0-alpha.8 → 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 +110 -114
  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,16 +105,18 @@ 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((isFirstRender) => {
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
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
+ }
117
120
  if (isFirstRender) {
118
121
  this._fit();
119
122
  this._shouldFitLayout = false;
@@ -202,17 +205,14 @@ class Graph extends ComponentCore {
202
205
  .attr('class', gLink)
203
206
  .call(createLinks, config, duration);
204
207
  const linkGroupsMerged = linkGroups.merge(linkGroupsEnter);
205
- linkGroupsMerged.call(updateLinks, config, duration, this._scale, this._getLinkArrowDefId);
208
+ linkGroupsMerged.call(updateLinks, config, duration, this._scale, this._getMarkerId);
206
209
  const linkGroupsExit = linkGroups.exit();
207
210
  linkGroupsExit
208
211
  .attr('class', gLinkExit)
209
212
  .call(removeLinks, config, duration);
210
213
  }
211
214
  _drawPanels(nodeUpdateSelection, duration) {
212
- var _a;
213
215
  const { config } = this;
214
- smartTransition(this._panelsGroup, duration / 2)
215
- .style('opacity', ((_a = config.panels) === null || _a === void 0 ? void 0 : _a.length) ? 1 : 0);
216
216
  if (!this._panels)
217
217
  return;
218
218
  const selection = (nodeUpdateSelection.duration)
@@ -239,58 +239,51 @@ class Graph extends ComponentCore {
239
239
  panelToUpdate.call(updatePanels, config, duration);
240
240
  }
241
241
  _calculateLayout() {
242
- var _a, _b;
243
242
  return __awaiter(this, void 0, void 0, function* () {
244
243
  const { config, datamodel } = this;
245
244
  const firstRender = this._isFirstRender;
246
- switch (config.layoutType) {
247
- case GraphLayoutType.Precalculated:
248
- break;
249
- case GraphLayoutType.Parallel:
250
- applyLayoutParallel(datamodel, config, this._width, this._height);
251
- break;
252
- case GraphLayoutType.ParallelHorizontal:
253
- applyLayoutParallel(datamodel, config, this._width, this._height, 'horizontal');
254
- break;
255
- case GraphLayoutType.Dagre:
256
- yield applyLayoutDagre(datamodel, config, this._width);
257
- break;
258
- case GraphLayoutType.Force:
259
- yield applyLayoutForce(datamodel, config, this._width);
260
- break;
261
- case GraphLayoutType.Concentric:
262
- applyLayoutConcentric(datamodel, config, this._width, this._height);
263
- break;
264
- case GraphLayoutType.Elk:
265
- yield applyELKLayout(datamodel, config, this._width);
266
- break;
267
- case GraphLayoutType.Circular:
268
- default:
269
- applyLayoutCircular(datamodel, config, this._width, this._height);
270
- break;
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;
271
271
  }
272
- // We need to update the panels data right after the layout calculation
273
- // because we want to have the latest coordinates before calling `onLayoutCalculated`
274
- this._initPanelsData();
275
- (_b = (_a = this.config).onLayoutCalculated) === null || _b === void 0 ? void 0 : _b.call(_a, datamodel.nodes, datamodel.links);
276
- this._shouldRecalculateLayout = false;
277
272
  return firstRender;
278
273
  });
279
274
  }
280
- _initPanelsData() {
281
- const { config, datamodel } = this;
282
- if (this._shouldSetPanels) {
283
- this._panels = initPanels(config.panels);
284
- setPanelForNodes(this._panels, datamodel.nodes, this.config);
285
- this._shouldSetPanels = false;
286
- }
287
- }
288
275
  _fit(duration = 0) {
276
+ var _a;
289
277
  const { datamodel: { nodes } } = this;
290
- const transform = this._getTransform(nodes);
291
- smartTransition(this.g, duration)
292
- .call(this._zoomBehavior.transform, transform);
293
- 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
+ }
294
287
  }
295
288
  _getTransform(nodes) {
296
289
  const { nodeSize, zoomScaleExtent } = this.config;
@@ -299,17 +292,13 @@ class Graph extends ComponentCore {
299
292
  const w = this._width;
300
293
  const h = this._height;
301
294
  const xExtent = [
302
- min(nodes, d => getX(d) - maxNodeSize / 2 - (max((d._panels || []).map(p => p._padding.left)) || 0)),
303
- 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); }),
304
297
  ];
305
298
  const yExtent = [
306
- min(nodes, d => getY(d) - maxNodeSize / 2 - (max((d._panels || []).map(p => p._padding.top)) || 0)),
307
- 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); }),
308
301
  ];
309
- if (xExtent.some(item => item === undefined) || yExtent.some(item => item === undefined)) {
310
- 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.');
311
- return zoomIdentity;
312
- }
313
302
  const xScale = w / (xExtent[1] - xExtent[0] + left + right);
314
303
  const yScale = h / (yExtent[1] - yExtent[0] + top + bottom);
315
304
  const clampedScale = clamp(min([xScale, yScale]), zoomScaleExtent[0], zoomScaleExtent[1]);
@@ -452,8 +441,7 @@ class Graph extends ComponentCore {
452
441
  this._scale = transform.k;
453
442
  this._graphGroup.attr('transform', transform.toString());
454
443
  if (isFunction(config.onZoom))
455
- config.onZoom(this._scale, config.zoomScaleExtent, event);
456
- // console.warn('Unovis | Graph: Zoom: ', transform)
444
+ config.onZoom(this._scale, config.zoomScaleExtent);
457
445
  if (!this._initialTransform)
458
446
  this._initialTransform = transform;
459
447
  // If the event was triggered by a mouse interaction (pan or zoom) we don't
@@ -463,9 +451,7 @@ class Graph extends ComponentCore {
463
451
  const propVal = transform[prop];
464
452
  const initialPropVal = this._initialTransform[prop];
465
453
  const dVal = Math.abs(propVal - initialPropVal);
466
- const scaledDVal = prop === 'k' ? 20 * dVal : dVal / 15;
467
- acc += scaledDVal;
468
- return acc;
454
+ return prop === 'k' ? 2 * dVal : dVal / 50;
469
455
  }, 0);
470
456
  if (diff > config.layoutAutofitTolerance)
471
457
  this._isAutoFitDisabled = true;
@@ -475,18 +461,16 @@ class Graph extends ComponentCore {
475
461
  this._nodesGroup.selectAll(`.${gNode}`)
476
462
  .call((nodes.length > config.zoomThrottledUpdateNodeThreshold ? zoomNodesThrottled : zoomNodes), config, this._scale);
477
463
  this._linksGroup.selectAll(`.${gLink}`)
478
- .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);
479
465
  }
480
466
  _onDragStarted(d, event, nodeSelection) {
481
- var _a;
482
467
  const { config } = this;
483
468
  this._isDragging = true;
484
469
  d._state.isDragged = true;
485
470
  nodeSelection.call(updateNodes, config, 0, this._scale);
486
- (_a = config.onNodeDragStart) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
487
471
  }
488
472
  _onDragged(d, event, allNodesSelection) {
489
- var _a, _b, _c;
473
+ var _a, _b;
490
474
  const { config } = this;
491
475
  const transform = zoomTransform(this.g.node());
492
476
  const scale = transform.k;
@@ -528,60 +512,79 @@ class Graph extends ComponentCore {
528
512
  const target = l.target;
529
513
  return source._id === d._id || target._id === d._id;
530
514
  });
531
- linksToUpdate.call(updateLinks, config, 0, scale, this._getLinkArrowDefId);
515
+ linksToUpdate.call(updateLinks, config, 0, scale, this._getMarkerId);
532
516
  const linksToAnimate = linksToUpdate.filter(d => d._state.greyout);
533
517
  if (linksToAnimate.size())
534
518
  animateLinkFlow(linksToAnimate, config, this._scale);
535
- (_c = config.onNodeDrag) === null || _c === void 0 ? void 0 : _c.call(config, d, event);
536
519
  }
537
520
  _onDragEnded(d, event, nodeSelection) {
538
- var _a;
539
521
  const { config } = this;
540
522
  this._isDragging = false;
541
523
  d._state.isDragged = false;
542
524
  nodeSelection.call(updateNodes, config, 0, this._scale);
543
- (_a = config.onNodeDragEnd) === null || _a === void 0 ? void 0 : _a.call(config, d, event);
544
525
  }
545
- _shouldLayoutRecalculate() {
546
- const { prevConfig, config } = this;
547
- if (prevConfig.layoutType !== config.layoutType)
526
+ _shouldLayoutRecalculate(nextConfig) {
527
+ const { config } = this;
528
+ if (config.layoutType !== nextConfig.layoutType)
548
529
  return true;
549
- if (prevConfig.layoutNonConnectedAside !== config.layoutNonConnectedAside)
530
+ if (config.layoutNonConnectedAside !== nextConfig.layoutNonConnectedAside)
550
531
  return true;
551
- if (prevConfig.layoutType === GraphLayoutType.Force) {
552
- const forceSettingsDiff = shallowDiff(prevConfig.forceLayoutSettings, config.forceLayoutSettings);
532
+ if (config.layoutType === GraphLayoutType.Force) {
533
+ const forceSettingsDiff = shallowDiff(config.forceLayoutSettings, nextConfig.forceLayoutSettings);
553
534
  if (Object.keys(forceSettingsDiff).length)
554
535
  return true;
555
536
  }
556
- if (prevConfig.layoutType === GraphLayoutType.Dagre) {
557
- const dagreSettingsDiff = shallowDiff(prevConfig.dagreLayoutSettings, config.dagreLayoutSettings);
537
+ if (config.layoutType === GraphLayoutType.Dagre) {
538
+ const dagreSettingsDiff = shallowDiff(config.dagreLayoutSettings, nextConfig.dagreLayoutSettings);
558
539
  if (Object.keys(dagreSettingsDiff).length)
559
540
  return true;
560
541
  }
561
- if (prevConfig.layoutType === GraphLayoutType.Parallel ||
562
- prevConfig.layoutType === GraphLayoutType.ParallelHorizontal ||
563
- prevConfig.layoutType === GraphLayoutType.Concentric) {
564
- 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)
565
546
  return true;
566
- if (prevConfig.layoutParallelNodesPerColumn !== config.layoutParallelNodesPerColumn)
547
+ if (config.layoutParallelNodesPerColumn !== nextConfig.layoutParallelNodesPerColumn)
567
548
  return true;
568
- if (prevConfig.layoutParallelSortConnectionsByGroup !== config.layoutParallelSortConnectionsByGroup)
549
+ if (config.layoutParallelSortConnectionsByGroup !== nextConfig.layoutParallelSortConnectionsByGroup)
569
550
  return true;
570
551
  }
571
552
  return false;
572
553
  }
573
- _getLinkArrowDefId(arrow) {
574
- 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;
575
559
  }
576
560
  _addSVGDefs() {
561
+ const { datamodel: { links } } = this;
577
562
  // Clean up old defs
578
563
  this._defs.selectAll('*').remove();
579
- // Single Arrow
580
- this._defs.append('path').attr('d', getArrowPath())
581
- .attr('id', this._getLinkArrowDefId(GraphLinkArrowStyle.Single));
582
- // Double Arrow
583
- this._defs.append('path').attr('d', getDoubleArrowPath())
584
- .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
+ });
585
588
  }
586
589
  zoomIn(increment = 0.3) {
587
590
  const scaleBy = 1 + increment;
@@ -597,13 +600,8 @@ class Graph extends ComponentCore {
597
600
  smartTransition(this.g, this.config.duration / 2)
598
601
  .call(this._zoomBehavior.scaleTo, zoomLevel);
599
602
  }
600
- getZoom() {
601
- return zoomTransform(this.g.node()).k;
602
- }
603
- fitView(duration = this.config.duration) {
604
- this._layoutCalculationPromise.then(() => {
605
- this._fit(duration);
606
- });
603
+ fitView() {
604
+ this._fit(this.config.duration / 2);
607
605
  }
608
606
  /** Enable automatic fitting to container if it was disabled due to previous zoom / pan interactions */
609
607
  resetAutofitState() {
@@ -643,10 +641,8 @@ Graph.selectors = {
643
641
  nodeGauge: nodeGauge,
644
642
  nodeSideLabel: sideLabelGroup,
645
643
  nodeLabel: label,
646
- dimmedNode: greyedOutNode,
647
644
  link: gLink,
648
645
  linkLine: link,
649
- dimmedLink: greyedOutLink,
650
646
  panel: gPanel,
651
647
  panelRect: panel,
652
648
  panelSelection: panelSelection,