@progress/kendo-charts 2.3.0-dev.202404070723 → 2.3.0-dev.202404121620

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.
@@ -58,9 +58,14 @@ Sankey.prototype.calculate = function calculate () {
58
58
  var links = ref.links;
59
59
  this.connectLinksToNodes(nodes, links);
60
60
  this.calculateNodeValues(nodes);
61
- this.calculateNodeDepths(nodes);
62
- this.calculateNodeHeights(nodes);
63
61
 
62
+ var circularLinks = this.calculateNodeHeights(nodes);
63
+
64
+ if (circularLinks) {
65
+ return { nodes: [], links: [], columns: [], circularLinks: circularLinks };
66
+ }
67
+
68
+ this.calculateNodeDepths(nodes);
64
69
  var columns = this.calculateNodeColumns(nodes);
65
70
  this.calculateNodeBreadths(columns);
66
71
  this.applyNodesOffset(nodes);
@@ -118,21 +123,26 @@ Sankey.prototype.calculateNodeDepths = function calculateNodeDepths (nodes) {
118
123
  };
119
124
 
120
125
  Sankey.prototype.calculateNodeHeights = function calculateNodeHeights (nodes) {
126
+ var nodesLength = nodes.length;
121
127
  var current = new Set(nodes);
122
128
  var next = new Set;
123
- var x = 0;
129
+ var currentHeight = 0;
124
130
  var eachNode = function (node) {
125
- node.height = x;
131
+ node.height = currentHeight;
126
132
  node.targetLinks.forEach(function (link) {
127
133
  next.add(link.source);
128
134
  });
129
135
  };
130
136
  while (current.size) {
131
137
  current.forEach(eachNode);
132
- x++;
138
+ currentHeight++;
139
+ if (currentHeight > nodesLength) {
140
+ return true;
141
+ }
133
142
  current = next;
134
143
  next = new Set;
135
144
  }
145
+ return false;
136
146
  };
137
147
 
138
148
  Sankey.prototype.calculateNodeColumns = function calculateNodeColumns (nodes) {
@@ -1,7 +1,6 @@
1
1
  import { default as ChartLegend } from "../chart/legend/legend";
2
2
  import { SankeyElement } from "./element";
3
3
  import { setDefaultOptions } from '../common';
4
- import { nodeColor } from "./node";
5
4
  import { BOTTOM, CENTER, POINTER } from "../common/constants";
6
5
  import { AREA } from "../chart/constants";
7
6
 
@@ -25,17 +24,16 @@ export var Legend = (function (SankeyElement) {
25
24
  var options = this.options;
26
25
  var drawingRect = options.drawingRect;
27
26
  var nodes = options.nodes; if ( nodes === void 0 ) nodes = [];
28
- var colors = options.colors; if ( colors === void 0 ) colors = [];
29
27
  var item = options.item;
30
28
 
31
29
  if (options.visible === false || !nodes.length) {
32
30
  return null;
33
31
  }
34
32
 
35
- var data = nodes.map(function (node, index) { return ({
33
+ var data = nodes.map(function (node) { return ({
36
34
  text: (node.label && node.label.text) || '',
37
35
  area: {
38
- background: item.areaBackground !== undefined ? item.areaBackground : nodeColor(node, colors, index),
36
+ background: item.areaBackground !== undefined ? item.areaBackground : node.color,
39
37
  opacity: item.areaOpacity !== undefined ? item.areaOpacity : node.opacity
40
38
  },
41
39
  node: node,
@@ -38,12 +38,12 @@ export var Node = (function (SankeyElement) {
38
38
  return Node;
39
39
  }(SankeyElement));
40
40
 
41
- export var nodeColor = function (node, nodesColors, index) { return node.color || nodesColors[index % nodesColors.length]; };
41
+ var nodeColor = function (node, nodeColors, index) { return node.color || nodeColors[index % nodeColors.length]; };
42
42
 
43
- export var resolveNodeOptions = function (node, options, nodesColors, index) {
43
+ export var resolveNodeOptions = function (node, options, nodeColors, index) {
44
44
  var nodeOptions = deepExtend({}, options, options.node);
45
45
  return deepExtend({},
46
- { color: nodeColor(node, nodesColors, index) },
46
+ { color: nodeColor(node, nodeColors, index) },
47
47
  nodeOptions,
48
48
  { node: node },
49
49
  {
@@ -105,12 +105,21 @@ export var Sankey = (function (Observable) {
105
105
  var this$1 = this;
106
106
 
107
107
  this.linksVisuals.forEach(function (link) {
108
- this$1.setOpacity(link, opacity);
108
+ this$1.setOpacity(link, opacity, link.linkOptions.opacity);
109
109
  });
110
110
  };
111
111
 
112
- Sankey.prototype.setOpacity = function setOpacity (link, opacity) {
113
- link.options.set('stroke', Object.assign({}, link.options.stroke, {opacity: opacity}));
112
+ Sankey.prototype.setLinksInactivityOpacity = function setLinksInactivityOpacity (inactiveOpacity) {
113
+ var this$1 = this;
114
+
115
+ this.linksVisuals.forEach(function (link) {
116
+ this$1.setOpacity(link, inactiveOpacity, link.linkOptions.highlight.inactiveOpacity);
117
+ });
118
+ };
119
+
120
+ Sankey.prototype.setOpacity = function setOpacity (link, opacity, linkValue) {
121
+ link.options.set('stroke', Object.assign({}, link.options.stroke,
122
+ {opacity: defined(linkValue) ? linkValue : opacity}));
114
123
  };
115
124
 
116
125
  Sankey.prototype.trigger = function trigger (name, ev) {
@@ -136,8 +145,8 @@ export var Sankey = (function (Observable) {
136
145
  var ref = this.options.links;
137
146
  var highlight = ref.highlight;
138
147
  if (isLink) {
139
- this.setLinksOpacity(highlight.inactiveOpacity);
140
- this.setOpacity(element, highlight.opacity);
148
+ this.setLinksInactivityOpacity(highlight.inactiveOpacity);
149
+ this.setOpacity(element, highlight.opacity, element.linkOptions.highlight.opacity);
141
150
  } else if (isNode) {
142
151
  this.highlightLinks(element, highlight);
143
152
  } else if (isLegendItem) {
@@ -147,6 +156,8 @@ export var Sankey = (function (Observable) {
147
156
  };
148
157
 
149
158
  Sankey.prototype._mouseleave = function _mouseleave (ev) {
159
+ var this$1 = this;
160
+
150
161
  var element = ev.element;
151
162
  var isLink = element.type === LINK;
152
163
  var isNode = element.type === NODE;
@@ -172,14 +183,16 @@ export var Sankey = (function (Observable) {
172
183
  }
173
184
 
174
185
  if (isLink || isNode || isLegendItem) {
175
- this.setLinksOpacity(this.options.links.opacity);
186
+ this.linksVisuals.forEach(function (link) {
187
+ this$1.setOpacity(link, this$1.options.links.opacity, link.linkOptions.opacity);
188
+ });
176
189
  }
177
190
  };
178
191
 
179
192
  Sankey.prototype._mousemove = function _mousemove (ev) {
180
193
  var this$1 = this;
181
194
 
182
- var ref = this.options.tooltips;
195
+ var ref = this.options.tooltip;
183
196
  var followPointer = ref.followPointer;
184
197
  var delay = ref.delay;
185
198
  var element = ev.element;
@@ -241,9 +254,9 @@ export var Sankey = (function (Observable) {
241
254
  var this$1 = this;
242
255
 
243
256
  if (node) {
244
- this.setLinksOpacity(highlight.inactiveOpacity);
257
+ this.setLinksInactivityOpacity(highlight.inactiveOpacity);
245
258
  node.links.forEach(function (link) {
246
- this$1.setOpacity(link, highlight.opacity);
259
+ this$1.setOpacity(link, highlight.opacity, link.linkOptions.highlight.opacity);
247
260
  });
248
261
  }
249
262
  };
@@ -333,7 +346,7 @@ export var Sankey = (function (Observable) {
333
346
  var data = sankeyOptions.data;
334
347
  var nodes = sankeyOptions.nodes;
335
348
  var labels = sankeyOptions.labels;
336
- var nodesColors = sankeyOptions.nodesColors;
349
+ var nodeColors = sankeyOptions.nodeColors;
337
350
  var disableAutoLayout = sankeyOptions.disableAutoLayout;
338
351
  var autoLayout = !disableAutoLayout;
339
352
 
@@ -374,11 +387,18 @@ export var Sankey = (function (Observable) {
374
387
  }
375
388
  }
376
389
 
377
- var calculatedNodes = calculateSankey(Object.assign({}, calcOptions, {offsetX: 0, offsetY: 0, width: sankeyBox.width(), height: sankeyBox.height()})).nodes;
390
+ var ref = calculateSankey(Object.assign({}, calcOptions, {offsetX: 0, offsetY: 0, width: sankeyBox.width(), height: sankeyBox.height()}));
391
+ var calculatedNodes = ref.nodes;
392
+ var circularLinks = ref.circularLinks;
393
+ if (circularLinks) {
394
+ console.warn('Circular links detected. Kendo Sankey diagram does not support circular links.');
395
+ return { sankey: { nodes: [], links: [], circularLinks: circularLinks }, legendBox: legendBox, titleBox: titleBox };
396
+ }
397
+
378
398
  var box = new Box();
379
399
 
380
400
  calculatedNodes.forEach(function (nodeEl, i) {
381
- var nodeOps = resolveNodeOptions(nodeEl, nodes, nodesColors, i);
401
+ var nodeOps = resolveNodeOptions(nodeEl, nodes, nodeColors, i);
382
402
  var nodeInstance = new Node(nodeOps);
383
403
  box.wrap(rectToBox(nodeInstance.exportVisual().rawBBox()));
384
404
 
@@ -460,7 +480,7 @@ export var Sankey = (function (Observable) {
460
480
  var labelOptions = sankeyOptions.labels;
461
481
  var nodesOptions = sankeyOptions.nodes;
462
482
  var linkOptions = sankeyOptions.links;
463
- var nodesColors = sankeyOptions.nodesColors;
483
+ var nodeColors = sankeyOptions.nodeColors;
464
484
  var title = sankeyOptions.title;
465
485
  var legend = sankeyOptions.legend;
466
486
  var ref = sankeyContext.size;
@@ -485,17 +505,24 @@ export var Sankey = (function (Observable) {
485
505
  visual.append(titleVisual);
486
506
  }
487
507
 
508
+ if (sankey.circularLinks) {
509
+ return visual;
510
+ }
511
+
488
512
  var visualNodes = new Map();
489
513
  sankeyContext.nodesVisuals = visualNodes;
490
514
 
491
515
  nodes.forEach(function (node, i) {
492
- var nodeOps = resolveNodeOptions(node, nodesOptions, nodesColors, i);
516
+ var nodeOps = resolveNodeOptions(node, nodesOptions, nodeColors, i);
493
517
 
494
518
  var nodeInstance = new Node(nodeOps);
495
519
  var nodeVisual = nodeInstance.exportVisual();
496
520
  nodeVisual.links = [];
497
521
  nodeVisual.type = NODE;
498
522
 
523
+ node.color = nodeOps.color;
524
+ node.opacity = nodeOps.opacity;
525
+
499
526
  nodeVisual.dataItem = Object.assign({}, data.nodes[i],
500
527
  {color: nodeOps.color,
501
528
  opacity: nodeOps.opacity,
@@ -526,6 +553,7 @@ export var Sankey = (function (Observable) {
526
553
  target: Object.assign({}, targetNode.dataItem),
527
554
  value: link.value
528
555
  };
556
+ linkVisual.linkOptions = linkOps;
529
557
  linksVisuals.push(linkVisual);
530
558
 
531
559
  sourceNode.links.push(linkVisual);
@@ -546,7 +574,7 @@ export var Sankey = (function (Observable) {
546
574
  });
547
575
 
548
576
  if (legendBox) {
549
- var legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes: nodes, colors: nodesColors}));
577
+ var legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes: nodes}));
550
578
  var legendVisual = legendElement.exportVisual();
551
579
  visual.append(legendVisual);
552
580
  }
@@ -612,7 +640,7 @@ setDefaultOptions(Sankey, {
612
640
  inactiveOpacity: 0.2
613
641
  }
614
642
  },
615
- tooltips: {
643
+ tooltip: {
616
644
  followPointer: false,
617
645
  delay: 1000
618
646
  }
@@ -55,9 +55,14 @@ class Sankey {
55
55
  const { nodes, links } = this.data;
56
56
  this.connectLinksToNodes(nodes, links);
57
57
  this.calculateNodeValues(nodes);
58
- this.calculateNodeDepths(nodes);
59
- this.calculateNodeHeights(nodes);
60
58
 
59
+ const circularLinks = this.calculateNodeHeights(nodes);
60
+
61
+ if (circularLinks) {
62
+ return { nodes: [], links: [], columns: [], circularLinks };
63
+ }
64
+
65
+ this.calculateNodeDepths(nodes);
61
66
  const columns = this.calculateNodeColumns(nodes);
62
67
  this.calculateNodeBreadths(columns);
63
68
  this.applyNodesOffset(nodes);
@@ -115,21 +120,26 @@ class Sankey {
115
120
  }
116
121
 
117
122
  calculateNodeHeights(nodes) {
123
+ const nodesLength = nodes.length;
118
124
  let current = new Set(nodes);
119
125
  let next = new Set;
120
- let x = 0;
126
+ let currentHeight = 0;
121
127
  const eachNode = (node) => {
122
- node.height = x;
128
+ node.height = currentHeight;
123
129
  node.targetLinks.forEach((link) => {
124
130
  next.add(link.source);
125
131
  });
126
132
  };
127
133
  while (current.size) {
128
134
  current.forEach(eachNode);
129
- x++;
135
+ currentHeight++;
136
+ if (currentHeight > nodesLength) {
137
+ return true;
138
+ }
130
139
  current = next;
131
140
  next = new Set;
132
141
  }
142
+ return false;
133
143
  }
134
144
 
135
145
  calculateNodeColumns(nodes) {
@@ -1,7 +1,6 @@
1
1
  import { default as ChartLegend } from "../chart/legend/legend";
2
2
  import { SankeyElement } from "./element";
3
3
  import { setDefaultOptions } from '../common';
4
- import { nodeColor } from "./node";
5
4
  import { BOTTOM, CENTER, POINTER } from "../common/constants";
6
5
  import { AREA } from "../chart/constants";
7
6
 
@@ -15,16 +14,16 @@ const sortData = (a, b) => {
15
14
  export class Legend extends SankeyElement {
16
15
  getElement() {
17
16
  const options = this.options;
18
- const { drawingRect, nodes = [], colors = [], item } = options;
17
+ const { drawingRect, nodes = [], item } = options;
19
18
 
20
19
  if (options.visible === false || !nodes.length) {
21
20
  return null;
22
21
  }
23
22
 
24
- const data = nodes.map((node, index) => ({
23
+ const data = nodes.map((node) => ({
25
24
  text: (node.label && node.label.text) || '',
26
25
  area: {
27
- background: item.areaBackground !== undefined ? item.areaBackground : nodeColor(node, colors, index),
26
+ background: item.areaBackground !== undefined ? item.areaBackground : node.color,
28
27
  opacity: item.areaOpacity !== undefined ? item.areaOpacity : node.opacity
29
28
  },
30
29
  node: node,
@@ -28,12 +28,12 @@ export class Node extends SankeyElement {
28
28
  }
29
29
  }
30
30
 
31
- export const nodeColor = (node, nodesColors, index) => node.color || nodesColors[index % nodesColors.length];
31
+ const nodeColor = (node, nodeColors, index) => node.color || nodeColors[index % nodeColors.length];
32
32
 
33
- export const resolveNodeOptions = (node, options, nodesColors, index) => {
33
+ export const resolveNodeOptions = (node, options, nodeColors, index) => {
34
34
  const nodeOptions = deepExtend({}, options, options.node);
35
35
  return deepExtend({},
36
- { color: nodeColor(node, nodesColors, index) },
36
+ { color: nodeColor(node, nodeColors, index) },
37
37
  nodeOptions,
38
38
  { node },
39
39
  {
@@ -94,12 +94,19 @@ export class Sankey extends Observable {
94
94
 
95
95
  setLinksOpacity(opacity) {
96
96
  this.linksVisuals.forEach(link => {
97
- this.setOpacity(link, opacity);
97
+ this.setOpacity(link, opacity, link.linkOptions.opacity);
98
98
  });
99
99
  }
100
100
 
101
- setOpacity(link, opacity) {
102
- link.options.set('stroke', Object.assign({}, link.options.stroke, {opacity}));
101
+ setLinksInactivityOpacity(inactiveOpacity) {
102
+ this.linksVisuals.forEach(link => {
103
+ this.setOpacity(link, inactiveOpacity, link.linkOptions.highlight.inactiveOpacity);
104
+ });
105
+ }
106
+
107
+ setOpacity(link, opacity, linkValue) {
108
+ link.options.set('stroke', Object.assign({}, link.options.stroke,
109
+ {opacity: defined(linkValue) ? linkValue : opacity}));
103
110
  }
104
111
 
105
112
  trigger(name, ev) {
@@ -124,8 +131,8 @@ export class Sankey extends Observable {
124
131
 
125
132
  const { highlight } = this.options.links;
126
133
  if (isLink) {
127
- this.setLinksOpacity(highlight.inactiveOpacity);
128
- this.setOpacity(element, highlight.opacity);
134
+ this.setLinksInactivityOpacity(highlight.inactiveOpacity);
135
+ this.setOpacity(element, highlight.opacity, element.linkOptions.highlight.opacity);
129
136
  } else if (isNode) {
130
137
  this.highlightLinks(element, highlight);
131
138
  } else if (isLegendItem) {
@@ -160,12 +167,14 @@ export class Sankey extends Observable {
160
167
  }
161
168
 
162
169
  if (isLink || isNode || isLegendItem) {
163
- this.setLinksOpacity(this.options.links.opacity);
170
+ this.linksVisuals.forEach(link => {
171
+ this.setOpacity(link, this.options.links.opacity, link.linkOptions.opacity);
172
+ });
164
173
  }
165
174
  }
166
175
 
167
176
  _mousemove(ev) {
168
- const { followPointer, delay } = this.options.tooltips;
177
+ const { followPointer, delay } = this.options.tooltip;
169
178
  const element = ev.element;
170
179
  const tooltipElType = element.type;
171
180
 
@@ -221,9 +230,9 @@ export class Sankey extends Observable {
221
230
 
222
231
  highlightLinks(node, highlight) {
223
232
  if (node) {
224
- this.setLinksOpacity(highlight.inactiveOpacity);
233
+ this.setLinksInactivityOpacity(highlight.inactiveOpacity);
225
234
  node.links.forEach(link => {
226
- this.setOpacity(link, highlight.opacity);
235
+ this.setOpacity(link, highlight.opacity, link.linkOptions.highlight.opacity);
227
236
  });
228
237
  }
229
238
  }
@@ -306,7 +315,7 @@ export class Sankey extends Observable {
306
315
  }
307
316
 
308
317
  calculateSankey(calcOptions, sankeyOptions) {
309
- const { title, legend, data, nodes, labels, nodesColors, disableAutoLayout } = sankeyOptions;
318
+ const { title, legend, data, nodes, labels, nodeColors, disableAutoLayout } = sankeyOptions;
310
319
  const autoLayout = !disableAutoLayout;
311
320
 
312
321
  const sankeyBox = new Box(0, 0, calcOptions.width, calcOptions.height);
@@ -346,11 +355,16 @@ export class Sankey extends Observable {
346
355
  }
347
356
  }
348
357
 
349
- const calculatedNodes = calculateSankey(Object.assign({}, calcOptions, {offsetX: 0, offsetY: 0, width: sankeyBox.width(), height: sankeyBox.height()})).nodes;
358
+ const { nodes: calculatedNodes, circularLinks } = calculateSankey(Object.assign({}, calcOptions, {offsetX: 0, offsetY: 0, width: sankeyBox.width(), height: sankeyBox.height()}));
359
+ if (circularLinks) {
360
+ console.warn('Circular links detected. Kendo Sankey diagram does not support circular links.');
361
+ return { sankey: { nodes: [], links: [], circularLinks }, legendBox, titleBox };
362
+ }
363
+
350
364
  const box = new Box();
351
365
 
352
366
  calculatedNodes.forEach((nodeEl, i) => {
353
- const nodeOps = resolveNodeOptions(nodeEl, nodes, nodesColors, i);
367
+ const nodeOps = resolveNodeOptions(nodeEl, nodes, nodeColors, i);
354
368
  const nodeInstance = new Node(nodeOps);
355
369
  box.wrap(rectToBox(nodeInstance.exportVisual().rawBBox()));
356
370
 
@@ -428,7 +442,7 @@ export class Sankey extends Observable {
428
442
  const sankeyOptions = options || this.options;
429
443
  const sankeyContext = context || this;
430
444
 
431
- const { data, labels: labelOptions, nodes: nodesOptions, links: linkOptions, nodesColors, title, legend } = sankeyOptions;
445
+ const { data, labels: labelOptions, nodes: nodesOptions, links: linkOptions, nodeColors, title, legend } = sankeyOptions;
432
446
  const { width, height } = sankeyContext.size;
433
447
 
434
448
  const calcOptions = Object.assign({}, data, {width, height, nodesOptions, title, legend});
@@ -445,17 +459,24 @@ export class Sankey extends Observable {
445
459
  visual.append(titleVisual);
446
460
  }
447
461
 
462
+ if (sankey.circularLinks) {
463
+ return visual;
464
+ }
465
+
448
466
  const visualNodes = new Map();
449
467
  sankeyContext.nodesVisuals = visualNodes;
450
468
 
451
469
  nodes.forEach((node, i) => {
452
- const nodeOps = resolveNodeOptions(node, nodesOptions, nodesColors, i);
470
+ const nodeOps = resolveNodeOptions(node, nodesOptions, nodeColors, i);
453
471
 
454
472
  const nodeInstance = new Node(nodeOps);
455
473
  const nodeVisual = nodeInstance.exportVisual();
456
474
  nodeVisual.links = [];
457
475
  nodeVisual.type = NODE;
458
476
 
477
+ node.color = nodeOps.color;
478
+ node.opacity = nodeOps.opacity;
479
+
459
480
  nodeVisual.dataItem = Object.assign({}, data.nodes[i],
460
481
  {color: nodeOps.color,
461
482
  opacity: nodeOps.opacity,
@@ -485,6 +506,7 @@ export class Sankey extends Observable {
485
506
  target: Object.assign({}, targetNode.dataItem),
486
507
  value: link.value
487
508
  };
509
+ linkVisual.linkOptions = linkOps;
488
510
  linksVisuals.push(linkVisual);
489
511
 
490
512
  sourceNode.links.push(linkVisual);
@@ -505,7 +527,7 @@ export class Sankey extends Observable {
505
527
  });
506
528
 
507
529
  if (legendBox) {
508
- const legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes, colors: nodesColors}));
530
+ const legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes}));
509
531
  const legendVisual = legendElement.exportVisual();
510
532
  visual.append(legendVisual);
511
533
  }
@@ -569,7 +591,7 @@ setDefaultOptions(Sankey, {
569
591
  inactiveOpacity: 0.2
570
592
  }
571
593
  },
572
- tooltips: {
594
+ tooltip: {
573
595
  followPointer: false,
574
596
  delay: 1000
575
597
  }