@progress/kendo-charts 2.6.2 → 2.6.3-dev.202411211546

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.
@@ -25,7 +25,14 @@ var BaseTooltip = (function (Class) {
25
25
  border = valueOrDefault(border, pointColor);
26
26
  }
27
27
 
28
- var padding = getSpacing(options.padding || {}, "auto");
28
+ var padding = options.padding !== undefined ? getSpacing(options.padding) : {};
29
+
30
+ if (typeof options.padding === "object") {
31
+ padding.top = options.padding.top !== undefined ? padding.top : undefined;
32
+ padding.right = options.padding.right !== undefined ? padding.right : undefined;
33
+ padding.bottom = options.padding.bottom !== undefined ? padding.bottom : undefined;
34
+ padding.left = options.padding.left !== undefined ? padding.left : undefined;
35
+ }
29
36
 
30
37
  return {
31
38
  backgroundColor: background,
@@ -1,22 +1,10 @@
1
+ /* eslint-disable camelcase */
1
2
  import { drawing } from '@progress/kendo-drawing';
2
3
  import { SankeyElement } from './element';
3
4
  import { deepExtend } from '../common';
4
5
  import { defined } from '../drawing-utils';
5
6
  import { ARIA_ACTIVE_DESCENDANT } from '../common/constants';
6
7
 
7
- var distanceToLine = function (line, point) {
8
- var ref = line[0];
9
- var x1 = ref[0];
10
- var y1 = ref[1];
11
- var ref$1 = line[1];
12
- var x2 = ref$1[0];
13
- var y2 = ref$1[1];
14
- var x3 = point[0];
15
- var y3 = point[1];
16
-
17
- return Math.abs((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) / Math.sqrt(Math.pow( (x2 - x1), 2 ) + Math.pow( (y2 - y1), 2 ));
18
- };
19
-
20
8
  var bezierPoint = function (p1, p2, p3, p4, t) {
21
9
  var t1 = 1 - t;
22
10
  var t1t1 = t1 * t1;
@@ -24,64 +12,131 @@ var bezierPoint = function (p1, p2, p3, p4, t) {
24
12
  return (p1 * t1t1 * t1) + (3 * p2 * t * t1t1) + (3 * p3 * tt * t1) + (p4 * tt * t);
25
13
  };
26
14
 
27
- var angelBetweenTwoLines = function (line1, line2) {
28
- var ref = line1[0];
29
- var x1 = ref[0];
30
- var y1 = ref[1];
31
- var ref$1 = line1[1];
32
- var x2 = ref$1[0];
33
- var y2 = ref$1[1];
34
- var ref$2 = line2[0];
35
- var x3 = ref$2[0];
36
- var y3 = ref$2[1];
37
- var ref$3 = line2[1];
38
- var x4 = ref$3[0];
39
- var y4 = ref$3[1];
40
-
41
- var a1 = Math.atan2(y2 - y1, x2 - x1);
42
- var a2 = Math.atan2(y4 - y3, x4 - x3);
43
-
44
- return Math.abs(a1 - a2);
45
- };
15
+ function calculatePerpendicularLine(x1, y1, x2, y2, L) {
16
+ // 1. Calculate the midpoint M
17
+ var xM = (x1 + x2) / 2;
18
+ var yM = (y1 + y2) / 2;
19
+
20
+ var dx, dy;
21
+ if (y1 === y2) {
22
+ // The line AB is horizontal
23
+ dx = 0;
24
+ dy = L / 2;
25
+ } else if (x1 === x2) {
26
+ // The line AB is vertical
27
+ dx = L / 2;
28
+ dy = 0;
29
+ } else {
30
+ // Common case when the line is not horizontal or vertical
31
+ // 2. Calculate the slope of the original line
32
+ var m = (y2 - y1) / (x2 - x1);
33
+
34
+ // 3. Calculate the slope of the perpendicular line
35
+ var mPerp = -1 / m;
36
+
37
+ // 4. Calculate dx and dy
38
+ dx = (L / 2) / Math.sqrt(1 + mPerp * mPerp);
39
+ dy = mPerp * dx;
40
+ }
46
41
 
47
- var calculateControlPointsOffsetX = function (link, rtl) {
48
- var x0 = link.x0;
49
- var x1 = link.x1;
50
- var y0 = link.y0;
51
- var y1 = link.y1;
52
- var xC = (x0 + x1) / 2;
42
+ // 5. Coordinates of the points of the perpendicular line
43
+ var P1 = { x: xM - dx, y: yM - dy };
44
+ var P2 = { x: xM + dx, y: yM + dy };
53
45
 
54
- var width = link.width;
55
- var halfWidth = width / 2;
46
+ return { P1: P1, P2: P2 };
47
+ }
56
48
 
57
- // upper curve, t = 0.5
58
- var upperCurveMiddleLine = [[(x0 + xC) / 2, y0 - halfWidth], [(x1 + xC) / 2, y1 - halfWidth]];
49
+ function findIntersection(a, b, L, p, q) {
50
+ // Midpoint between a and b
51
+ var midpoint = {
52
+ x: (a.x + b.x) / 2,
53
+ y: (a.y + b.y) / 2
54
+ };
55
+
56
+ // Vector of the line ab
57
+ var ab_dx = b.x - a.x;
58
+ var ab_dy = b.y - a.y;
59
+
60
+ // Vector, perpendicular to ab
61
+ var perp_dx = -ab_dy;
62
+ var perp_dy = ab_dx;
63
+
64
+ // Normalize the perpendicular vector and scale it to 2*L
65
+ var magnitude = Math.sqrt(perp_dx * perp_dx + perp_dy * perp_dy);
66
+ perp_dx = (perp_dx / magnitude) * L;
67
+ perp_dy = (perp_dy / magnitude) * L;
68
+
69
+ // The endpoints of the perpendicular, 2*L long
70
+ var c1 = {
71
+ x: midpoint.x + perp_dx,
72
+ y: midpoint.y + perp_dy
73
+ };
74
+ var c2 = {
75
+ x: midpoint.x - perp_dx,
76
+ y: midpoint.y - perp_dy
77
+ };
59
78
 
60
- // for lower curve, bezier-point at t = 0.5
61
- // for the case t = 0.5, the bezier-point is the middle point of the curve. => ((y0 + halfWidth) + (y1 + halfWidth)) / 2
62
- var lowerCurveMiddlePoint = [xC, bezierPoint(y0 + halfWidth, y0 + halfWidth, y1 + halfWidth, y1 + halfWidth, 0.5)];
79
+ // Check for intersection of the lines pq and the perpendicular
80
+ var pq_dx = q.x - p.x;
81
+ var pq_dy = q.y - p.y;
63
82
 
64
- // The actual width of the link at its middle point as can be seen on the screen.
65
- var actualWidth = distanceToLine(upperCurveMiddleLine, lowerCurveMiddlePoint);
83
+ var denominator = (pq_dy) * (c1.x - c2.x) - (pq_dx) * (c1.y - c2.y);
66
84
 
67
- var upperNarrowness = (width - actualWidth) / 2;
85
+ if (Math.abs(denominator) < 1e-10) {
86
+ // The lines are almost parallel, no intersection
87
+ return null;
88
+ }
68
89
 
69
- // The line `upperCurveMiddleLine` shows the upper border of the link.
70
- // Assumption 1: Translated to the left to the desired link width and the translate value will be the `offset`.
71
- // Assumption 2: The translate value is a hypotenuse of a triangle.
72
- var alpha = angelBetweenTwoLines(upperCurveMiddleLine, [[x0, y0 - halfWidth], [xC, y0 - halfWidth]]);
73
- var a = upperNarrowness;
74
- var b = Math.sin(alpha) * a;
75
- var offset = Math.sqrt(a * a + b * b);
76
- // Another option is to assume the triangle is isosceles
77
- // => offset = Math.sqrt(2) * upperNarrowness;
90
+ var ua = (pq_dx * (c2.y - p.y) - pq_dy * (c2.x - p.x)) / denominator;
91
+ var ub = ((c1.x - c2.x) * (c2.y - p.y) - (c1.y - c2.y) * (c2.x - p.x)) / denominator;
78
92
 
79
- var sign = y0 - y1 > 0 ? (-1) : 1;
80
- if (rtl) {
81
- sign = -sign;
93
+ if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
94
+ var intersection = {
95
+ x: c2.x + ua * (c1.x - c2.x),
96
+ // y: c2.y + ua * (c1.y - c2.y)
97
+ };
98
+ return intersection;
82
99
  }
83
100
 
84
- return sign * offset;
101
+ // No intersection of the segments
102
+ return null;
103
+ }
104
+
105
+ var calculateControlPointsOffsetX = function (link, rtl) {
106
+ var halfWidth = link.width / 2;
107
+ var x0 = rtl ? link.x1 : link.x0;
108
+ var x1 = rtl ? link.x0 : link.x1;
109
+ var y0 = rtl ? link.y1 : link.y0;
110
+ var y1 = rtl ? link.y0 : link.y1;
111
+
112
+ var xC = (x0 + x1) / 2;
113
+ var middlePoint = [xC, bezierPoint(y0, y0, y1, y1, 0.5)];
114
+
115
+ var tH = 0.4999;
116
+
117
+ var pointH = [
118
+ bezierPoint(x0, xC, xC, x1, tH),
119
+ bezierPoint(y0, y0, y1, y1, tH)
120
+ ];
121
+
122
+ var line = calculatePerpendicularLine(middlePoint[0], middlePoint[1], pointH[0], pointH[1], link.width);
123
+
124
+ var middlePointDown = [xC, bezierPoint(y0 + halfWidth, y0 + halfWidth, y1 + halfWidth, y1 + halfWidth, 0.5)];
125
+ // const middlePointUp = [xC, bezierPoint(y0 - halfWidth, y0 - halfWidth, y1 - halfWidth, y1 - halfWidth, 0.5)];
126
+
127
+ var P = line.P1.y > line.P2.y ? line.P1 : line.P2;
128
+ var L = halfWidth;
129
+ var LDir = (y0 > y1 ? 1 : -1) * L;
130
+ var a = P;
131
+ var b = { x: middlePointDown[0], y: middlePointDown[1] };
132
+ var p = { x: middlePointDown[0], y: middlePointDown[1] };
133
+ var q = { x: Math.max(1, middlePointDown[0] + LDir), y: middlePointDown[1] };
134
+ var Pmx = findIntersection(a, b, L, p, q) || { x: (middlePointDown[0] + P.x) / 2 };
135
+ var P1 = x0;
136
+ var P4 = x1;
137
+ var P2 = (Pmx.x - (0.125 * P1) - (0.125 * P4)) / 0.75;
138
+
139
+ return xC - P2;
85
140
  };
86
141
 
87
142
  export var Link = (function (SankeyElement) {
@@ -134,9 +189,9 @@ export var Link = (function (SankeyElement) {
134
189
  if (!this.options.navigatable) {
135
190
  return;
136
191
  }
192
+
137
193
  var ref = this.options;
138
194
  var link = ref.link;
139
- var rtl = ref.rtl;
140
195
  var x0 = link.x0;
141
196
  var x1 = link.x1;
142
197
  var y0 = link.y0;
@@ -144,7 +199,7 @@ export var Link = (function (SankeyElement) {
144
199
  var xC = (x0 + x1) / 2;
145
200
  var halfWidth = link.width / 2;
146
201
 
147
- var offset = calculateControlPointsOffsetX(link, rtl);
202
+ var offset = calculateControlPointsOffsetX(link, this.options.rtl);
148
203
 
149
204
  this._highlight = new drawing.Path({ stroke: this.options.focusHighlight, visible: false })
150
205
  .moveTo(x0, y0 + halfWidth)
@@ -20,7 +20,14 @@ class BaseTooltip extends Class {
20
20
  border = valueOrDefault(border, pointColor);
21
21
  }
22
22
 
23
- const padding = getSpacing(options.padding || {}, "auto");
23
+ const padding = options.padding !== undefined ? getSpacing(options.padding) : {};
24
+
25
+ if (typeof options.padding === "object") {
26
+ padding.top = options.padding.top !== undefined ? padding.top : undefined;
27
+ padding.right = options.padding.right !== undefined ? padding.right : undefined;
28
+ padding.bottom = options.padding.bottom !== undefined ? padding.bottom : undefined;
29
+ padding.left = options.padding.left !== undefined ? padding.left : undefined;
30
+ }
24
31
 
25
32
  return {
26
33
  backgroundColor: background,
@@ -1,17 +1,10 @@
1
+ /* eslint-disable camelcase */
1
2
  import { drawing } from '@progress/kendo-drawing';
2
3
  import { SankeyElement } from './element';
3
4
  import { deepExtend } from '../common';
4
5
  import { defined } from '../drawing-utils';
5
6
  import { ARIA_ACTIVE_DESCENDANT } from '../common/constants';
6
7
 
7
- const distanceToLine = (line, point) => {
8
- const [x1, y1] = line[0];
9
- const [x2, y2] = line[1];
10
- const [x3, y3] = point;
11
-
12
- return Math.abs((x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)) / Math.sqrt(Math.pow( (x2 - x1), 2 ) + Math.pow( (y2 - y1), 2 ));
13
- };
14
-
15
8
  const bezierPoint = (p1, p2, p3, p4, t) => {
16
9
  const t1 = 1 - t;
17
10
  const t1t1 = t1 * t1;
@@ -19,53 +12,131 @@ const bezierPoint = (p1, p2, p3, p4, t) => {
19
12
  return (p1 * t1t1 * t1) + (3 * p2 * t * t1t1) + (3 * p3 * tt * t1) + (p4 * tt * t);
20
13
  };
21
14
 
22
- const angelBetweenTwoLines = (line1, line2) => {
23
- const [x1, y1] = line1[0];
24
- const [x2, y2] = line1[1];
25
- const [x3, y3] = line2[0];
26
- const [x4, y4] = line2[1];
27
-
28
- const a1 = Math.atan2(y2 - y1, x2 - x1);
29
- const a2 = Math.atan2(y4 - y3, x4 - x3);
30
-
31
- return Math.abs(a1 - a2);
32
- };
33
-
34
- const calculateControlPointsOffsetX = (link, rtl) => {
35
- const { x0, x1, y0, y1 } = link;
36
- let xC = (x0 + x1) / 2;
37
-
38
- const width = link.width;
39
- const halfWidth = width / 2;
40
-
41
- // upper curve, t = 0.5
42
- const upperCurveMiddleLine = [[(x0 + xC) / 2, y0 - halfWidth], [(x1 + xC) / 2, y1 - halfWidth]];
15
+ function calculatePerpendicularLine(x1, y1, x2, y2, L) {
16
+ // 1. Calculate the midpoint M
17
+ let xM = (x1 + x2) / 2;
18
+ let yM = (y1 + y2) / 2;
19
+
20
+ let dx, dy;
21
+ if (y1 === y2) {
22
+ // The line AB is horizontal
23
+ dx = 0;
24
+ dy = L / 2;
25
+ } else if (x1 === x2) {
26
+ // The line AB is vertical
27
+ dx = L / 2;
28
+ dy = 0;
29
+ } else {
30
+ // Common case when the line is not horizontal or vertical
31
+ // 2. Calculate the slope of the original line
32
+ let m = (y2 - y1) / (x2 - x1);
33
+
34
+ // 3. Calculate the slope of the perpendicular line
35
+ let mPerp = -1 / m;
36
+
37
+ // 4. Calculate dx and dy
38
+ dx = (L / 2) / Math.sqrt(1 + mPerp * mPerp);
39
+ dy = mPerp * dx;
40
+ }
43
41
 
44
- // for lower curve, bezier-point at t = 0.5
45
- // for the case t = 0.5, the bezier-point is the middle point of the curve. => ((y0 + halfWidth) + (y1 + halfWidth)) / 2
46
- const lowerCurveMiddlePoint = [xC, bezierPoint(y0 + halfWidth, y0 + halfWidth, y1 + halfWidth, y1 + halfWidth, 0.5)];
42
+ // 5. Coordinates of the points of the perpendicular line
43
+ let P1 = { x: xM - dx, y: yM - dy };
44
+ let P2 = { x: xM + dx, y: yM + dy };
47
45
 
48
- // The actual width of the link at its middle point as can be seen on the screen.
49
- const actualWidth = distanceToLine(upperCurveMiddleLine, lowerCurveMiddlePoint);
46
+ return { P1, P2 };
47
+ }
50
48
 
51
- const upperNarrowness = (width - actualWidth) / 2;
49
+ function findIntersection(a, b, L, p, q) {
50
+ // Midpoint between a and b
51
+ const midpoint = {
52
+ x: (a.x + b.x) / 2,
53
+ y: (a.y + b.y) / 2
54
+ };
55
+
56
+ // Vector of the line ab
57
+ const ab_dx = b.x - a.x;
58
+ const ab_dy = b.y - a.y;
59
+
60
+ // Vector, perpendicular to ab
61
+ let perp_dx = -ab_dy;
62
+ let perp_dy = ab_dx;
63
+
64
+ // Normalize the perpendicular vector and scale it to 2*L
65
+ const magnitude = Math.sqrt(perp_dx * perp_dx + perp_dy * perp_dy);
66
+ perp_dx = (perp_dx / magnitude) * L;
67
+ perp_dy = (perp_dy / magnitude) * L;
68
+
69
+ // The endpoints of the perpendicular, 2*L long
70
+ const c1 = {
71
+ x: midpoint.x + perp_dx,
72
+ y: midpoint.y + perp_dy
73
+ };
74
+ const c2 = {
75
+ x: midpoint.x - perp_dx,
76
+ y: midpoint.y - perp_dy
77
+ };
78
+
79
+ // Check for intersection of the lines pq and the perpendicular
80
+ const pq_dx = q.x - p.x;
81
+ const pq_dy = q.y - p.y;
82
+
83
+ const denominator = (pq_dy) * (c1.x - c2.x) - (pq_dx) * (c1.y - c2.y);
84
+
85
+ if (Math.abs(denominator) < 1e-10) {
86
+ // The lines are almost parallel, no intersection
87
+ return null;
88
+ }
52
89
 
53
- // The line `upperCurveMiddleLine` shows the upper border of the link.
54
- // Assumption 1: Translated to the left to the desired link width and the translate value will be the `offset`.
55
- // Assumption 2: The translate value is a hypotenuse of a triangle.
56
- const alpha = angelBetweenTwoLines(upperCurveMiddleLine, [[x0, y0 - halfWidth], [xC, y0 - halfWidth]]);
57
- const a = upperNarrowness;
58
- const b = Math.sin(alpha) * a;
59
- const offset = Math.sqrt(a * a + b * b);
60
- // Another option is to assume the triangle is isosceles
61
- // => offset = Math.sqrt(2) * upperNarrowness;
90
+ const ua = (pq_dx * (c2.y - p.y) - pq_dy * (c2.x - p.x)) / denominator;
91
+ const ub = ((c1.x - c2.x) * (c2.y - p.y) - (c1.y - c2.y) * (c2.x - p.x)) / denominator;
62
92
 
63
- let sign = y0 - y1 > 0 ? (-1) : 1;
64
- if (rtl) {
65
- sign = -sign;
93
+ if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) {
94
+ const intersection = {
95
+ x: c2.x + ua * (c1.x - c2.x),
96
+ // y: c2.y + ua * (c1.y - c2.y)
97
+ };
98
+ return intersection;
66
99
  }
67
100
 
68
- return sign * offset;
101
+ // No intersection of the segments
102
+ return null;
103
+ }
104
+
105
+ const calculateControlPointsOffsetX = (link, rtl) => {
106
+ const halfWidth = link.width / 2;
107
+ const x0 = rtl ? link.x1 : link.x0;
108
+ const x1 = rtl ? link.x0 : link.x1;
109
+ const y0 = rtl ? link.y1 : link.y0;
110
+ const y1 = rtl ? link.y0 : link.y1;
111
+
112
+ const xC = (x0 + x1) / 2;
113
+ const middlePoint = [xC, bezierPoint(y0, y0, y1, y1, 0.5)];
114
+
115
+ const tH = 0.4999;
116
+
117
+ const pointH = [
118
+ bezierPoint(x0, xC, xC, x1, tH),
119
+ bezierPoint(y0, y0, y1, y1, tH)
120
+ ];
121
+
122
+ const line = calculatePerpendicularLine(middlePoint[0], middlePoint[1], pointH[0], pointH[1], link.width);
123
+
124
+ const middlePointDown = [xC, bezierPoint(y0 + halfWidth, y0 + halfWidth, y1 + halfWidth, y1 + halfWidth, 0.5)];
125
+ // const middlePointUp = [xC, bezierPoint(y0 - halfWidth, y0 - halfWidth, y1 - halfWidth, y1 - halfWidth, 0.5)];
126
+
127
+ const P = line.P1.y > line.P2.y ? line.P1 : line.P2;
128
+ const L = halfWidth;
129
+ const LDir = (y0 > y1 ? 1 : -1) * L;
130
+ const a = P;
131
+ const b = { x: middlePointDown[0], y: middlePointDown[1] };
132
+ const p = { x: middlePointDown[0], y: middlePointDown[1] };
133
+ const q = { x: Math.max(1, middlePointDown[0] + LDir), y: middlePointDown[1] };
134
+ const Pmx = findIntersection(a, b, L, p, q) || { x: (middlePointDown[0] + P.x) / 2 };
135
+ const P1 = x0;
136
+ const P4 = x1;
137
+ const P2 = (Pmx.x - (0.125 * P1) - (0.125 * P4)) / 0.75;
138
+
139
+ return xC - P2;
69
140
  };
70
141
 
71
142
  export class Link extends SankeyElement {
@@ -107,12 +178,13 @@ export class Link extends SankeyElement {
107
178
  if (!this.options.navigatable) {
108
179
  return;
109
180
  }
110
- const { link, rtl } = this.options;
181
+
182
+ const { link } = this.options;
111
183
  const { x0, x1, y0, y1 } = link;
112
184
  const xC = (x0 + x1) / 2;
113
185
  const halfWidth = link.width / 2;
114
186
 
115
- const offset = calculateControlPointsOffsetX(link, rtl);
187
+ const offset = calculateControlPointsOffsetX(link, this.options.rtl);
116
188
 
117
189
  this._highlight = new drawing.Path({ stroke: this.options.focusHighlight, visible: false })
118
190
  .moveTo(x0, y0 + halfWidth)