@gravity-ui/charts 0.6.0 → 0.7.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/README.md +1 -1
- package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +2 -2
- package/dist/cjs/components/Tooltip/index.js +6 -6
- package/dist/cjs/components/Tooltip/styles.css +7 -18
- package/dist/cjs/components/index.d.ts +10 -9
- package/dist/cjs/hooks/useSeries/prepare-area.d.ts +1 -1
- package/dist/cjs/hooks/useSeries/prepare-line.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +4 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/line/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/pie/index.js +2 -1
- package/dist/cjs/hooks/useShapes/pie/prepare-data.js +159 -111
- package/dist/cjs/hooks/useShapes/pie/types.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +1 -0
- package/dist/cjs/types/chart/area.d.ts +6 -6
- package/dist/cjs/types/chart/axis.d.ts +8 -7
- package/dist/cjs/types/chart/bar-x.d.ts +4 -4
- package/dist/cjs/types/chart/bar-y.d.ts +5 -6
- package/dist/cjs/types/chart/base.d.ts +6 -6
- package/dist/cjs/types/chart/chart.d.ts +4 -4
- package/dist/cjs/types/chart/halo.d.ts +2 -2
- package/dist/cjs/types/chart/legend.d.ts +10 -10
- package/dist/cjs/types/chart/line.d.ts +4 -4
- package/dist/cjs/types/chart/marker.d.ts +2 -2
- package/dist/cjs/types/chart/pie.d.ts +4 -4
- package/dist/cjs/types/chart/scatter.d.ts +4 -4
- package/dist/cjs/types/chart/series.d.ts +8 -8
- package/dist/cjs/types/chart/split.d.ts +4 -4
- package/dist/cjs/types/chart/title.d.ts +2 -2
- package/dist/cjs/types/chart/tooltip.d.ts +20 -20
- package/dist/cjs/types/chart/treemap.d.ts +4 -4
- package/dist/cjs/types/chart/waterfall.d.ts +4 -4
- package/dist/cjs/types/chart-ui.d.ts +10 -6
- package/dist/cjs/types/formatter.d.ts +4 -4
- package/dist/cjs/types/index.d.ts +34 -4
- package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +2 -2
- package/dist/esm/components/Tooltip/index.js +6 -6
- package/dist/esm/components/Tooltip/styles.css +7 -18
- package/dist/esm/components/index.d.ts +10 -9
- package/dist/esm/hooks/useSeries/prepare-area.d.ts +1 -1
- package/dist/esm/hooks/useSeries/prepare-line.d.ts +1 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +4 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/line/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/pie/index.js +2 -1
- package/dist/esm/hooks/useShapes/pie/prepare-data.js +159 -111
- package/dist/esm/hooks/useShapes/pie/types.d.ts +1 -1
- package/dist/esm/hooks/useShapes/treemap/prepare-data.js +1 -0
- package/dist/esm/types/chart/area.d.ts +6 -6
- package/dist/esm/types/chart/axis.d.ts +8 -7
- package/dist/esm/types/chart/bar-x.d.ts +4 -4
- package/dist/esm/types/chart/bar-y.d.ts +5 -6
- package/dist/esm/types/chart/base.d.ts +6 -6
- package/dist/esm/types/chart/chart.d.ts +4 -4
- package/dist/esm/types/chart/halo.d.ts +2 -2
- package/dist/esm/types/chart/legend.d.ts +10 -10
- package/dist/esm/types/chart/line.d.ts +4 -4
- package/dist/esm/types/chart/marker.d.ts +2 -2
- package/dist/esm/types/chart/pie.d.ts +4 -4
- package/dist/esm/types/chart/scatter.d.ts +4 -4
- package/dist/esm/types/chart/series.d.ts +8 -8
- package/dist/esm/types/chart/split.d.ts +4 -4
- package/dist/esm/types/chart/title.d.ts +2 -2
- package/dist/esm/types/chart/tooltip.d.ts +20 -20
- package/dist/esm/types/chart/treemap.d.ts +4 -4
- package/dist/esm/types/chart/waterfall.d.ts +4 -4
- package/dist/esm/types/chart-ui.d.ts +10 -6
- package/dist/esm/types/formatter.d.ts +4 -4
- package/dist/esm/types/index.d.ts +34 -4
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ChartTooltip, ChartXAxis, ChartYAxis, TooltipDataChunk } from '../../types';
|
|
3
|
-
export
|
|
3
|
+
export interface ChartTooltipContentProps {
|
|
4
4
|
hovered?: TooltipDataChunk[];
|
|
5
5
|
xAxis?: ChartXAxis;
|
|
6
6
|
yAxis?: ChartYAxis;
|
|
7
7
|
renderer?: ChartTooltip['renderer'];
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
export declare const ChartTooltipContent: (props: ChartTooltipContentProps) => React.JSX.Element | null;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Popup,
|
|
2
|
+
import { Popup, useVirtualElement } from '@gravity-ui/uikit';
|
|
3
3
|
import { useTooltip } from '../../hooks';
|
|
4
4
|
import { block } from '../../utils';
|
|
5
5
|
import { ChartTooltipContent } from './ChartTooltipContent';
|
|
6
6
|
import './styles.css';
|
|
7
|
-
const b = block('
|
|
7
|
+
const b = block('tooltip');
|
|
8
8
|
export const Tooltip = (props) => {
|
|
9
9
|
const { tooltip, xAxis, yAxis, svgContainer, dispatcher, tooltipPinned, onOutsideClick } = props;
|
|
10
10
|
const { hovered, pointerPosition } = useTooltip({ dispatcher, tooltip });
|
|
11
11
|
const containerRect = (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) || { left: 0, top: 0 };
|
|
12
12
|
const left = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) || 0) + containerRect.left;
|
|
13
13
|
const top = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[1]) || 0) + containerRect.top;
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
if (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.contains(e.target)) {
|
|
14
|
+
const { anchor } = useVirtualElement({ left, top });
|
|
15
|
+
const handleOnOpenChange = (_open, e) => {
|
|
16
|
+
if (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.contains(e === null || e === void 0 ? void 0 : e.target)) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
onOutsideClick === null || onOutsideClick === void 0 ? void 0 : onOutsideClick();
|
|
@@ -21,7 +21,7 @@ export const Tooltip = (props) => {
|
|
|
21
21
|
React.useEffect(() => {
|
|
22
22
|
window.dispatchEvent(new CustomEvent('scroll'));
|
|
23
23
|
}, [left, top]);
|
|
24
|
-
return (hovered === null || hovered === void 0 ? void 0 : hovered.length) ? (React.createElement(Popup, { className: b({ pinned: tooltipPinned }),
|
|
24
|
+
return (hovered === null || hovered === void 0 ? void 0 : hovered.length) ? (React.createElement(Popup, { anchorElement: anchor, className: b({ pinned: tooltipPinned }), disableTransition: true, floatingStyles: tooltipPinned ? undefined : { pointerEvents: 'none' }, offset: { mainAxis: 20 }, onOpenChange: tooltipPinned ? handleOnOpenChange : undefined, open: true, placement: ['right', 'left', 'top', 'bottom'] },
|
|
25
25
|
React.createElement("div", { className: b('content') },
|
|
26
26
|
React.createElement(ChartTooltipContent, { hovered: hovered, xAxis: xAxis, yAxis: yAxis, renderer: tooltip.renderer })))) : null;
|
|
27
27
|
};
|
|
@@ -1,28 +1,17 @@
|
|
|
1
|
-
.gcharts-
|
|
2
|
-
--g-
|
|
3
|
-
pointer-events: none;
|
|
4
|
-
}
|
|
5
|
-
.gcharts-d3-tooltip[class] > div {
|
|
6
|
-
animation-duration: unset;
|
|
7
|
-
animation-timing-function: unset;
|
|
8
|
-
animation-fill-mode: unset;
|
|
9
|
-
}
|
|
10
|
-
.gcharts-d3-tooltip[class].gcharts-d3-tooltip_pinned {
|
|
11
|
-
pointer-events: inherit;
|
|
1
|
+
.gcharts-tooltip {
|
|
2
|
+
box-shadow: 0 2px 12px var(--g-color-sfx-shadow);
|
|
12
3
|
}
|
|
13
|
-
.gcharts-
|
|
14
|
-
padding:
|
|
4
|
+
.gcharts-tooltip__content {
|
|
5
|
+
padding: 8px 14px;
|
|
15
6
|
text-wrap: nowrap;
|
|
16
|
-
border:
|
|
17
|
-
border-radius: 3px;
|
|
7
|
+
border-radius: 4px;
|
|
18
8
|
background-color: var(--g-color-infographics-tooltip-bg);
|
|
19
|
-
box-shadow: 0 2px 12px var(--g-color-sfx-shadow);
|
|
20
9
|
}
|
|
21
|
-
.gcharts-
|
|
10
|
+
.gcharts-tooltip__content-row {
|
|
22
11
|
display: flex;
|
|
23
12
|
align-items: center;
|
|
24
13
|
}
|
|
25
|
-
.gcharts-
|
|
14
|
+
.gcharts-tooltip__color {
|
|
26
15
|
display: inline-block;
|
|
27
16
|
width: 16px;
|
|
28
17
|
height: 8px;
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ChartData } from '../types';
|
|
3
3
|
export * from './Tooltip/ChartTooltipContent';
|
|
4
|
-
export
|
|
4
|
+
export interface ChartRef {
|
|
5
5
|
reflow: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
6
|
+
}
|
|
7
|
+
export interface ChartDimentions {
|
|
8
8
|
height: number;
|
|
9
9
|
width: number;
|
|
10
|
-
}
|
|
11
|
-
export type
|
|
10
|
+
}
|
|
11
|
+
export type ChartOnResize = (args: {
|
|
12
|
+
dimensions?: ChartDimentions;
|
|
13
|
+
}) => void;
|
|
14
|
+
export interface ChartProps {
|
|
12
15
|
data: ChartData;
|
|
13
16
|
lang?: string;
|
|
14
|
-
onResize?:
|
|
15
|
-
|
|
16
|
-
}) => void;
|
|
17
|
-
};
|
|
17
|
+
onResize?: ChartOnResize;
|
|
18
|
+
}
|
|
18
19
|
export declare const Chart: React.ForwardRefExoticComponent<ChartProps & React.RefAttributes<ChartRef>>;
|
|
@@ -5,9 +5,9 @@ export declare const DEFAULT_LINE_WIDTH = 1;
|
|
|
5
5
|
export declare const DEFAULT_MARKER: {
|
|
6
6
|
enabled: boolean;
|
|
7
7
|
symbol: `${import("../../constants").SymbolType}`;
|
|
8
|
+
radius: number;
|
|
8
9
|
borderColor: string;
|
|
9
10
|
borderWidth: number;
|
|
10
|
-
radius: number;
|
|
11
11
|
};
|
|
12
12
|
type PrepareAreaSeriesArgs = {
|
|
13
13
|
colorScale: ScaleOrdinal<string, string>;
|
|
@@ -8,9 +8,9 @@ export declare const DEFAULT_DASH_STYLE = DashStyle.Solid;
|
|
|
8
8
|
export declare const DEFAULT_MARKER: {
|
|
9
9
|
enabled: boolean;
|
|
10
10
|
symbol: `${import("../../constants").SymbolType}`;
|
|
11
|
+
radius: number;
|
|
11
12
|
borderColor: string;
|
|
12
13
|
borderWidth: number;
|
|
13
|
-
radius: number;
|
|
14
14
|
};
|
|
15
15
|
type PrepareLineSeriesArgs = {
|
|
16
16
|
colorScale: ScaleOrdinal<string, string>;
|
|
@@ -102,10 +102,14 @@ export const prepareAreaData = (args) => {
|
|
|
102
102
|
const labelItems = points.map((p) => getLabelData(p, s, xMax));
|
|
103
103
|
if (s.dataLabels.html) {
|
|
104
104
|
const htmlLabels = labelItems.map((l) => {
|
|
105
|
+
var _a;
|
|
106
|
+
const style = (_a = l.style) !== null && _a !== void 0 ? _a : s.dataLabels.style;
|
|
107
|
+
const labelSize = getLabelsSize({ labels: [l.text], style, html: true });
|
|
105
108
|
return {
|
|
106
109
|
x: l.x - l.size.width / 2,
|
|
107
110
|
y: l.y,
|
|
108
111
|
content: l.text,
|
|
112
|
+
size: { width: labelSize.maxWidth, height: labelSize.maxHeight },
|
|
109
113
|
};
|
|
110
114
|
});
|
|
111
115
|
htmlElements.push(...htmlLabels);
|
|
@@ -33,6 +33,7 @@ function getHtmlLabel(point, series, xMax) {
|
|
|
33
33
|
x: Math.min(xMax - size.maxWidth, Math.max(0, point.x)),
|
|
34
34
|
y: Math.max(0, point.y - series.dataLabels.padding - size.maxHeight),
|
|
35
35
|
content,
|
|
36
|
+
size: { width: size.maxWidth, height: size.maxHeight },
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
export const prepareLineData = (args) => {
|
|
@@ -165,7 +165,8 @@ export function PieSeriesShapes(args) {
|
|
|
165
165
|
dispatcher.on(eventName, null);
|
|
166
166
|
};
|
|
167
167
|
}, [dispatcher, preparedData, seriesOptions]);
|
|
168
|
+
const htmlElements = preparedData.map((d) => d.htmlLabels).flat();
|
|
168
169
|
return (React.createElement(React.Fragment, null,
|
|
169
170
|
React.createElement("g", { ref: ref, className: b(), style: { zIndex: 9 } }),
|
|
170
|
-
React.createElement(HtmlLayer, { preparedData:
|
|
171
|
+
React.createElement(HtmlLayer, { preparedData: { htmlElements }, htmlLayout: htmlLayout })));
|
|
171
172
|
}
|
|
@@ -18,7 +18,7 @@ export function preparePieData(args) {
|
|
|
18
18
|
const { series: preparedSeries, boundsWidth, boundsHeight } = args;
|
|
19
19
|
const maxRadius = Math.min(boundsWidth, boundsHeight) / 2;
|
|
20
20
|
const groupedPieSeries = group(preparedSeries, (pieSeries) => pieSeries.stackId);
|
|
21
|
-
|
|
21
|
+
const prepareItem = (stackId, items) => {
|
|
22
22
|
var _a, _b, _c;
|
|
23
23
|
const series = items[0];
|
|
24
24
|
const { center, borderWidth, borderColor, borderRadius, radius: seriesRadius, innerRadius: seriesInnerRadius, dataLabels, } = series;
|
|
@@ -30,6 +30,7 @@ export function preparePieData(args) {
|
|
|
30
30
|
radius,
|
|
31
31
|
segments: [],
|
|
32
32
|
labels: [],
|
|
33
|
+
htmlLabels: [],
|
|
33
34
|
connectors: [],
|
|
34
35
|
borderColor,
|
|
35
36
|
borderWidth,
|
|
@@ -41,7 +42,6 @@ export function preparePieData(args) {
|
|
|
41
42
|
opacity: series.states.hover.halo.opacity,
|
|
42
43
|
size: series.states.hover.halo.size,
|
|
43
44
|
},
|
|
44
|
-
htmlElements: [],
|
|
45
45
|
};
|
|
46
46
|
const segments = items.map((item) => {
|
|
47
47
|
return {
|
|
@@ -55,132 +55,180 @@ export function preparePieData(args) {
|
|
|
55
55
|
};
|
|
56
56
|
});
|
|
57
57
|
data.segments = pieGenerator(segments);
|
|
58
|
-
let line = lineGenerator();
|
|
59
|
-
const curveFactory = getCurveFactory(data);
|
|
60
|
-
if (curveFactory) {
|
|
61
|
-
line = line.curve(curveFactory);
|
|
62
|
-
}
|
|
63
58
|
if (dataLabels.enabled) {
|
|
64
59
|
const { style, connectorPadding, distance } = dataLabels;
|
|
65
60
|
const { maxHeight: labelHeight } = getLabelsSize({ labels: ['Some Label'], style });
|
|
66
|
-
const minSegmentRadius = maxRadius -
|
|
61
|
+
const minSegmentRadius = maxRadius - distance - connectorPadding - labelHeight;
|
|
67
62
|
if (data.radius > minSegmentRadius) {
|
|
68
63
|
data.radius = minSegmentRadius;
|
|
69
64
|
data.innerRadius =
|
|
70
65
|
(_c = calculateNumericProperty({ value: seriesInnerRadius, base: data.radius })) !== null && _c !== void 0 ? _c : 0;
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
67
|
+
}
|
|
68
|
+
return data;
|
|
69
|
+
};
|
|
70
|
+
const prepareLabels = (prepareLabelsArgs) => {
|
|
71
|
+
const { data, series } = prepareLabelsArgs;
|
|
72
|
+
const { dataLabels } = series[0];
|
|
73
|
+
const labels = [];
|
|
74
|
+
const htmlLabels = [];
|
|
75
|
+
const connectors = [];
|
|
76
|
+
if (!dataLabels.enabled) {
|
|
77
|
+
return { labels, htmlLabels, connectors };
|
|
78
|
+
}
|
|
79
|
+
let line = lineGenerator();
|
|
80
|
+
const curveFactory = getCurveFactory(data);
|
|
81
|
+
if (curveFactory) {
|
|
82
|
+
line = line.curve(curveFactory);
|
|
83
|
+
}
|
|
84
|
+
const { style, connectorPadding, distance } = dataLabels;
|
|
85
|
+
const { maxHeight: labelHeight } = getLabelsSize({ labels: ['Some Label'], style });
|
|
86
|
+
const connectorStartPointGenerator = arc()
|
|
87
|
+
.innerRadius(data.radius)
|
|
88
|
+
.outerRadius(data.radius);
|
|
89
|
+
const connectorMidPointRadius = data.radius + distance / 2;
|
|
90
|
+
const connectorMidPointGenerator = arc()
|
|
91
|
+
.innerRadius(connectorMidPointRadius)
|
|
92
|
+
.outerRadius(connectorMidPointRadius);
|
|
93
|
+
const connectorArcRadius = data.radius + distance;
|
|
94
|
+
const connectorEndPointGenerator = arc()
|
|
95
|
+
.innerRadius(connectorArcRadius)
|
|
96
|
+
.outerRadius(connectorArcRadius);
|
|
97
|
+
const labelArcRadius = connectorArcRadius + connectorPadding;
|
|
98
|
+
const labelArcGenerator = arc()
|
|
99
|
+
.innerRadius(labelArcRadius)
|
|
100
|
+
.outerRadius(labelArcRadius);
|
|
101
|
+
series.forEach((d, index) => {
|
|
102
|
+
const prevLabel = labels[labels.length - 1];
|
|
103
|
+
const text = String(d.data.label || d.data.value);
|
|
104
|
+
const shouldUseHtml = dataLabels.html;
|
|
105
|
+
const labelSize = getLabelsSize({ labels: [text], style, html: shouldUseHtml });
|
|
106
|
+
const labelWidth = labelSize.maxWidth;
|
|
107
|
+
const relatedSegment = data.segments[index];
|
|
108
|
+
const getLabelPosition = (angle) => {
|
|
109
|
+
let [x, y] = labelArcGenerator.centroid(Object.assign(Object.assign({}, relatedSegment), { startAngle: angle, endAngle: angle }));
|
|
110
|
+
if (shouldUseHtml) {
|
|
111
|
+
x = x < 0 ? x - labelWidth : x;
|
|
112
|
+
y = y - labelSize.maxHeight;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
97
115
|
y = y < 0 ? y - labelHeight : y;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
116
|
+
}
|
|
117
|
+
x = Math.max(-boundsWidth / 2, x);
|
|
118
|
+
return [x, y];
|
|
119
|
+
};
|
|
120
|
+
const getConnectorPoints = (angle) => {
|
|
121
|
+
const connectorStartPoint = connectorStartPointGenerator.centroid(relatedSegment);
|
|
122
|
+
const connectorEndPoint = connectorEndPointGenerator.centroid(Object.assign(Object.assign({}, relatedSegment), { startAngle: angle, endAngle: angle }));
|
|
123
|
+
if (dataLabels.connectorShape === 'straight-line') {
|
|
124
|
+
return [connectorStartPoint, connectorEndPoint];
|
|
125
|
+
}
|
|
126
|
+
const connectorMidPoint = connectorMidPointGenerator.centroid(relatedSegment);
|
|
127
|
+
return [connectorStartPoint, connectorMidPoint, connectorEndPoint];
|
|
128
|
+
};
|
|
129
|
+
const midAngle = Math.max((prevLabel === null || prevLabel === void 0 ? void 0 : prevLabel.angle) || 0, relatedSegment.startAngle +
|
|
130
|
+
(relatedSegment.endAngle - relatedSegment.startAngle) / 2);
|
|
131
|
+
const [x, y] = getLabelPosition(midAngle);
|
|
132
|
+
const label = {
|
|
133
|
+
text,
|
|
134
|
+
x,
|
|
135
|
+
y,
|
|
136
|
+
style,
|
|
137
|
+
size: { width: labelWidth, height: labelHeight },
|
|
138
|
+
maxWidth: labelWidth,
|
|
139
|
+
textAnchor: midAngle < Math.PI ? 'start' : 'end',
|
|
140
|
+
series: { id: d.id },
|
|
141
|
+
active: true,
|
|
142
|
+
segment: relatedSegment.data,
|
|
143
|
+
angle: midAngle,
|
|
144
|
+
};
|
|
145
|
+
let overlap = false;
|
|
146
|
+
if (prevLabel) {
|
|
147
|
+
overlap = isLabelsOverlapping(prevLabel, label, dataLabels.padding);
|
|
148
|
+
if (overlap) {
|
|
149
|
+
let shouldAdjustAngle = true;
|
|
150
|
+
const step = Math.PI / 180;
|
|
151
|
+
while (shouldAdjustAngle) {
|
|
152
|
+
const newAngle = label.angle + step;
|
|
153
|
+
if (newAngle > FULL_CIRCLE && newAngle % FULL_CIRCLE > labels[0].angle) {
|
|
154
|
+
shouldAdjustAngle = false;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
label.angle = newAngle;
|
|
158
|
+
const [newX, newY] = getLabelPosition(newAngle);
|
|
159
|
+
label.x = newX;
|
|
160
|
+
label.y = newY;
|
|
161
|
+
if (!isLabelsOverlapping(prevLabel, label, dataLabels.padding)) {
|
|
139
162
|
shouldAdjustAngle = false;
|
|
140
|
-
|
|
141
|
-
else {
|
|
142
|
-
label.angle = newAngle;
|
|
143
|
-
const [newX, newY] = getLabelPosition(newAngle);
|
|
144
|
-
label.x = newX;
|
|
145
|
-
label.y = newY;
|
|
146
|
-
if (!isLabelsOverlapping(prevLabel, label, dataLabels.padding)) {
|
|
147
|
-
shouldAdjustAngle = false;
|
|
148
|
-
overlap = false;
|
|
149
|
-
}
|
|
163
|
+
overlap = false;
|
|
150
164
|
}
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
167
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
if (shouldUseHtml) {
|
|
166
|
-
data.htmlElements.push({
|
|
167
|
-
x: boundsWidth / 2 + label.x,
|
|
168
|
-
y: boundsHeight / 2 + label.y,
|
|
169
|
-
content: label.text,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
labels.push(label);
|
|
168
|
+
}
|
|
169
|
+
if (dataLabels.allowOverlap || !overlap) {
|
|
170
|
+
const left = getLeftPosition(label);
|
|
171
|
+
if (Math.abs(left) > boundsWidth / 2) {
|
|
172
|
+
label.maxWidth = label.size.width - (Math.abs(left) - boundsWidth / 2);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
const right = left + label.size.width;
|
|
176
|
+
if (right > boundsWidth / 2) {
|
|
177
|
+
label.maxWidth = label.size.width - (right - boundsWidth / 2);
|
|
174
178
|
}
|
|
175
|
-
const connector = {
|
|
176
|
-
path: line(getConnectorPoints(midAngle)),
|
|
177
|
-
color: relatedSegment.data.color,
|
|
178
|
-
};
|
|
179
|
-
data.connectors.push(connector);
|
|
180
179
|
}
|
|
181
|
-
|
|
182
|
-
|
|
180
|
+
if (shouldUseHtml) {
|
|
181
|
+
htmlLabels.push({
|
|
182
|
+
x: boundsWidth / 2 + label.x,
|
|
183
|
+
y: boundsHeight / 2 + label.y,
|
|
184
|
+
content: label.text,
|
|
185
|
+
size: label.size,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
labels.push(label);
|
|
190
|
+
}
|
|
191
|
+
const connector = {
|
|
192
|
+
path: line(getConnectorPoints(midAngle)),
|
|
193
|
+
color: relatedSegment.data.color,
|
|
194
|
+
};
|
|
195
|
+
connectors.push(connector);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return {
|
|
199
|
+
labels,
|
|
200
|
+
htmlLabels,
|
|
201
|
+
connectors,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
return Array.from(groupedPieSeries).map(([stackId, items]) => {
|
|
205
|
+
const data = prepareItem(stackId, items);
|
|
206
|
+
const preparedLabels = prepareLabels({
|
|
207
|
+
data,
|
|
208
|
+
series: items,
|
|
209
|
+
});
|
|
210
|
+
const allPreparedLabels = [...preparedLabels.labels, ...preparedLabels.htmlLabels];
|
|
211
|
+
const top = Math.min(data.center[1] - data.radius, ...allPreparedLabels.map((l) => l.y + data.center[1]));
|
|
212
|
+
const bottom = Math.max(data.center[1] + data.radius, ...allPreparedLabels.map((l) => data.center[1] + l.y + l.size.height));
|
|
213
|
+
const topAdjustment = Math.floor(top - data.halo.size);
|
|
214
|
+
if (topAdjustment > 0) {
|
|
215
|
+
// should adjust top position and height
|
|
216
|
+
data.radius += topAdjustment / 2;
|
|
217
|
+
data.center[1] -= topAdjustment / 2;
|
|
183
218
|
}
|
|
219
|
+
const bottomAdjustment = Math.floor(boundsHeight - bottom - data.halo.size);
|
|
220
|
+
if (bottomAdjustment > 0) {
|
|
221
|
+
// should adjust position and radius
|
|
222
|
+
data.radius += bottomAdjustment / 2;
|
|
223
|
+
data.center[1] += bottomAdjustment / 2;
|
|
224
|
+
}
|
|
225
|
+
const { labels, htmlLabels, connectors } = prepareLabels({
|
|
226
|
+
data,
|
|
227
|
+
series: items,
|
|
228
|
+
});
|
|
229
|
+
data.labels = labels;
|
|
230
|
+
data.htmlLabels = htmlLabels;
|
|
231
|
+
data.connectors = connectors;
|
|
184
232
|
return data;
|
|
185
233
|
});
|
|
186
234
|
}
|
|
@@ -3,7 +3,7 @@ import type { MeaningfulAny } from '../misc';
|
|
|
3
3
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
4
4
|
import type { ChartLegend, RectLegendSymbolOptions } from './legend';
|
|
5
5
|
import type { PointMarkerOptions } from './marker';
|
|
6
|
-
export
|
|
6
|
+
export interface AreaSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
|
|
7
7
|
/**
|
|
8
8
|
* The `x` value of the point. Depending on the context , it may represents:
|
|
9
9
|
* - numeric value (for `linear` x axis)
|
|
@@ -35,12 +35,12 @@ export type AreaSeriesData<T = MeaningfulAny> = BaseSeriesData<T> & {
|
|
|
35
35
|
};
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
-
}
|
|
38
|
+
}
|
|
39
39
|
export type AreaMarkerSymbol = 'circle' | 'square';
|
|
40
|
-
export
|
|
40
|
+
export interface AreaMarkerOptions extends PointMarkerOptions {
|
|
41
41
|
symbol?: AreaMarkerSymbol;
|
|
42
|
-
}
|
|
43
|
-
export
|
|
42
|
+
}
|
|
43
|
+
export interface AreaSeries<T = MeaningfulAny> extends BaseSeries {
|
|
44
44
|
type: typeof SeriesType.Area;
|
|
45
45
|
data: AreaSeriesData<T>[];
|
|
46
46
|
/** The name of the series (used in legend, tooltip etc) */
|
|
@@ -73,4 +73,4 @@ export type AreaSeries<T = MeaningfulAny> = BaseSeries & {
|
|
|
73
73
|
marker?: AreaMarkerOptions;
|
|
74
74
|
/** Y-axis index (when using two axes) */
|
|
75
75
|
yAxis?: number;
|
|
76
|
-
}
|
|
76
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { FormatNumberOptions } from '../formatter';
|
|
|
2
2
|
import type { BaseTextStyle } from './base';
|
|
3
3
|
export type ChartAxisType = 'category' | 'datetime' | 'linear' | 'logarithmic';
|
|
4
4
|
export type ChartAxisTitleAlignment = 'left' | 'center' | 'right';
|
|
5
|
-
export
|
|
5
|
+
export interface ChartAxisLabels {
|
|
6
6
|
/** Enable or disable the axis labels. */
|
|
7
7
|
enabled?: boolean;
|
|
8
8
|
/** The label's pixel distance from the perimeter of the plot area.
|
|
@@ -27,8 +27,8 @@ export type ChartAxisLabels = {
|
|
|
27
27
|
* @default: 0
|
|
28
28
|
*/
|
|
29
29
|
rotation?: number;
|
|
30
|
-
}
|
|
31
|
-
export
|
|
30
|
+
}
|
|
31
|
+
export interface ChartAxis {
|
|
32
32
|
categories?: string[];
|
|
33
33
|
timestamps?: number[];
|
|
34
34
|
type?: ChartAxisType;
|
|
@@ -72,9 +72,10 @@ export type ChartAxis = {
|
|
|
72
72
|
* Defaults to 0.05 for Y axis and to 0.01 for X axis.
|
|
73
73
|
* */
|
|
74
74
|
maxPadding?: number;
|
|
75
|
-
}
|
|
76
|
-
export
|
|
77
|
-
|
|
75
|
+
}
|
|
76
|
+
export interface ChartXAxis extends ChartAxis {
|
|
77
|
+
}
|
|
78
|
+
export interface ChartYAxis extends ChartAxis {
|
|
78
79
|
/** Axis location.
|
|
79
80
|
* Possible values - 'left' and 'right'.
|
|
80
81
|
* */
|
|
@@ -82,4 +83,4 @@ export type ChartYAxis = ChartAxis & {
|
|
|
82
83
|
/** Property for splitting charts. Determines which area the axis is located in.
|
|
83
84
|
* */
|
|
84
85
|
plotIndex?: number;
|
|
85
|
-
}
|
|
86
|
+
}
|
|
@@ -3,7 +3,7 @@ import type { MeaningfulAny } from '../misc';
|
|
|
3
3
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
4
4
|
import type { ChartLegend, RectLegendSymbolOptions } from './legend';
|
|
5
5
|
import type { ChartSeriesOptions } from './series';
|
|
6
|
-
export
|
|
6
|
+
export interface BarXSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
|
|
7
7
|
/**
|
|
8
8
|
* The `x` value of the bar. Depending on the context , it may represents:
|
|
9
9
|
* - numeric value (for `linear` x axis)
|
|
@@ -28,8 +28,8 @@ export type BarXSeriesData<T = MeaningfulAny> = BaseSeriesData<T> & {
|
|
|
28
28
|
label?: string | number;
|
|
29
29
|
/** Individual opacity for the bar-x column. */
|
|
30
30
|
opacity?: number;
|
|
31
|
-
}
|
|
32
|
-
export
|
|
31
|
+
}
|
|
32
|
+
export interface BarXSeries<T = MeaningfulAny> extends BaseSeries {
|
|
33
33
|
type: typeof SeriesType.BarX;
|
|
34
34
|
data: BarXSeriesData<T>[];
|
|
35
35
|
/** The name of the series (used in legend, tooltip etc) */
|
|
@@ -64,4 +64,4 @@ export type BarXSeries<T = MeaningfulAny> = BaseSeries & {
|
|
|
64
64
|
};
|
|
65
65
|
/** Y-axis index (when using two axes) */
|
|
66
66
|
yAxis?: number;
|
|
67
|
-
}
|
|
67
|
+
}
|