@gravity-ui/chartkit 5.14.1 → 5.16.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.
- package/build/plugins/d3/renderer/components/Chart.js +5 -0
- package/build/plugins/d3/renderer/components/Legend.js +129 -66
- package/build/plugins/d3/renderer/components/styles.css +16 -0
- package/build/plugins/d3/renderer/constants/defaults/legend.d.ts +12 -4
- package/build/plugins/d3/renderer/constants/defaults/legend.js +4 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-area.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.js +8 -6
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.js +58 -11
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-line.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-pie.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-treemap.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-waterfall.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +24 -1
- package/build/plugins/d3/renderer/hooks/useShapes/HtmlLayer.d.ts +8 -0
- package/build/plugins/d3/renderer/hooks/useShapes/HtmlLayer.js +22 -0
- package/build/plugins/d3/renderer/hooks/useShapes/area/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/area/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/area/prepare-data.js +18 -3
- package/build/plugins/d3/renderer/hooks/useShapes/area/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +21 -4
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.js +18 -23
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +44 -3
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +9 -9
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +17 -1
- package/build/plugins/d3/renderer/hooks/useShapes/line/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/pie/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/pie/index.js +10 -14
- package/build/plugins/d3/renderer/hooks/useShapes/pie/prepare-data.js +30 -12
- package/build/plugins/d3/renderer/hooks/useShapes/pie/types.d.ts +7 -5
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/types.d.ts +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/prepare-data.js +1 -1
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/types.d.ts +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/types.d.ts +2 -1
- package/build/plugins/d3/renderer/types/index.d.ts +8 -0
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +5 -4
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +11 -7
- package/build/plugins/d3/renderer/utils/axis.d.ts +1 -1
- package/build/plugins/d3/renderer/utils/axis.js +1 -1
- package/build/plugins/d3/renderer/utils/color.d.ts +10 -0
- package/build/plugins/d3/renderer/utils/color.js +43 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +2 -0
- package/build/plugins/d3/renderer/utils/index.js +2 -0
- package/build/plugins/d3/renderer/utils/legend.d.ts +8 -0
- package/build/plugins/d3/renderer/utils/legend.js +23 -0
- package/build/plugins/d3/renderer/utils/text.d.ts +2 -1
- package/build/plugins/d3/renderer/utils/text.js +32 -10
- package/build/types/widget-data/bar-x.d.ts +1 -1
- package/build/types/widget-data/base.d.ts +7 -0
- package/build/types/widget-data/legend.d.ts +24 -0
- package/package.json +2 -2
|
@@ -4,7 +4,7 @@ import { getXValue, getYValue } from '../utils';
|
|
|
4
4
|
function getLabelData(point, series, xMax) {
|
|
5
5
|
const text = String(point.data.label || point.data.y);
|
|
6
6
|
const style = series.dataLabels.style;
|
|
7
|
-
const size = getLabelsSize({ labels: [text], style });
|
|
7
|
+
const size = getLabelsSize({ labels: [text], style, html: series.dataLabels.html });
|
|
8
8
|
const labelData = {
|
|
9
9
|
text,
|
|
10
10
|
x: point.x,
|
|
@@ -22,7 +22,7 @@ function getLabelData(point, series, xMax) {
|
|
|
22
22
|
else {
|
|
23
23
|
const right = left + labelData.size.width;
|
|
24
24
|
if (right > xMax) {
|
|
25
|
-
labelData.x = labelData.x -
|
|
25
|
+
labelData.x = labelData.x - (right - xMax);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
return labelData;
|
|
@@ -97,8 +97,22 @@ export const prepareAreaData = (args) => {
|
|
|
97
97
|
return pointsAcc;
|
|
98
98
|
}, []);
|
|
99
99
|
let labels = [];
|
|
100
|
+
const htmlElements = [];
|
|
100
101
|
if (s.dataLabels.enabled) {
|
|
101
|
-
|
|
102
|
+
const labelItems = points.map((p) => getLabelData(p, s, xMax));
|
|
103
|
+
if (s.dataLabels.html) {
|
|
104
|
+
const htmlLabels = labelItems.map((l) => {
|
|
105
|
+
return {
|
|
106
|
+
x: l.x - l.size.width / 2,
|
|
107
|
+
y: l.y,
|
|
108
|
+
content: l.text,
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
htmlElements.push(...htmlLabels);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
labels = labelItems;
|
|
115
|
+
}
|
|
102
116
|
}
|
|
103
117
|
let markers = [];
|
|
104
118
|
if (s.marker.states.normal.enabled || s.marker.states.hover.enabled) {
|
|
@@ -119,6 +133,7 @@ export const prepareAreaData = (args) => {
|
|
|
119
133
|
hovered: false,
|
|
120
134
|
active: true,
|
|
121
135
|
id: s.id,
|
|
136
|
+
htmlElements,
|
|
122
137
|
});
|
|
123
138
|
return acc;
|
|
124
139
|
}, []);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AreaSeriesData } from '../../../../../../types';
|
|
2
|
-
import { LabelData } from '../../../types';
|
|
2
|
+
import { HtmlItem, LabelData } from '../../../types';
|
|
3
3
|
import { PreparedAreaSeries } from '../../useSeries/types';
|
|
4
4
|
export type PointData = {
|
|
5
5
|
y0: number;
|
|
@@ -24,4 +24,5 @@ export type PreparedAreaData = {
|
|
|
24
24
|
hovered: boolean;
|
|
25
25
|
active: boolean;
|
|
26
26
|
labels: LabelData[];
|
|
27
|
+
htmlElements: HtmlItem[];
|
|
27
28
|
};
|
|
@@ -3,11 +3,12 @@ import { color, select } from 'd3';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
5
|
import { filterOverlappingLabels } from '../../../utils';
|
|
6
|
+
import { HtmlLayer } from '../HtmlLayer';
|
|
6
7
|
export { prepareBarXData } from './prepare-data';
|
|
7
8
|
export * from './types';
|
|
8
9
|
const b = block('d3-bar-x');
|
|
9
10
|
export const BarXSeriesShapes = (args) => {
|
|
10
|
-
const { dispatcher, preparedData, seriesOptions } = args;
|
|
11
|
+
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
11
12
|
const ref = React.useRef(null);
|
|
12
13
|
React.useEffect(() => {
|
|
13
14
|
var _a;
|
|
@@ -89,5 +90,7 @@ export const BarXSeriesShapes = (args) => {
|
|
|
89
90
|
dispatcher.on('hover-shape.bar-x', null);
|
|
90
91
|
};
|
|
91
92
|
}, [dispatcher, preparedData, seriesOptions]);
|
|
92
|
-
return React.createElement(
|
|
93
|
+
return (React.createElement(React.Fragment, null,
|
|
94
|
+
React.createElement("g", { ref: ref, className: b() }),
|
|
95
|
+
React.createElement(HtmlLayer, { preparedData: preparedData, htmlLayout: htmlLayout })));
|
|
93
96
|
};
|
|
@@ -8,15 +8,21 @@ function getLabelData(d) {
|
|
|
8
8
|
}
|
|
9
9
|
const text = String(d.data.label || d.data.y);
|
|
10
10
|
const style = d.series.dataLabels.style;
|
|
11
|
-
const
|
|
11
|
+
const html = d.series.dataLabels.html;
|
|
12
|
+
const { maxHeight: height, maxWidth: width } = getLabelsSize({
|
|
13
|
+
labels: [text],
|
|
14
|
+
style,
|
|
15
|
+
html,
|
|
16
|
+
});
|
|
12
17
|
let y = Math.max(height, d.y - d.series.dataLabels.padding);
|
|
13
18
|
if (d.series.dataLabels.inside) {
|
|
14
19
|
y = d.y + d.height / 2;
|
|
15
20
|
}
|
|
21
|
+
const x = d.x + d.width / 2;
|
|
16
22
|
return {
|
|
17
23
|
text,
|
|
18
|
-
x:
|
|
19
|
-
y,
|
|
24
|
+
x: html ? x - width / 2 : x,
|
|
25
|
+
y: html ? y - height : y,
|
|
20
26
|
style,
|
|
21
27
|
size: { width, height },
|
|
22
28
|
textAnchor: 'middle',
|
|
@@ -122,8 +128,19 @@ export const prepareBarXData = (args) => {
|
|
|
122
128
|
opacity: get(yValue.data, 'opacity', null),
|
|
123
129
|
data: yValue.data,
|
|
124
130
|
series: yValue.series,
|
|
131
|
+
htmlElements: [],
|
|
125
132
|
};
|
|
126
|
-
|
|
133
|
+
const label = getLabelData(barData);
|
|
134
|
+
if (yValue.series.dataLabels.html && label) {
|
|
135
|
+
barData.htmlElements.push({
|
|
136
|
+
x: label.x,
|
|
137
|
+
y: label.y,
|
|
138
|
+
content: label.text,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
barData.label = getLabelData(barData);
|
|
143
|
+
}
|
|
127
144
|
stackItems.push(barData);
|
|
128
145
|
stackHeight += height + 1;
|
|
129
146
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TooltipDataChunkBarX } from '../../../../../../types';
|
|
2
|
-
import { LabelData } from '../../../types';
|
|
2
|
+
import { HtmlItem, LabelData } from '../../../types';
|
|
3
3
|
import { PreparedBarXSeries } from '../../useSeries/types';
|
|
4
4
|
export type PreparedBarXData = Omit<TooltipDataChunkBarX, 'series'> & {
|
|
5
5
|
x: number;
|
|
@@ -9,4 +9,5 @@ export type PreparedBarXData = Omit<TooltipDataChunkBarX, 'series'> & {
|
|
|
9
9
|
opacity: number | null;
|
|
10
10
|
series: PreparedBarXSeries;
|
|
11
11
|
label?: LabelData;
|
|
12
|
+
htmlElements: HtmlItem[];
|
|
12
13
|
};
|
|
@@ -2,11 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { color, select } from 'd3';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
|
+
import { HtmlLayer } from '../HtmlLayer';
|
|
5
6
|
export { prepareBarYData } from './prepare-data';
|
|
6
|
-
const DEFAULT_LABEL_PADDING = 7;
|
|
7
7
|
const b = block('d3-bar-y');
|
|
8
8
|
export const BarYSeriesShapes = (args) => {
|
|
9
|
-
const { dispatcher, preparedData, seriesOptions } = args;
|
|
9
|
+
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
10
10
|
const ref = React.useRef(null);
|
|
11
11
|
React.useEffect(() => {
|
|
12
12
|
if (!ref.current) {
|
|
@@ -26,31 +26,24 @@ export const BarYSeriesShapes = (args) => {
|
|
|
26
26
|
.attr('fill', (d) => d.color)
|
|
27
27
|
.attr('opacity', (d) => d.data.opacity || null)
|
|
28
28
|
.attr('cursor', (d) => d.series.cursor);
|
|
29
|
-
const dataLabels = preparedData.
|
|
29
|
+
const dataLabels = preparedData.reduce((acc, d) => {
|
|
30
|
+
if (d.label) {
|
|
31
|
+
acc.push(d.label);
|
|
32
|
+
}
|
|
33
|
+
return acc;
|
|
34
|
+
}, []);
|
|
30
35
|
const labelSelection = svgElement
|
|
31
36
|
.selectAll('text')
|
|
32
37
|
.data(dataLabels)
|
|
33
38
|
.join('text')
|
|
34
|
-
.text((d) =>
|
|
39
|
+
.text((d) => d.text)
|
|
35
40
|
.attr('class', b('label'))
|
|
36
|
-
.attr('x', (d) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.attr('y', (d) => {
|
|
43
|
-
return d.y + d.height / 2 + d.series.dataLabels.maxHeight / 2;
|
|
44
|
-
})
|
|
45
|
-
.attr('text-anchor', (d) => {
|
|
46
|
-
if (d.series.dataLabels.inside) {
|
|
47
|
-
return 'middle';
|
|
48
|
-
}
|
|
49
|
-
return 'right';
|
|
50
|
-
})
|
|
51
|
-
.style('font-size', (d) => d.series.dataLabels.style.fontSize)
|
|
52
|
-
.style('font-weight', (d) => d.series.dataLabels.style.fontWeight || null)
|
|
53
|
-
.style('fill', (d) => d.series.dataLabels.style.fontColor || null);
|
|
41
|
+
.attr('x', (d) => d.x)
|
|
42
|
+
.attr('y', (d) => d.y)
|
|
43
|
+
.attr('text-anchor', (d) => d.textAnchor)
|
|
44
|
+
.style('font-size', (d) => d.style.fontSize)
|
|
45
|
+
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
46
|
+
.style('fill', (d) => d.style.fontColor || null);
|
|
54
47
|
const hoverOptions = get(seriesOptions, 'bar-y.states.hover');
|
|
55
48
|
const inactiveOptions = get(seriesOptions, 'bar-y.states.inactive');
|
|
56
49
|
dispatcher.on('hover-shape.bar-y', (data) => {
|
|
@@ -85,5 +78,7 @@ export const BarYSeriesShapes = (args) => {
|
|
|
85
78
|
dispatcher.on('hover-shape.bar-y', null);
|
|
86
79
|
};
|
|
87
80
|
}, [dispatcher, preparedData, seriesOptions]);
|
|
88
|
-
return React.createElement(
|
|
81
|
+
return (React.createElement(React.Fragment, null,
|
|
82
|
+
React.createElement("g", { ref: ref, className: b() }),
|
|
83
|
+
React.createElement(HtmlLayer, { preparedData: preparedData, htmlLayout: htmlLayout })));
|
|
89
84
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ascending, descending, max, sort } from 'd3';
|
|
2
2
|
import get from 'lodash/get';
|
|
3
|
-
import { getDataCategoryValue } from '../../../utils';
|
|
3
|
+
import { getDataCategoryValue, getLabelsSize } from '../../../utils';
|
|
4
4
|
import { MIN_BAR_GAP, MIN_BAR_GROUP_GAP, MIN_BAR_WIDTH } from '../constants';
|
|
5
|
+
const DEFAULT_LABEL_PADDING = 7;
|
|
5
6
|
function groupByYValue(series, yAxis) {
|
|
6
7
|
const data = {};
|
|
7
8
|
series.forEach((s) => {
|
|
@@ -47,6 +48,41 @@ function getBandWidth(series, yAxis, yScale) {
|
|
|
47
48
|
}
|
|
48
49
|
return bandWidth;
|
|
49
50
|
}
|
|
51
|
+
function setLabel(prepared) {
|
|
52
|
+
const dataLabels = prepared.series.dataLabels;
|
|
53
|
+
if (!dataLabels.enabled) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const data = prepared.data;
|
|
57
|
+
const content = String(data.label || data.x);
|
|
58
|
+
const { maxHeight: height, maxWidth: width } = getLabelsSize({
|
|
59
|
+
labels: [content],
|
|
60
|
+
style: dataLabels.style,
|
|
61
|
+
html: dataLabels.html,
|
|
62
|
+
});
|
|
63
|
+
const x = dataLabels.inside
|
|
64
|
+
? prepared.x + prepared.width / 2
|
|
65
|
+
: prepared.x + prepared.width + DEFAULT_LABEL_PADDING;
|
|
66
|
+
const y = prepared.y + prepared.height / 2;
|
|
67
|
+
if (dataLabels.html) {
|
|
68
|
+
prepared.htmlElements.push({
|
|
69
|
+
x,
|
|
70
|
+
y: y - height / 2,
|
|
71
|
+
content,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
prepared.label = {
|
|
76
|
+
x,
|
|
77
|
+
y: y + height / 2,
|
|
78
|
+
text: content,
|
|
79
|
+
textAnchor: dataLabels.inside ? 'middle' : 'right',
|
|
80
|
+
style: dataLabels.style,
|
|
81
|
+
series: prepared.series,
|
|
82
|
+
size: { width, height },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
50
86
|
export const prepareBarYData = (args) => {
|
|
51
87
|
const { series, seriesOptions, yAxis, xScale, yScale: [yScale], } = args;
|
|
52
88
|
const xLinearScale = xScale;
|
|
@@ -100,7 +136,7 @@ export const prepareBarYData = (args) => {
|
|
|
100
136
|
const y = center - currentBarHeight / 2 + (barHeight + rectGap) * groupItemIndex;
|
|
101
137
|
const xValue = Number(data.x);
|
|
102
138
|
const width = xValue > 0 ? xLinearScale(xValue) - base : base - xLinearScale(xValue);
|
|
103
|
-
|
|
139
|
+
const item = {
|
|
104
140
|
x: xValue > 0 ? stackSum : stackSum - width,
|
|
105
141
|
y,
|
|
106
142
|
width,
|
|
@@ -109,7 +145,9 @@ export const prepareBarYData = (args) => {
|
|
|
109
145
|
opacity: get(data, 'opacity', null),
|
|
110
146
|
data,
|
|
111
147
|
series: s,
|
|
112
|
-
|
|
148
|
+
htmlElements: [],
|
|
149
|
+
};
|
|
150
|
+
stackItems.push(item);
|
|
113
151
|
stackSum += width + 1;
|
|
114
152
|
});
|
|
115
153
|
if (series.some((s) => s.stacking === 'percent')) {
|
|
@@ -124,5 +162,8 @@ export const prepareBarYData = (args) => {
|
|
|
124
162
|
result.push(...stackItems);
|
|
125
163
|
});
|
|
126
164
|
});
|
|
165
|
+
result.forEach((d) => {
|
|
166
|
+
setLabel(d);
|
|
167
|
+
});
|
|
127
168
|
return result;
|
|
128
169
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TooltipDataChunkBarX } from '../../../../../../types';
|
|
2
|
+
import { HtmlItem, LabelData } from '../../../types';
|
|
2
3
|
import { PreparedBarYSeries } from '../../useSeries/types';
|
|
3
4
|
export type PreparedBarYData = Omit<TooltipDataChunkBarX, 'series'> & {
|
|
4
5
|
x: number;
|
|
@@ -8,4 +9,6 @@ export type PreparedBarYData = Omit<TooltipDataChunkBarX, 'series'> & {
|
|
|
8
9
|
color: string;
|
|
9
10
|
opacity: number | null;
|
|
10
11
|
series: PreparedBarYSeries;
|
|
12
|
+
label?: LabelData;
|
|
13
|
+
htmlElements: HtmlItem[];
|
|
11
14
|
};
|
|
@@ -25,6 +25,7 @@ type Args = {
|
|
|
25
25
|
xScale?: ChartScale;
|
|
26
26
|
yScale?: ChartScale[];
|
|
27
27
|
split: PreparedSplit;
|
|
28
|
+
htmlLayout: HTMLElement | null;
|
|
28
29
|
};
|
|
29
30
|
export declare const useShapes: (args: Args) => {
|
|
30
31
|
shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
|
|
@@ -15,7 +15,7 @@ import { prepareTreemapData } from './treemap/prepare-data';
|
|
|
15
15
|
import { WaterfallSeriesShapes, prepareWaterfallData } from './waterfall';
|
|
16
16
|
import './styles.css';
|
|
17
17
|
export const useShapes = (args) => {
|
|
18
|
-
const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, split, } = args;
|
|
18
|
+
const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, split, htmlLayout, } = args;
|
|
19
19
|
const shapesComponents = React.useMemo(() => {
|
|
20
20
|
const visibleSeries = getOnlyVisibleSeries(series);
|
|
21
21
|
const groupedSeries = group(visibleSeries, (item) => item.type);
|
|
@@ -34,7 +34,7 @@ export const useShapes = (args) => {
|
|
|
34
34
|
yScale,
|
|
35
35
|
boundsHeight,
|
|
36
36
|
});
|
|
37
|
-
acc.push(React.createElement(BarXSeriesShapes, { key: "bar-x", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
37
|
+
acc.push(React.createElement(BarXSeriesShapes, { key: "bar-x", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout }));
|
|
38
38
|
shapesData.push(...preparedData);
|
|
39
39
|
}
|
|
40
40
|
break;
|
|
@@ -49,7 +49,7 @@ export const useShapes = (args) => {
|
|
|
49
49
|
yAxis,
|
|
50
50
|
yScale,
|
|
51
51
|
});
|
|
52
|
-
acc.push(React.createElement(BarYSeriesShapes, { key: "bar-y", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
52
|
+
acc.push(React.createElement(BarYSeriesShapes, { key: "bar-y", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout }));
|
|
53
53
|
shapesData.push(...preparedData);
|
|
54
54
|
}
|
|
55
55
|
break;
|
|
@@ -64,7 +64,7 @@ export const useShapes = (args) => {
|
|
|
64
64
|
yAxis,
|
|
65
65
|
yScale,
|
|
66
66
|
});
|
|
67
|
-
acc.push(React.createElement(WaterfallSeriesShapes, { key: "waterfall", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
67
|
+
acc.push(React.createElement(WaterfallSeriesShapes, { key: "waterfall", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout }));
|
|
68
68
|
shapesData.push(...preparedData);
|
|
69
69
|
}
|
|
70
70
|
break;
|
|
@@ -79,7 +79,7 @@ export const useShapes = (args) => {
|
|
|
79
79
|
yScale,
|
|
80
80
|
split,
|
|
81
81
|
});
|
|
82
|
-
acc.push(React.createElement(LineSeriesShapes, { key: "line", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
82
|
+
acc.push(React.createElement(LineSeriesShapes, { key: "line", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout }));
|
|
83
83
|
shapesData.push(...preparedData);
|
|
84
84
|
}
|
|
85
85
|
break;
|
|
@@ -94,7 +94,7 @@ export const useShapes = (args) => {
|
|
|
94
94
|
yScale,
|
|
95
95
|
boundsHeight,
|
|
96
96
|
});
|
|
97
|
-
acc.push(React.createElement(AreaSeriesShapes, { key: "area", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
97
|
+
acc.push(React.createElement(AreaSeriesShapes, { key: "area", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout }));
|
|
98
98
|
shapesData.push(...preparedData);
|
|
99
99
|
}
|
|
100
100
|
break;
|
|
@@ -108,7 +108,7 @@ export const useShapes = (args) => {
|
|
|
108
108
|
yAxis,
|
|
109
109
|
yScale,
|
|
110
110
|
});
|
|
111
|
-
acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions }));
|
|
111
|
+
acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
112
112
|
shapesData.push(...preparedData);
|
|
113
113
|
}
|
|
114
114
|
break;
|
|
@@ -119,7 +119,7 @@ export const useShapes = (args) => {
|
|
|
119
119
|
boundsWidth,
|
|
120
120
|
boundsHeight,
|
|
121
121
|
});
|
|
122
|
-
acc.push(React.createElement(PieSeriesShapes, { key: "pie", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions }));
|
|
122
|
+
acc.push(React.createElement(PieSeriesShapes, { key: "pie", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
123
123
|
shapesData.push(...preparedData);
|
|
124
124
|
break;
|
|
125
125
|
}
|
|
@@ -131,7 +131,7 @@ export const useShapes = (args) => {
|
|
|
131
131
|
width: boundsWidth,
|
|
132
132
|
height: boundsHeight,
|
|
133
133
|
});
|
|
134
|
-
acc.push(React.createElement(TreemapSeriesShape, { key: "treemap", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions }));
|
|
134
|
+
acc.push(React.createElement(TreemapSeriesShape, { key: "treemap", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, htmlLayout: htmlLayout }));
|
|
135
135
|
shapesData.push(preparedData);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -3,11 +3,12 @@ import { color, line as lineGenerator, select } from 'd3';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
5
|
import { filterOverlappingLabels } from '../../../utils';
|
|
6
|
+
import { HtmlLayer } from '../HtmlLayer';
|
|
6
7
|
import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
|
|
7
8
|
import { getLineDashArray, setActiveState } from '../utils';
|
|
8
9
|
const b = block('d3-line');
|
|
9
10
|
export const LineSeriesShapes = (args) => {
|
|
10
|
-
const { dispatcher, preparedData, seriesOptions } = args;
|
|
11
|
+
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
11
12
|
const ref = React.useRef(null);
|
|
12
13
|
React.useEffect(() => {
|
|
13
14
|
var _a;
|
|
@@ -124,5 +125,7 @@ export const LineSeriesShapes = (args) => {
|
|
|
124
125
|
dispatcher.on('hover-shape.line', null);
|
|
125
126
|
};
|
|
126
127
|
}, [dispatcher, preparedData, seriesOptions]);
|
|
127
|
-
return React.createElement(
|
|
128
|
+
return (React.createElement(React.Fragment, null,
|
|
129
|
+
React.createElement("g", { ref: ref, className: b() }),
|
|
130
|
+
React.createElement(HtmlLayer, { preparedData: preparedData, htmlLayout: htmlLayout })));
|
|
128
131
|
};
|
|
@@ -26,6 +26,15 @@ function getLabelData(point, series, xMax) {
|
|
|
26
26
|
}
|
|
27
27
|
return labelData;
|
|
28
28
|
}
|
|
29
|
+
function getHtmlLabel(point, series, xMax) {
|
|
30
|
+
const content = String(point.data.label || point.data.y);
|
|
31
|
+
const size = getLabelsSize({ labels: [content], html: true });
|
|
32
|
+
return {
|
|
33
|
+
x: Math.min(xMax - size.maxWidth, Math.max(0, point.x)),
|
|
34
|
+
y: Math.max(0, point.y - series.dataLabels.padding - size.maxHeight),
|
|
35
|
+
content,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
29
38
|
export const prepareLineData = (args) => {
|
|
30
39
|
const { series, xAxis, yAxis, xScale, yScale, split } = args;
|
|
31
40
|
const [_xMin, xRangeMax] = xScale.range();
|
|
@@ -43,9 +52,15 @@ export const prepareLineData = (args) => {
|
|
|
43
52
|
data: d,
|
|
44
53
|
series: s,
|
|
45
54
|
}));
|
|
55
|
+
const htmlElements = [];
|
|
46
56
|
let labels = [];
|
|
47
57
|
if (s.dataLabels.enabled) {
|
|
48
|
-
|
|
58
|
+
if (s.dataLabels.html) {
|
|
59
|
+
htmlElements.push(...points.map((p) => getHtmlLabel(p, s, xMax)));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
labels = points.map((p) => getLabelData(p, s, xMax));
|
|
63
|
+
}
|
|
49
64
|
}
|
|
50
65
|
let markers = [];
|
|
51
66
|
if (s.marker.states.normal.enabled || s.marker.states.hover.enabled) {
|
|
@@ -68,6 +83,7 @@ export const prepareLineData = (args) => {
|
|
|
68
83
|
dashStyle: s.dashStyle,
|
|
69
84
|
linecap: s.linecap,
|
|
70
85
|
opacity: s.opacity,
|
|
86
|
+
htmlElements,
|
|
71
87
|
};
|
|
72
88
|
acc.push(result);
|
|
73
89
|
return acc;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DashStyle, LineCap } from '../../../../../../constants';
|
|
2
2
|
import { LineSeriesData } from '../../../../../../types';
|
|
3
|
-
import { LabelData } from '../../../types';
|
|
3
|
+
import { HtmlItem, LabelData } from '../../../types';
|
|
4
4
|
import { PreparedLineSeries } from '../../useSeries/types';
|
|
5
5
|
export type PointData = {
|
|
6
6
|
x: number;
|
|
@@ -26,4 +26,5 @@ export type PreparedLineData = {
|
|
|
26
26
|
dashStyle: DashStyle;
|
|
27
27
|
linecap: LineCap;
|
|
28
28
|
opacity: number | null;
|
|
29
|
+
htmlElements: HtmlItem[];
|
|
29
30
|
};
|
|
@@ -6,6 +6,7 @@ type PreparePieSeriesArgs = {
|
|
|
6
6
|
dispatcher: Dispatch<object>;
|
|
7
7
|
preparedData: PreparedPieData[];
|
|
8
8
|
seriesOptions: PreparedSeriesOptions;
|
|
9
|
+
htmlLayout: HTMLElement | null;
|
|
9
10
|
};
|
|
10
11
|
export declare function getHaloVisibility(d: PieArcDatum<SegmentData>): "" | "hidden";
|
|
11
12
|
export declare function PieSeriesShapes(args: PreparePieSeriesArgs): React.JSX.Element;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { arc, color,
|
|
2
|
+
import { arc, color, select } from 'd3';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
5
|
import { setEllipsisForOverflowTexts } from '../../../utils';
|
|
6
|
+
import { HtmlLayer } from '../HtmlLayer';
|
|
6
7
|
import { setActiveState } from '../utils';
|
|
7
|
-
import { getCurveFactory } from './utils';
|
|
8
8
|
const b = block('d3-pie');
|
|
9
9
|
export function getHaloVisibility(d) {
|
|
10
10
|
const enabled = d.data.pie.halo.enabled && d.data.hovered;
|
|
11
11
|
return enabled ? '' : 'hidden';
|
|
12
12
|
}
|
|
13
13
|
export function PieSeriesShapes(args) {
|
|
14
|
-
const { dispatcher, preparedData, seriesOptions } = args;
|
|
14
|
+
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
15
15
|
const ref = React.useRef(null);
|
|
16
16
|
React.useEffect(() => {
|
|
17
17
|
if (!ref.current) {
|
|
@@ -71,6 +71,7 @@ export function PieSeriesShapes(args) {
|
|
|
71
71
|
.attr('class', b('segment'))
|
|
72
72
|
.attr('fill', (d) => d.data.color)
|
|
73
73
|
.attr('opacity', (d) => d.data.opacity);
|
|
74
|
+
// render Labels
|
|
74
75
|
shapesSelection
|
|
75
76
|
.selectAll('text')
|
|
76
77
|
.data((pieData) => pieData.labels)
|
|
@@ -87,19 +88,12 @@ export function PieSeriesShapes(args) {
|
|
|
87
88
|
// Add the polyline between chart and labels
|
|
88
89
|
shapesSelection
|
|
89
90
|
.selectAll(connectorSelector)
|
|
90
|
-
.data((pieData) => pieData.
|
|
91
|
+
.data((pieData) => pieData.connectors)
|
|
91
92
|
.enter()
|
|
92
93
|
.append('path')
|
|
93
94
|
.attr('class', b('connector'))
|
|
94
|
-
.attr('d', (d) =>
|
|
95
|
-
|
|
96
|
-
const curveFactory = getCurveFactory(d.segment.pie);
|
|
97
|
-
if (curveFactory) {
|
|
98
|
-
line = line.curve(curveFactory);
|
|
99
|
-
}
|
|
100
|
-
return line(d.connector.points);
|
|
101
|
-
})
|
|
102
|
-
.attr('stroke', (d) => d.connector.color)
|
|
95
|
+
.attr('d', (d) => d.path)
|
|
96
|
+
.attr('stroke', (d) => d.color)
|
|
103
97
|
.attr('stroke-width', 1)
|
|
104
98
|
.attr('stroke-linejoin', 'round')
|
|
105
99
|
.attr('stroke-linecap', 'round')
|
|
@@ -172,5 +166,7 @@ export function PieSeriesShapes(args) {
|
|
|
172
166
|
dispatcher.on(eventName, null);
|
|
173
167
|
};
|
|
174
168
|
}, [dispatcher, preparedData, seriesOptions]);
|
|
175
|
-
return React.createElement(
|
|
169
|
+
return (React.createElement(React.Fragment, null,
|
|
170
|
+
React.createElement("g", { ref: ref, className: b(), style: { zIndex: 9 } }),
|
|
171
|
+
React.createElement(HtmlLayer, { preparedData: preparedData, htmlLayout: htmlLayout })));
|
|
176
172
|
}
|