@progress/kendo-charts 2.4.0-dev.202405290547 → 2.4.0-dev.202406110723

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.
@@ -1,7 +1,9 @@
1
1
  import { drawing as draw } from '@progress/kendo-drawing';
2
2
 
3
3
  import { ChartElement, Box, rectToBox } from '../../core';
4
- import { CENTER, HORIZONTAL, START, VERTICAL } from '../../common/constants';
4
+ import { CENTER, HORIZONTAL, START, END, VERTICAL } from '../../common/constants';
5
+
6
+ var alignItems = function (rtl) { return (rtl ? END : START); };
5
7
 
6
8
  var LegendLayout = (function (ChartElement) {
7
9
  function LegendLayout(options, chartService) {
@@ -25,7 +27,7 @@ var LegendLayout = (function (ChartElement) {
25
27
  lineSpacing: vertical ? options.spacing : 0,
26
28
  orientation: vertical ? VERTICAL : HORIZONTAL,
27
29
  reverse: options.rtl,
28
- alignItems: vertical ? START : CENTER
30
+ alignItems: vertical ? alignItems(options.rtl) : CENTER
29
31
  });
30
32
 
31
33
  for (var idx = 0; idx < children.length; idx++) {
@@ -4,8 +4,11 @@ var OBJECT = "object";
4
4
  var UNDEFINED = "undefined";
5
5
 
6
6
  function deepExtendOne(destination, source) {
7
-
8
7
  for (var property in source) {
8
+ if (property === '__proto__' || property === 'constructor') {
9
+ continue;
10
+ }
11
+
9
12
  var propValue = source[property];
10
13
  var propType = typeof propValue;
11
14
 
@@ -17,7 +20,6 @@ function deepExtendOne(destination, source) {
17
20
  }
18
21
 
19
22
  if (propInit && propInit !== Array) {
20
-
21
23
  if (propValue instanceof Date) {
22
24
  destination[property] = new Date(propValue.getTime());
23
25
  } else if (isFunction(propValue.clone)) {
@@ -49,4 +51,4 @@ export default function deepExtend(destination) {
49
51
  }
50
52
 
51
53
  return destination;
52
- }
54
+ }
@@ -17,10 +17,15 @@ export var Label = (function (SankeyElement) {
17
17
  Label.prototype.getElement = function getElement () {
18
18
  var options = deepExtend({}, this.options, this.options.node.label);
19
19
  var node = options.node;
20
- var totalWidth = options.totalWidth;
21
- var position = options.position;
20
+ var diagramMinX = options.diagramMinX;
21
+ var diagramMaxX = options.diagramMaxX;
22
22
  var text = options.text;
23
23
  var offset = options.offset;
24
+ var rtl = options.rtl;
25
+ var position = options.position;
26
+ if (rtl && position !== INSIDE) {
27
+ position = position === BEFORE ? AFTER : BEFORE;
28
+ }
24
29
 
25
30
  if (!options.visible || !text) {
26
31
  return null;
@@ -28,13 +33,20 @@ export var Label = (function (SankeyElement) {
28
33
 
29
34
  var nodeBox = new Box(node.x0, node.y0, node.x1, node.y1);
30
35
  var visualOptions = this.visualOptions();
36
+ if (rtl && !visualOptions.align) {
37
+ visualOptions.align = 'right';
38
+ }
31
39
  var textbox = new TextBox(text, visualOptions);
32
40
  textbox.reflow(new Box());
33
41
  var textSizeBox = textbox.box;
34
-
35
- var goesOutside = node.x1 + textSizeBox.width() > totalWidth;
36
42
  var textY = nodeBox.center().y - (textSizeBox.height() / 2);
37
- var side = position === BEFORE || (position === INSIDE && goesOutside) ? BEFORE : AFTER;
43
+
44
+ var labelAfterLastNode = node.x1 + textSizeBox.width() > diagramMaxX;
45
+ var labelBeforeFirstNode = node.x0 - textSizeBox.width() < diagramMinX;
46
+ var side = position === BEFORE || (position === INSIDE && labelAfterLastNode) ? BEFORE : AFTER;
47
+ if (rtl) {
48
+ side = position === AFTER || (position === INSIDE && labelBeforeFirstNode) ? AFTER : BEFORE;
49
+ }
38
50
  var textOrigin = [side === BEFORE ? node.x0 - textSizeBox.width() : node.x1, textY];
39
51
 
40
52
  var textRect = new Box(textOrigin[0], textOrigin[1], textOrigin[0] + textSizeBox.width(), textOrigin[1] + textSizeBox.height());
@@ -67,11 +79,13 @@ setDefaultOptions(Label, {
67
79
  position: INSIDE, // inside, before, after
68
80
  });
69
81
 
70
- export var resolveLabelOptions = function (node, options, totalWidth) { return deepExtend({},
82
+ export var resolveLabelOptions = function (node, options, rtl, diagramMinX, diagramMaxX) { return deepExtend({},
71
83
  options,
72
84
  {
73
85
  node: node,
74
- totalWidth: totalWidth,
86
+ diagramMinX: diagramMinX,
87
+ diagramMaxX: diagramMaxX,
88
+ rtl: rtl,
75
89
  visual: node.label.visual,
76
90
  visible: node.label.visible,
77
91
  margin: node.label.margin,
@@ -1,7 +1,7 @@
1
1
  import { default as ChartLegend } from "../chart/legend/legend";
2
2
  import { SankeyElement } from "./element";
3
3
  import { setDefaultOptions } from '../common';
4
- import { BOTTOM, CENTER, POINTER } from "../common/constants";
4
+ import { BOTTOM, CENTER, LEFT, POINTER, RIGHT } from "../common/constants";
5
5
  import { AREA } from "../chart/constants";
6
6
 
7
7
  var sortData = function (a, b) {
@@ -11,6 +11,15 @@ var sortData = function (a, b) {
11
11
  return a.node.y0 - b.node.y0;
12
12
  };
13
13
 
14
+ var sortDataRTL = function (a, b) {
15
+ if (a.node.x1 - b.node.x1 !== 0) {
16
+ return a.node.x1 - b.node.x1;
17
+ }
18
+ return b.node.y0 - a.node.y0;
19
+ };
20
+
21
+ var sort = function (rtl) { return (rtl ? sortDataRTL : sortData); };
22
+
14
23
  export var Legend = (function (SankeyElement) {
15
24
  function Legend () {
16
25
  SankeyElement.apply(this, arguments);
@@ -23,8 +32,10 @@ export var Legend = (function (SankeyElement) {
23
32
  Legend.prototype.getElement = function getElement () {
24
33
  var options = this.options;
25
34
  var drawingRect = options.drawingRect;
35
+ var rtl = options.rtl;
26
36
  var nodes = options.nodes; if ( nodes === void 0 ) nodes = [];
27
37
  var item = options.item;
38
+ var position = options.position;
28
39
 
29
40
  if (options.visible === false || !nodes.length) {
30
41
  return null;
@@ -36,12 +47,13 @@ export var Legend = (function (SankeyElement) {
36
47
  background: item.areaBackground !== undefined ? item.areaBackground : node.color,
37
48
  opacity: item.areaOpacity !== undefined ? item.areaOpacity : node.opacity
38
49
  },
39
- node: node,
50
+ node: node
40
51
  }); });
41
52
 
42
- data.sort(sortData);
53
+ data.sort(sort(rtl));
43
54
 
44
- var legend = new ChartLegend(Object.assign({}, options, {data: data}));
55
+ var reverse = rtl && position !== LEFT && position !== RIGHT;
56
+ var legend = new ChartLegend(Object.assign({}, options, {data: data, reverse: reverse}), { rtl: rtl });
45
57
  legend.reflow(drawingRect);
46
58
 
47
59
  legend.renderVisual();
@@ -44,7 +44,7 @@ var angelBetweenTwoLines = function (line1, line2) {
44
44
  return Math.abs(a1 - a2);
45
45
  };
46
46
 
47
- var calculateControlPointsOffsetX = function (link) {
47
+ var calculateControlPointsOffsetX = function (link, rtl) {
48
48
  var x0 = link.x0;
49
49
  var x1 = link.x1;
50
50
  var y0 = link.y0;
@@ -76,7 +76,12 @@ var calculateControlPointsOffsetX = function (link) {
76
76
  // Another option is to assume the triangle is isosceles
77
77
  // => offset = Math.sqrt(2) * upperNarrowness;
78
78
 
79
- return y0 - y1 > 0 ? (-1) * offset : offset;
79
+ var sign = y0 - y1 > 0 ? (-1) : 1;
80
+ if (rtl) {
81
+ sign = -sign;
82
+ }
83
+
84
+ return sign * offset;
80
85
  };
81
86
 
82
87
  export var Link = (function (SankeyElement) {
@@ -129,7 +134,9 @@ export var Link = (function (SankeyElement) {
129
134
  if (!this.options.navigatable) {
130
135
  return;
131
136
  }
132
- var link = this.options.link;
137
+ var ref = this.options;
138
+ var link = ref.link;
139
+ var rtl = ref.rtl;
133
140
  var x0 = link.x0;
134
141
  var x1 = link.x1;
135
142
  var y0 = link.y0;
@@ -137,7 +144,7 @@ export var Link = (function (SankeyElement) {
137
144
  var xC = (x0 + x1) / 2;
138
145
  var halfWidth = link.width / 2;
139
146
 
140
- var offset = calculateControlPointsOffsetX(link);
147
+ var offset = calculateControlPointsOffsetX(link, rtl);
141
148
 
142
149
  this._highlight = new drawing.Path({ stroke: this.options.focusHighlight, visible: false })
143
150
  .moveTo(x0, y0 + halfWidth)
@@ -13,6 +13,28 @@ import { defined } from '../drawing-utils';
13
13
  var LINK = 'link';
14
14
  var NODE = 'node';
15
15
 
16
+ var toRtl = function (sankey) {
17
+ var nodes = sankey.nodes;
18
+ var links = sankey.links;
19
+ var startX = Math.min.apply(Math, nodes.map(function (node) { return node.x0; }));
20
+ var endX = Math.max.apply(Math, nodes.map(function (node) { return node.x1; }));
21
+ var width = endX - startX;
22
+
23
+ nodes.forEach(function (node) {
24
+ var x0 = width - (node.x1 - 2 * startX);
25
+ var x1 = width - (node.x0 - 2 * startX);
26
+ node.x0 = x0;
27
+ node.x1 = x1;
28
+ });
29
+
30
+ links.forEach(function (link) {
31
+ var x0 = width - (link.x1 - 2 * startX);
32
+ var x1 = width - (link.x0 - 2 * startX);
33
+ link.x1 = x0;
34
+ link.x0 = x1;
35
+ });
36
+ };
37
+
16
38
  export var Sankey = (function (Observable) {
17
39
  function Sankey(element, options, theme) {
18
40
  Observable.call(this);
@@ -96,11 +118,15 @@ export var Sankey = (function (Observable) {
96
118
  element.addEventListener('pointerdown', this._onDownHandler);
97
119
 
98
120
  this._focusState = {
99
- node: this.columns[0][0],
121
+ node: this.firstFocusableNode(),
100
122
  link: null
101
123
  };
102
124
  };
103
125
 
126
+ Sankey.prototype.firstFocusableNode = function firstFocusableNode () {
127
+ return this.columns[0][0];
128
+ };
129
+
104
130
  Sankey.prototype._initResizeObserver = function _initResizeObserver () {
105
131
  var this$1 = this;
106
132
 
@@ -160,10 +186,13 @@ export var Sankey = (function (Observable) {
160
186
  };
161
187
 
162
188
  Sankey.prototype.trigger = function trigger (name, ev) {
189
+ var dataItem = ev.element.dataItem;
190
+ var targetType = ev.element.type;
191
+
163
192
  var event = Object.assign({}, ev,
164
193
  {type: name,
165
- targetType: ev.element.type,
166
- dataItem: ev.element.dataItem});
194
+ targetType: targetType,
195
+ dataItem: dataItem});
167
196
 
168
197
  return Observable.prototype.trigger.call(this, name, event);
169
198
  };
@@ -443,6 +472,13 @@ export var Sankey = (function (Observable) {
443
472
 
444
473
  Sankey.prototype._keydown = function _keydown (ev) {
445
474
  var handler = this['on' + ev.key];
475
+ var rtl = this.options.rtl;
476
+
477
+ if (rtl && ev.key === 'ArrowLeft') {
478
+ handler = this.onArrowRight;
479
+ } else if (rtl && ev.key === 'ArrowRight') {
480
+ handler = this.onArrowLeft;
481
+ }
446
482
 
447
483
  if (handler) {
448
484
  handler.call(this, ev);
@@ -452,7 +488,7 @@ export var Sankey = (function (Observable) {
452
488
  Sankey.prototype.onEscape = function onEscape (ev) {
453
489
  ev.preventDefault();
454
490
 
455
- this._focusState = { node: this.columns[0][0], link: null };
491
+ this._focusState = { node: this.firstFocusableNode(), link: null };
456
492
  this._focusNode();
457
493
  };
458
494
 
@@ -595,6 +631,7 @@ export var Sankey = (function (Observable) {
595
631
  var nodeColors = sankeyOptions.nodeColors;
596
632
  var disableAutoLayout = sankeyOptions.disableAutoLayout;
597
633
  var disableKeyboardNavigation = sankeyOptions.disableKeyboardNavigation;
634
+ var rtl = sankeyOptions.rtl;
598
635
  var autoLayout = !disableAutoLayout;
599
636
  var padding = disableKeyboardNavigation ? 0 : highlightOptions.width / 2;
600
637
 
@@ -647,12 +684,21 @@ export var Sankey = (function (Observable) {
647
684
 
648
685
  var box = new Box();
649
686
 
687
+ var diagramMinX = calculatedNodes.reduce(function (acc, node) { return Math.min(acc, node.x0); }, Infinity);
688
+ var diagramMaxX = calculatedNodes.reduce(function (acc, node) { return Math.max(acc, node.x1); }, 0);
689
+
650
690
  calculatedNodes.forEach(function (nodeEl, i) {
691
+ if (rtl) {
692
+ var x0 = nodeEl.x0;
693
+ var x1 = nodeEl.x1;
694
+ nodeEl.x0 = diagramMaxX - x1;
695
+ nodeEl.x1 = diagramMaxX - x0;
696
+ }
651
697
  var nodeOps = resolveNodeOptions(nodeEl, nodes, nodeColors, i);
652
698
  var nodeInstance = new Node(nodeOps);
653
699
  box.wrap(rectToBox(nodeInstance.exportVisual().rawBBox()));
654
700
 
655
- var labelInstance = new Label(resolveLabelOptions(nodeEl, labels, sankeyBox.width()));
701
+ var labelInstance = new Label(resolveLabelOptions(nodeEl, labels, rtl, diagramMinX, diagramMaxX));
656
702
  var labelVisual = labelInstance.exportVisual();
657
703
  if (labelVisual) {
658
704
  box.wrap(rectToBox(labelVisual.rawBBox()));
@@ -726,14 +772,15 @@ export var Sankey = (function (Observable) {
726
772
  var sankeyOptions = options || this.options;
727
773
  var sankeyContext = context || this;
728
774
 
729
- var data = sankeyOptions.data;
730
775
  var labelOptions = sankeyOptions.labels;
731
776
  var nodesOptions = sankeyOptions.nodes;
732
777
  var linkOptions = sankeyOptions.links;
733
778
  var nodeColors = sankeyOptions.nodeColors;
734
779
  var title = sankeyOptions.title;
735
780
  var legend = sankeyOptions.legend;
781
+ var rtl = sankeyOptions.rtl;
736
782
  var disableKeyboardNavigation = sankeyOptions.disableKeyboardNavigation;
783
+ var data = sankeyOptions.data;
737
784
  var ref = sankeyContext.size;
738
785
  var width = ref.width;
739
786
  var height = ref.height;
@@ -743,6 +790,9 @@ export var Sankey = (function (Observable) {
743
790
  var sankey = ref$1.sankey;
744
791
  var titleBox = ref$1.titleBox;
745
792
  var legendBox = ref$1.legendBox;
793
+ if (rtl) {
794
+ toRtl(sankey);
795
+ }
746
796
  var nodes = sankey.nodes;
747
797
  var links = sankey.links;
748
798
  var columns = sankey.columns;
@@ -821,10 +871,11 @@ export var Sankey = (function (Observable) {
821
871
  var target = link.target;
822
872
  var sourceNode = visualNodes.get(source.id);
823
873
  var targetNode = visualNodes.get(target.id);
824
- var linkOps = resolveLinkOptions(link, linkOptions, sourceNode, targetNode);
825
- linkOps.root = function () { return sankeyContext.element; };
826
- linkOps.navigatable = disableKeyboardNavigation !== true;
827
- var linkInstance = new Link(linkOps);
874
+ var resolvedOptions = resolveLinkOptions(link, linkOptions, sourceNode, targetNode);
875
+ resolvedOptions.root = function () { return sankeyContext.element; };
876
+ resolvedOptions.navigatable = disableKeyboardNavigation !== true;
877
+ resolvedOptions.rtl = rtl;
878
+ var linkInstance = new Link(resolvedOptions);
828
879
  var linkVisual = linkInstance.exportVisual();
829
880
 
830
881
  linkVisual.type = LINK;
@@ -833,7 +884,7 @@ export var Sankey = (function (Observable) {
833
884
  target: Object.assign({}, targetNode.dataItem),
834
885
  value: link.value
835
886
  };
836
- linkVisual.linkOptions = linkOps;
887
+ linkVisual.linkOptions = resolvedOptions;
837
888
  linksVisuals.push(linkVisual);
838
889
 
839
890
  sourceNode.links.push(linkVisual);
@@ -851,9 +902,11 @@ export var Sankey = (function (Observable) {
851
902
  visual.append(linkVisual);
852
903
  });
853
904
 
854
- var diagramWidth = nodes.reduce(function (acc, node) { return Math.max(acc, node.x1); }, 0);
905
+ var diagramMinX = nodes.reduce(function (acc, node) { return Math.min(acc, node.x0); }, Infinity);
906
+ var diagramMaxX = nodes.reduce(function (acc, node) { return Math.max(acc, node.x1); }, 0);
907
+
855
908
  nodes.forEach(function (node) {
856
- var textOps = resolveLabelOptions(node, labelOptions, diagramWidth);
909
+ var textOps = resolveLabelOptions(node, labelOptions, rtl, diagramMinX, diagramMaxX);
857
910
  var labelInstance = new Label(textOps);
858
911
  var labelVisual = labelInstance.exportVisual();
859
912
 
@@ -863,7 +916,7 @@ export var Sankey = (function (Observable) {
863
916
  });
864
917
 
865
918
  if (legendBox) {
866
- var legendElement = new Legend(Object.assign({}, legend, {drawingRect: legendBox, nodes: nodes}));
919
+ var legendElement = new Legend(Object.assign({}, legend, {rtl: rtl, drawingRect: legendBox, nodes: nodes}));
867
920
  var legendVisual = legendElement.exportVisual();
868
921
  visual.append(legendVisual);
869
922
  }
@@ -923,7 +976,6 @@ setDefaultOptions(Sankey, {
923
976
  lineJoin: "round",
924
977
  width: 1
925
978
  },
926
- align: LEFT,
927
979
  offset: { left: 0, top: 0 }
928
980
  },
929
981
  nodes: {
@@ -1,7 +1,9 @@
1
1
  import { drawing as draw } from '@progress/kendo-drawing';
2
2
 
3
3
  import { ChartElement, Box, rectToBox } from '../../core';
4
- import { CENTER, HORIZONTAL, START, VERTICAL } from '../../common/constants';
4
+ import { CENTER, HORIZONTAL, START, END, VERTICAL } from '../../common/constants';
5
+
6
+ const alignItems = rtl => (rtl ? END : START);
5
7
 
6
8
  class LegendLayout extends ChartElement {
7
9
 
@@ -20,7 +22,7 @@ class LegendLayout extends ChartElement {
20
22
  lineSpacing: vertical ? options.spacing : 0,
21
23
  orientation: vertical ? VERTICAL : HORIZONTAL,
22
24
  reverse: options.rtl,
23
- alignItems: vertical ? START : CENTER
25
+ alignItems: vertical ? alignItems(options.rtl) : CENTER
24
26
  });
25
27
 
26
28
  for (let idx = 0; idx < children.length; idx++) {
@@ -4,8 +4,11 @@ const OBJECT = "object";
4
4
  const UNDEFINED = "undefined";
5
5
 
6
6
  function deepExtendOne(destination, source) {
7
-
8
7
  for (let property in source) {
8
+ if (property === '__proto__' || property === 'constructor') {
9
+ continue;
10
+ }
11
+
9
12
  let propValue = source[property];
10
13
  let propType = typeof propValue;
11
14
 
@@ -17,7 +20,6 @@ function deepExtendOne(destination, source) {
17
20
  }
18
21
 
19
22
  if (propInit && propInit !== Array) {
20
-
21
23
  if (propValue instanceof Date) {
22
24
  destination[property] = new Date(propValue.getTime());
23
25
  } else if (isFunction(propValue.clone)) {
@@ -47,4 +49,4 @@ export default function deepExtend(destination) {
47
49
  }
48
50
 
49
51
  return destination;
50
- }
52
+ }
@@ -8,7 +8,11 @@ const AFTER = 'after';
8
8
  export class Label extends SankeyElement {
9
9
  getElement() {
10
10
  const options = deepExtend({}, this.options, this.options.node.label);
11
- const { node, totalWidth, position, text, offset } = options;
11
+ const { node, diagramMinX, diagramMaxX, text, offset, rtl } = options;
12
+ let position = options.position;
13
+ if (rtl && position !== INSIDE) {
14
+ position = position === BEFORE ? AFTER : BEFORE;
15
+ }
12
16
 
13
17
  if (!options.visible || !text) {
14
18
  return null;
@@ -16,13 +20,20 @@ export class Label extends SankeyElement {
16
20
 
17
21
  const nodeBox = new Box(node.x0, node.y0, node.x1, node.y1);
18
22
  const visualOptions = this.visualOptions();
23
+ if (rtl && !visualOptions.align) {
24
+ visualOptions.align = 'right';
25
+ }
19
26
  const textbox = new TextBox(text, visualOptions);
20
27
  textbox.reflow(new Box());
21
28
  const textSizeBox = textbox.box;
22
-
23
- const goesOutside = node.x1 + textSizeBox.width() > totalWidth;
24
29
  const textY = nodeBox.center().y - (textSizeBox.height() / 2);
25
- const side = position === BEFORE || (position === INSIDE && goesOutside) ? BEFORE : AFTER;
30
+
31
+ const labelAfterLastNode = node.x1 + textSizeBox.width() > diagramMaxX;
32
+ const labelBeforeFirstNode = node.x0 - textSizeBox.width() < diagramMinX;
33
+ let side = position === BEFORE || (position === INSIDE && labelAfterLastNode) ? BEFORE : AFTER;
34
+ if (rtl) {
35
+ side = position === AFTER || (position === INSIDE && labelBeforeFirstNode) ? AFTER : BEFORE;
36
+ }
26
37
  const textOrigin = [side === BEFORE ? node.x0 - textSizeBox.width() : node.x1, textY];
27
38
 
28
39
  const textRect = new Box(textOrigin[0], textOrigin[1], textOrigin[0] + textSizeBox.width(), textOrigin[1] + textSizeBox.height());
@@ -53,11 +64,13 @@ setDefaultOptions(Label, {
53
64
  position: INSIDE, // inside, before, after
54
65
  });
55
66
 
56
- export const resolveLabelOptions = (node, options, totalWidth) => deepExtend({},
67
+ export const resolveLabelOptions = (node, options, rtl, diagramMinX, diagramMaxX) => deepExtend({},
57
68
  options,
58
69
  {
59
70
  node,
60
- totalWidth,
71
+ diagramMinX,
72
+ diagramMaxX,
73
+ rtl,
61
74
  visual: node.label.visual,
62
75
  visible: node.label.visible,
63
76
  margin: node.label.margin,
@@ -1,7 +1,7 @@
1
1
  import { default as ChartLegend } from "../chart/legend/legend";
2
2
  import { SankeyElement } from "./element";
3
3
  import { setDefaultOptions } from '../common';
4
- import { BOTTOM, CENTER, POINTER } from "../common/constants";
4
+ import { BOTTOM, CENTER, LEFT, POINTER, RIGHT } from "../common/constants";
5
5
  import { AREA } from "../chart/constants";
6
6
 
7
7
  const sortData = (a, b) => {
@@ -11,10 +11,19 @@ const sortData = (a, b) => {
11
11
  return a.node.y0 - b.node.y0;
12
12
  };
13
13
 
14
+ const sortDataRTL = (a, b) => {
15
+ if (a.node.x1 - b.node.x1 !== 0) {
16
+ return a.node.x1 - b.node.x1;
17
+ }
18
+ return b.node.y0 - a.node.y0;
19
+ };
20
+
21
+ const sort = (rtl) => (rtl ? sortDataRTL : sortData);
22
+
14
23
  export class Legend extends SankeyElement {
15
24
  getElement() {
16
25
  const options = this.options;
17
- const { drawingRect, nodes = [], item } = options;
26
+ const { drawingRect, rtl, nodes = [], item, position } = options;
18
27
 
19
28
  if (options.visible === false || !nodes.length) {
20
29
  return null;
@@ -26,12 +35,13 @@ export class Legend extends SankeyElement {
26
35
  background: item.areaBackground !== undefined ? item.areaBackground : node.color,
27
36
  opacity: item.areaOpacity !== undefined ? item.areaOpacity : node.opacity
28
37
  },
29
- node: node,
38
+ node: node
30
39
  }));
31
40
 
32
- data.sort(sortData);
41
+ data.sort(sort(rtl));
33
42
 
34
- const legend = new ChartLegend(Object.assign({}, options, {data}));
43
+ const reverse = rtl && position !== LEFT && position !== RIGHT;
44
+ const legend = new ChartLegend(Object.assign({}, options, {data, reverse}), { rtl });
35
45
  legend.reflow(drawingRect);
36
46
 
37
47
  legend.renderVisual();
@@ -31,7 +31,7 @@ const angelBetweenTwoLines = (line1, line2) => {
31
31
  return Math.abs(a1 - a2);
32
32
  };
33
33
 
34
- const calculateControlPointsOffsetX = (link) => {
34
+ const calculateControlPointsOffsetX = (link, rtl) => {
35
35
  const { x0, x1, y0, y1 } = link;
36
36
  let xC = (x0 + x1) / 2;
37
37
 
@@ -60,7 +60,12 @@ const calculateControlPointsOffsetX = (link) => {
60
60
  // Another option is to assume the triangle is isosceles
61
61
  // => offset = Math.sqrt(2) * upperNarrowness;
62
62
 
63
- return y0 - y1 > 0 ? (-1) * offset : offset;
63
+ let sign = y0 - y1 > 0 ? (-1) : 1;
64
+ if (rtl) {
65
+ sign = -sign;
66
+ }
67
+
68
+ return sign * offset;
64
69
  };
65
70
 
66
71
  export class Link extends SankeyElement {
@@ -102,12 +107,12 @@ export class Link extends SankeyElement {
102
107
  if (!this.options.navigatable) {
103
108
  return;
104
109
  }
105
- const link = this.options.link;
110
+ const { link, rtl } = this.options;
106
111
  const { x0, x1, y0, y1 } = link;
107
112
  const xC = (x0 + x1) / 2;
108
113
  const halfWidth = link.width / 2;
109
114
 
110
- const offset = calculateControlPointsOffsetX(link);
115
+ const offset = calculateControlPointsOffsetX(link, rtl);
111
116
 
112
117
  this._highlight = new drawing.Path({ stroke: this.options.focusHighlight, visible: false })
113
118
  .moveTo(x0, y0 + halfWidth)