@gravity-ui/charts 0.8.0 → 0.10.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 +0 -3
- package/dist/cjs/components/Axis/AxisX.d.ts +1 -0
- package/dist/cjs/components/Axis/AxisX.js +43 -6
- package/dist/cjs/components/Axis/AxisY.js +9 -5
- package/dist/cjs/components/Axis/styles.css +5 -5
- package/dist/cjs/components/ChartInner/index.js +5 -4
- package/dist/cjs/components/ChartInner/styles.css +4 -4
- package/dist/cjs/components/ChartInner/useChartInnerHandlers.d.ts +1 -0
- package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +3 -4
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -2
- package/dist/cjs/components/Legend/index.js +1 -1
- package/dist/cjs/components/Legend/styles.css +14 -14
- package/dist/cjs/components/Title/index.js +1 -1
- package/dist/cjs/components/Title/styles.css +1 -1
- package/dist/cjs/components/Tooltip/DefaultContent.js +18 -3
- package/dist/cjs/constants/defaults/series-options.js +12 -0
- package/dist/cjs/constants/index.d.ts +1 -0
- package/dist/cjs/constants/index.js +1 -0
- package/dist/cjs/hooks/useChartOptions/tooltip.js +2 -1
- package/dist/cjs/hooks/useChartOptions/types.d.ts +2 -1
- package/dist/cjs/hooks/useChartOptions/x-axis.js +9 -2
- package/dist/cjs/hooks/useSeries/constants.js +1 -1
- package/dist/cjs/hooks/useSeries/prepare-radar.d.ts +16 -0
- package/dist/cjs/hooks/useSeries/prepare-radar.js +63 -0
- package/dist/cjs/hooks/useSeries/prepareSeries.js +8 -0
- package/dist/cjs/hooks/useSeries/types.d.ts +35 -2
- package/dist/cjs/hooks/useShapes/area/index.js +1 -1
- package/dist/cjs/hooks/useShapes/index.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/index.js +12 -0
- package/dist/cjs/hooks/useShapes/line/index.js +1 -1
- package/dist/cjs/hooks/useShapes/marker.d.ts +3 -2
- package/dist/cjs/hooks/useShapes/marker.js +1 -1
- package/dist/cjs/hooks/useShapes/pie/index.js +1 -1
- package/dist/cjs/hooks/useShapes/radar/index.d.ts +12 -0
- package/dist/cjs/hooks/useShapes/radar/index.js +136 -0
- package/dist/cjs/hooks/useShapes/radar/prepare-data.d.ts +9 -0
- package/dist/cjs/hooks/useShapes/radar/prepare-data.js +155 -0
- package/dist/cjs/hooks/useShapes/radar/types.d.ts +58 -0
- package/dist/cjs/hooks/useShapes/radar/types.js +1 -0
- package/dist/cjs/hooks/useShapes/scatter/index.js +1 -1
- package/dist/cjs/hooks/useShapes/styles.css +9 -5
- package/dist/cjs/hooks/useShapes/treemap/index.js +1 -1
- package/dist/cjs/hooks/useShapes/waterfall/index.js +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/types/chart/axis.d.ts +2 -2
- package/dist/cjs/types/chart/radar.d.ts +50 -0
- package/dist/cjs/types/chart/radar.js +1 -0
- package/dist/cjs/types/chart/series.d.ts +17 -2
- package/dist/cjs/types/chart/tooltip.d.ts +10 -1
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/utils/chart/get-closest-data.js +39 -2
- package/dist/cjs/utils/chart/index.js +1 -1
- package/dist/cjs/utils/{d3-dispatcher.d.ts → dispatcher.d.ts} +1 -1
- package/dist/cjs/utils/{d3-dispatcher.js → dispatcher.js} +1 -1
- package/dist/cjs/utils/index.d.ts +1 -1
- package/dist/cjs/utils/index.js +1 -1
- package/dist/esm/components/Axis/AxisX.d.ts +1 -0
- package/dist/esm/components/Axis/AxisX.js +43 -6
- package/dist/esm/components/Axis/AxisY.js +9 -5
- package/dist/esm/components/Axis/styles.css +5 -5
- package/dist/esm/components/ChartInner/index.js +5 -4
- package/dist/esm/components/ChartInner/styles.css +4 -4
- package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +1 -0
- package/dist/esm/components/ChartInner/useChartInnerHandlers.js +3 -4
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -2
- package/dist/esm/components/Legend/index.js +1 -1
- package/dist/esm/components/Legend/styles.css +14 -14
- package/dist/esm/components/Title/index.js +1 -1
- package/dist/esm/components/Title/styles.css +1 -1
- package/dist/esm/components/Tooltip/DefaultContent.js +18 -3
- package/dist/esm/constants/defaults/series-options.js +12 -0
- package/dist/esm/constants/index.d.ts +1 -0
- package/dist/esm/constants/index.js +1 -0
- package/dist/esm/hooks/useChartOptions/tooltip.js +2 -1
- package/dist/esm/hooks/useChartOptions/types.d.ts +2 -1
- package/dist/esm/hooks/useChartOptions/x-axis.js +9 -2
- package/dist/esm/hooks/useSeries/constants.js +1 -1
- package/dist/esm/hooks/useSeries/prepare-radar.d.ts +16 -0
- package/dist/esm/hooks/useSeries/prepare-radar.js +63 -0
- package/dist/esm/hooks/useSeries/prepareSeries.js +8 -0
- package/dist/esm/hooks/useSeries/types.d.ts +35 -2
- package/dist/esm/hooks/useShapes/area/index.js +1 -1
- package/dist/esm/hooks/useShapes/index.d.ts +2 -1
- package/dist/esm/hooks/useShapes/index.js +12 -0
- package/dist/esm/hooks/useShapes/line/index.js +1 -1
- package/dist/esm/hooks/useShapes/marker.d.ts +3 -2
- package/dist/esm/hooks/useShapes/marker.js +1 -1
- package/dist/esm/hooks/useShapes/pie/index.js +1 -1
- package/dist/esm/hooks/useShapes/radar/index.d.ts +12 -0
- package/dist/esm/hooks/useShapes/radar/index.js +136 -0
- package/dist/esm/hooks/useShapes/radar/prepare-data.d.ts +9 -0
- package/dist/esm/hooks/useShapes/radar/prepare-data.js +155 -0
- package/dist/esm/hooks/useShapes/radar/types.d.ts +58 -0
- package/dist/esm/hooks/useShapes/radar/types.js +1 -0
- package/dist/esm/hooks/useShapes/scatter/index.js +1 -1
- package/dist/esm/hooks/useShapes/styles.css +9 -5
- package/dist/esm/hooks/useShapes/treemap/index.js +1 -1
- package/dist/esm/hooks/useShapes/waterfall/index.js +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/chart/axis.d.ts +2 -2
- package/dist/esm/types/chart/radar.d.ts +50 -0
- package/dist/esm/types/chart/radar.js +1 -0
- package/dist/esm/types/chart/series.d.ts +17 -2
- package/dist/esm/types/chart/tooltip.d.ts +10 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/chart/get-closest-data.js +39 -2
- package/dist/esm/utils/chart/index.js +1 -1
- package/dist/esm/utils/{d3-dispatcher.d.ts → dispatcher.d.ts} +1 -1
- package/dist/esm/utils/{d3-dispatcher.js → dispatcher.js} +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# Gravity Charts · [](https://www.npmjs.com/package/@gravity-ui/charts) [](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [](https://preview.gravity-ui.com/charts/)
|
|
2
2
|
|
|
3
|
-
> [!WARNING]
|
|
4
|
-
> The library may have major changes in minor releases while it is on version `0.*.*`.
|
|
5
|
-
|
|
6
3
|
## Install
|
|
7
4
|
|
|
8
5
|
```shell
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { select } from 'd3';
|
|
3
|
-
import { block, formatAxisTickLabel, getAxisTitleRows, getClosestPointsRange, getMaxTickCount, getScaleTicks, getTicksCount, handleOverflowingText, } from '../../utils';
|
|
2
|
+
import { line, select } from 'd3';
|
|
3
|
+
import { block, formatAxisTickLabel, getAxisTitleRows, getClosestPointsRange, getLineDashArray, getMaxTickCount, getScaleTicks, getTicksCount, handleOverflowingText, } from '../../utils';
|
|
4
4
|
import { axisBottom } from '../../utils/chart/axis-generators';
|
|
5
5
|
import './styles.css';
|
|
6
|
-
const b = block('
|
|
6
|
+
const b = block('axis');
|
|
7
7
|
function getLabelFormatter({ axis, scale }) {
|
|
8
8
|
const ticks = getScaleTicks(scale);
|
|
9
9
|
const tickStep = getClosestPointsRange(axis, ticks);
|
|
@@ -42,7 +42,7 @@ export function getTitlePosition(args) {
|
|
|
42
42
|
return { x, y };
|
|
43
43
|
}
|
|
44
44
|
export const AxisX = React.memo(function AxisX(props) {
|
|
45
|
-
const { axis, width, height: totalHeight, scale, split } = props;
|
|
45
|
+
const { axis, width, height: totalHeight, scale, split, plotRef } = props;
|
|
46
46
|
const ref = React.useRef(null);
|
|
47
47
|
React.useEffect(() => {
|
|
48
48
|
if (!ref.current) {
|
|
@@ -57,8 +57,9 @@ export const AxisX = React.memo(function AxisX(props) {
|
|
|
57
57
|
return [-top, -(top + height)];
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
+
const axisScale = scale;
|
|
60
61
|
const xAxisGenerator = axisBottom({
|
|
61
|
-
scale:
|
|
62
|
+
scale: axisScale,
|
|
62
63
|
ticks: {
|
|
63
64
|
items: tickItems,
|
|
64
65
|
labelFormat: getLabelFormatter({ axis, scale }),
|
|
@@ -103,6 +104,42 @@ export const AxisX = React.memo(function AxisX(props) {
|
|
|
103
104
|
}
|
|
104
105
|
});
|
|
105
106
|
}
|
|
106
|
-
|
|
107
|
+
// add plot lines
|
|
108
|
+
if (plotRef && axis.plotLines.length > 0) {
|
|
109
|
+
const plotLineClassName = b('plotLine');
|
|
110
|
+
const plotLineContainer = select(plotRef.current);
|
|
111
|
+
plotLineContainer.selectAll(`.${plotLineClassName}-x`).remove();
|
|
112
|
+
const plotLinesSelection = plotLineContainer
|
|
113
|
+
.selectAll(`.${plotLineClassName}-x`)
|
|
114
|
+
.data(axis.plotLines)
|
|
115
|
+
.join('g')
|
|
116
|
+
.attr('class', `${plotLineClassName}-x`);
|
|
117
|
+
const lineGenerator = line();
|
|
118
|
+
plotLinesSelection
|
|
119
|
+
.append('path')
|
|
120
|
+
.attr('d', (plotLine) => {
|
|
121
|
+
const plotLineValue = Number(axisScale(plotLine.value));
|
|
122
|
+
const points = [
|
|
123
|
+
[plotLineValue, 0],
|
|
124
|
+
[plotLineValue, totalHeight],
|
|
125
|
+
];
|
|
126
|
+
return lineGenerator(points);
|
|
127
|
+
})
|
|
128
|
+
.attr('stroke', (plotLine) => plotLine.color)
|
|
129
|
+
.attr('stroke-width', (plotLine) => plotLine.width)
|
|
130
|
+
.attr('stroke-dasharray', (plotLine) => getLineDashArray(plotLine.dashStyle, plotLine.width))
|
|
131
|
+
.attr('opacity', (plotLine) => plotLine.opacity);
|
|
132
|
+
// set layer placement
|
|
133
|
+
plotLinesSelection.each((plotLineData, i, nodes) => {
|
|
134
|
+
const plotLineSelection = select(nodes[i]);
|
|
135
|
+
if (plotLineData.layerPlacement === 'before') {
|
|
136
|
+
plotLineSelection.lower();
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
plotLineSelection.raise();
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}, [axis, width, totalHeight, scale, split, plotRef]);
|
|
107
144
|
return React.createElement("g", { ref: ref });
|
|
108
145
|
});
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { axisLeft, axisRight, line, select } from 'd3';
|
|
3
3
|
import { block, calculateCos, calculateSin, formatAxisTickLabel, getAxisHeight, getAxisTitleRows, getClosestPointsRange, getLineDashArray, getScaleTicks, getTicksCount, handleOverflowingText, parseTransformStyle, setEllipsisForOverflowTexts, wrapText, } from '../../utils';
|
|
4
4
|
import './styles.css';
|
|
5
|
-
const b = block('
|
|
5
|
+
const b = block('axis');
|
|
6
6
|
function transformLabel(args) {
|
|
7
7
|
const { node, axis } = args;
|
|
8
8
|
let topOffset = axis.labels.lineHeight / 2;
|
|
@@ -56,11 +56,14 @@ function getTitlePosition(args) {
|
|
|
56
56
|
if (rowCount < 1) {
|
|
57
57
|
return { x: 0, y: 0 };
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
let x = axis.title.height -
|
|
60
60
|
axis.title.height / rowCount +
|
|
61
61
|
axis.title.margin +
|
|
62
62
|
axis.labels.margin +
|
|
63
|
-
axis.labels.width
|
|
63
|
+
axis.labels.width;
|
|
64
|
+
if (axis.position === 'left') {
|
|
65
|
+
x = x * -1;
|
|
66
|
+
}
|
|
64
67
|
let y;
|
|
65
68
|
switch (axis.title.align) {
|
|
66
69
|
case 'left': {
|
|
@@ -82,6 +85,7 @@ export const AxisY = (props) => {
|
|
|
82
85
|
const { axes, width, height: totalHeight, scale, split, plotRef } = props;
|
|
83
86
|
const height = getAxisHeight({ split, boundsHeight: totalHeight });
|
|
84
87
|
const ref = React.useRef(null);
|
|
88
|
+
const lineGenerator = line();
|
|
85
89
|
React.useEffect(() => {
|
|
86
90
|
if (!ref.current) {
|
|
87
91
|
return;
|
|
@@ -174,7 +178,7 @@ export const AxisY = (props) => {
|
|
|
174
178
|
[0, plotLineValue],
|
|
175
179
|
[width, plotLineValue],
|
|
176
180
|
];
|
|
177
|
-
return
|
|
181
|
+
return lineGenerator(points);
|
|
178
182
|
})
|
|
179
183
|
.attr('stroke', (plotLine) => plotLine.color)
|
|
180
184
|
.attr('stroke-width', (plotLine) => plotLine.width)
|
|
@@ -199,7 +203,7 @@ export const AxisY = (props) => {
|
|
|
199
203
|
[0, 0],
|
|
200
204
|
[0, height],
|
|
201
205
|
];
|
|
202
|
-
return
|
|
206
|
+
return lineGenerator(points);
|
|
203
207
|
})
|
|
204
208
|
.style('stroke', (d) => d.lineColor || '');
|
|
205
209
|
svgElement.selectAll('.tick').each((_d, index, nodes) => {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
.gcharts-
|
|
1
|
+
.gcharts-axis .domain {
|
|
2
2
|
stroke: var(--g-color-line-generic-active);
|
|
3
3
|
}
|
|
4
|
-
.gcharts-
|
|
4
|
+
.gcharts-axis .tick text {
|
|
5
5
|
color: var(--g-color-text-secondary);
|
|
6
6
|
alignment-baseline: after-edge;
|
|
7
7
|
}
|
|
8
|
-
.gcharts-
|
|
8
|
+
.gcharts-axis .tick line, .gcharts-axis .tick path {
|
|
9
9
|
stroke: var(--g-color-line-generic);
|
|
10
10
|
}
|
|
11
|
-
.gcharts-
|
|
11
|
+
.gcharts-axis__title {
|
|
12
12
|
alignment-baseline: after-edge;
|
|
13
13
|
fill: var(--g-color-text-secondary);
|
|
14
14
|
}
|
|
15
|
-
.gcharts-
|
|
15
|
+
.gcharts-axis__title tspan {
|
|
16
16
|
alignment-baseline: after-edge;
|
|
17
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { EventType, block,
|
|
2
|
+
import { EventType, block, getDispatcher } from '../../utils';
|
|
3
3
|
import { AxisX, AxisY } from '../Axis';
|
|
4
4
|
import { Legend } from '../Legend';
|
|
5
5
|
import { PlotTitle } from '../PlotTitle';
|
|
@@ -9,14 +9,14 @@ import { useChartInnerHandlers } from './useChartInnerHandlers';
|
|
|
9
9
|
import { useChartInnerProps } from './useChartInnerProps';
|
|
10
10
|
import { useChartInnerState } from './useChartInnerState';
|
|
11
11
|
import './styles.css';
|
|
12
|
-
const b = block('
|
|
12
|
+
const b = block('chart');
|
|
13
13
|
export const ChartInner = (props) => {
|
|
14
14
|
var _a, _b, _c, _d;
|
|
15
15
|
const { width, height, data } = props;
|
|
16
16
|
const svgRef = React.useRef(null);
|
|
17
17
|
const htmlLayerRef = React.useRef(null);
|
|
18
18
|
const plotRef = React.useRef(null);
|
|
19
|
-
const dispatcher = React.useMemo(() =>
|
|
19
|
+
const dispatcher = React.useMemo(() => getDispatcher(), []);
|
|
20
20
|
const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, legendConfig, legendItems, preparedSeries, preparedSplit, preparedLegend, prevHeight, prevWidth, shapes, shapesData, title, tooltip, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { dispatcher, htmlLayout: htmlLayerRef.current }));
|
|
21
21
|
const { tooltipPinned, togglePinTooltip, unpinTooltip } = useChartInnerState({
|
|
22
22
|
dispatcher,
|
|
@@ -35,6 +35,7 @@ export const ChartInner = (props) => {
|
|
|
35
35
|
unpinTooltip,
|
|
36
36
|
xAxis,
|
|
37
37
|
yAxis,
|
|
38
|
+
tooltipThrottle: tooltip.throttle,
|
|
38
39
|
});
|
|
39
40
|
const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
|
|
40
41
|
const pointerMoveHandler = (_d = (_c = data.chart) === null || _c === void 0 ? void 0 : _c.events) === null || _d === void 0 ? void 0 : _d.pointermove;
|
|
@@ -68,7 +69,7 @@ export const ChartInner = (props) => {
|
|
|
68
69
|
xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length) && (React.createElement(React.Fragment, null,
|
|
69
70
|
React.createElement(AxisY, { axes: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale, split: preparedSplit, plotRef: plotRef }),
|
|
70
71
|
React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
|
|
71
|
-
React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit })))),
|
|
72
|
+
React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit, plotRef: plotRef })))),
|
|
72
73
|
shapes),
|
|
73
74
|
preparedLegend.enabled && (React.createElement(Legend, { chartSeries: preparedSeries, boundsWidth: boundsWidth, legend: preparedLegend, items: legendItems, config: legendConfig, onItemClick: handleLegendItemClick, onUpdate: unpinTooltip }))),
|
|
74
75
|
React.createElement("div", { className: b('html-layer'), ref: htmlLayerRef, style: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
.gcharts-
|
|
2
|
-
--
|
|
1
|
+
.gcharts-chart {
|
|
2
|
+
--gcharts-data-labels: var(--g-color-text-secondary);
|
|
3
3
|
position: absolute;
|
|
4
4
|
}
|
|
5
|
-
.gcharts-
|
|
5
|
+
.gcharts-chart__html-layer {
|
|
6
6
|
display: contents;
|
|
7
7
|
}
|
|
8
|
-
.gcharts-
|
|
8
|
+
.gcharts-chart__html-layer > * {
|
|
9
9
|
transform: inherit;
|
|
10
10
|
}
|
|
@@ -16,6 +16,7 @@ type Props = {
|
|
|
16
16
|
unpinTooltip: ChartInnerState['unpinTooltip'];
|
|
17
17
|
xAxis: PreparedAxis;
|
|
18
18
|
yAxis: PreparedAxis[];
|
|
19
|
+
tooltipThrottle: number;
|
|
19
20
|
};
|
|
20
21
|
export declare function useChartInnerHandlers(props: Props): {
|
|
21
22
|
handleChartClick: (event: React.MouseEvent<SVGSVGElement>) => void;
|
|
@@ -4,9 +4,8 @@ import throttle from 'lodash/throttle';
|
|
|
4
4
|
import { IS_TOUCH_ENABLED } from '../../constants';
|
|
5
5
|
import { EventType } from '../../utils';
|
|
6
6
|
import { getClosestPoints } from '../../utils/chart/get-closest-data';
|
|
7
|
-
const THROTTLE_DELAY = 50;
|
|
8
7
|
export function useChartInnerHandlers(props) {
|
|
9
|
-
const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, } = props;
|
|
8
|
+
const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, dispatcher, shapesData, svgContainer, togglePinTooltip, tooltipPinned, unpinTooltip, xAxis, yAxis, tooltipThrottle, } = props;
|
|
10
9
|
const isOutsideBounds = React.useCallback((x, y) => {
|
|
11
10
|
return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
|
|
12
11
|
}, [boundsHeight, boundsWidth]);
|
|
@@ -40,7 +39,7 @@ export function useChartInnerHandlers(props) {
|
|
|
40
39
|
};
|
|
41
40
|
const throttledHandleMouseMove = IS_TOUCH_ENABLED
|
|
42
41
|
? undefined
|
|
43
|
-
: throttle(handleMouseMove,
|
|
42
|
+
: throttle(handleMouseMove, tooltipThrottle);
|
|
44
43
|
const handleMouseLeave = (event) => {
|
|
45
44
|
if (tooltipPinned) {
|
|
46
45
|
return;
|
|
@@ -55,7 +54,7 @@ export function useChartInnerHandlers(props) {
|
|
|
55
54
|
handleMove([pointerX, pointerY], event);
|
|
56
55
|
};
|
|
57
56
|
const throttledHandleTouchMove = IS_TOUCH_ENABLED
|
|
58
|
-
? throttle(handleTouchMove,
|
|
57
|
+
? throttle(handleTouchMove, tooltipThrottle)
|
|
59
58
|
: undefined;
|
|
60
59
|
const handleChartClick = (event) => {
|
|
61
60
|
const [pointerX, pointerY] = pointer(event, svgContainer);
|
|
@@ -29,11 +29,12 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
29
29
|
prevWidth: number | undefined;
|
|
30
30
|
shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
|
|
31
31
|
shapesData: import("../../hooks").ShapeData[];
|
|
32
|
-
title: (import("
|
|
32
|
+
title: (import("../..").ChartTitle & {
|
|
33
33
|
height: number;
|
|
34
34
|
}) | undefined;
|
|
35
|
-
tooltip: import("
|
|
35
|
+
tooltip: import("../..").ChartTooltip<any> & {
|
|
36
36
|
enabled: boolean;
|
|
37
|
+
throttle: number;
|
|
37
38
|
};
|
|
38
39
|
xAxis: import("../../hooks").PreparedAxis;
|
|
39
40
|
xScale: import("../../hooks").ChartScale | undefined;
|
|
@@ -5,7 +5,7 @@ import { formatNumber } from '../../libs';
|
|
|
5
5
|
import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getLineDashArray, getSymbol, } from '../../utils';
|
|
6
6
|
import { axisBottom } from '../../utils/chart/axis-generators';
|
|
7
7
|
import './styles.css';
|
|
8
|
-
const b = block('
|
|
8
|
+
const b = block('legend');
|
|
9
9
|
const getLegendPosition = (args) => {
|
|
10
10
|
const { align, offsetWidth = 0, width, contentWidth } = args;
|
|
11
11
|
const top = 0;
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
.gcharts-
|
|
1
|
+
.gcharts-legend {
|
|
2
2
|
color: var(--g-color-text-secondary);
|
|
3
3
|
}
|
|
4
|
-
.gcharts-
|
|
4
|
+
.gcharts-legend__title {
|
|
5
5
|
fill: var(--g-color-text-secondary);
|
|
6
6
|
}
|
|
7
|
-
.gcharts-
|
|
7
|
+
.gcharts-legend__item {
|
|
8
8
|
cursor: pointer;
|
|
9
9
|
user-select: none;
|
|
10
10
|
}
|
|
11
|
-
.gcharts-
|
|
11
|
+
.gcharts-legend__item-symbol_shape_rect.gcharts-legend__item-symbol_unselected {
|
|
12
12
|
fill: var(--g-color-text-hint);
|
|
13
13
|
}
|
|
14
|
-
.gcharts-
|
|
14
|
+
.gcharts-legend__item-symbol_shape_path.gcharts-legend__item-symbol_unselected {
|
|
15
15
|
stroke: var(--g-color-text-hint);
|
|
16
16
|
}
|
|
17
|
-
.gcharts-
|
|
17
|
+
.gcharts-legend__item-symbol_shape_symbol.gcharts-legend__item-symbol_unselected {
|
|
18
18
|
fill: var(--g-color-text-hint);
|
|
19
19
|
}
|
|
20
|
-
.gcharts-
|
|
20
|
+
.gcharts-legend__item-text {
|
|
21
21
|
fill: var(--g-color-text-secondary);
|
|
22
22
|
alignment-baseline: before-edge;
|
|
23
23
|
}
|
|
24
|
-
.gcharts-
|
|
24
|
+
.gcharts-legend__item-text_unselected {
|
|
25
25
|
fill: var(--g-color-text-hint);
|
|
26
26
|
}
|
|
27
|
-
.gcharts-
|
|
27
|
+
.gcharts-legend__item-text:hover {
|
|
28
28
|
fill: var(--g-color-text-complementary);
|
|
29
29
|
}
|
|
30
|
-
.gcharts-
|
|
30
|
+
.gcharts-legend__pagination {
|
|
31
31
|
user-select: none;
|
|
32
32
|
fill: var(--g-color-text-primary);
|
|
33
33
|
}
|
|
34
|
-
.gcharts-
|
|
34
|
+
.gcharts-legend__pagination-counter, .gcharts-legend__pagination-arrow {
|
|
35
35
|
alignment-baseline: middle;
|
|
36
36
|
}
|
|
37
|
-
.gcharts-
|
|
37
|
+
.gcharts-legend__pagination-arrow {
|
|
38
38
|
cursor: pointer;
|
|
39
39
|
fill: var(--g-color-text-brand);
|
|
40
40
|
}
|
|
41
|
-
.gcharts-
|
|
41
|
+
.gcharts-legend__pagination-arrow_inactive {
|
|
42
42
|
cursor: inherit;
|
|
43
43
|
fill: var(--g-color-base-generic-accent-disabled);
|
|
44
44
|
}
|
|
45
|
-
.gcharts-
|
|
45
|
+
.gcharts-legend__pagination-arrow:hover:not(.gcharts-legend__pagination-arrow_inactive) {
|
|
46
46
|
fill: var(--g-color-base-brand-hover);
|
|
47
47
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { block } from '../../utils';
|
|
3
3
|
import './styles.css';
|
|
4
|
-
const b = block('
|
|
4
|
+
const b = block('title');
|
|
5
5
|
export const Title = (props) => {
|
|
6
6
|
const { chartWidth, text, height, style } = props;
|
|
7
7
|
return (React.createElement("text", { className: b(), dx: chartWidth / 2, dy: height / 2, dominantBaseline: "middle", textAnchor: "middle", style: Object.assign({ lineHeight: `${height}px` }, style) },
|
|
@@ -28,14 +28,17 @@ const getRowData = (fieldName, data, axis) => {
|
|
|
28
28
|
const getXRowData = (data, xAxis) => getRowData('x', data, xAxis);
|
|
29
29
|
const getYRowData = (data, yAxis) => getRowData('y', data, yAxis);
|
|
30
30
|
const getMeasureValue = (data, xAxis, yAxis) => {
|
|
31
|
-
var _a, _b;
|
|
31
|
+
var _a, _b, _c, _d;
|
|
32
32
|
if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
+
if (data.some((item) => item.series.type === 'radar')) {
|
|
36
|
+
return (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
|
|
37
|
+
}
|
|
35
38
|
if (data.some((item) => item.series.type === 'bar-y')) {
|
|
36
|
-
return getYRowData((
|
|
39
|
+
return getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis);
|
|
37
40
|
}
|
|
38
|
-
return getXRowData((
|
|
41
|
+
return getXRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, xAxis);
|
|
39
42
|
};
|
|
40
43
|
export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
41
44
|
const measureValue = getMeasureValue(hovered, xAxis, yAxis);
|
|
@@ -109,6 +112,18 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
|
109
112
|
": ",
|
|
110
113
|
value)));
|
|
111
114
|
}
|
|
115
|
+
case 'radar': {
|
|
116
|
+
const radarSeries = series;
|
|
117
|
+
const seriesData = data;
|
|
118
|
+
const value = (React.createElement(React.Fragment, null,
|
|
119
|
+
React.createElement("span", null,
|
|
120
|
+
radarSeries.name || radarSeries.id,
|
|
121
|
+
"\u00A0"),
|
|
122
|
+
React.createElement("span", null, seriesData.value)));
|
|
123
|
+
return (React.createElement("div", { key: id, className: b('content-row') },
|
|
124
|
+
React.createElement("div", { className: b('color'), style: { backgroundColor: color } }),
|
|
125
|
+
React.createElement("div", null, closest ? React.createElement("b", null, value) : React.createElement("span", null, value))));
|
|
126
|
+
}
|
|
112
127
|
default: {
|
|
113
128
|
return null;
|
|
114
129
|
}
|
|
@@ -89,6 +89,18 @@ export const seriesOptionsDefaults = {
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
|
+
radar: {
|
|
93
|
+
states: {
|
|
94
|
+
hover: {
|
|
95
|
+
enabled: true,
|
|
96
|
+
brightness: 0.3,
|
|
97
|
+
},
|
|
98
|
+
inactive: {
|
|
99
|
+
enabled: true,
|
|
100
|
+
opacity: 0.5,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
92
104
|
waterfall: {
|
|
93
105
|
barMaxWidth: 50,
|
|
94
106
|
barPadding: 0.1,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
export const getPreparedTooltip = (args) => {
|
|
3
|
+
var _a;
|
|
3
4
|
const { tooltip } = args;
|
|
4
|
-
return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true) });
|
|
5
|
+
return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0 });
|
|
5
6
|
};
|
|
@@ -19,7 +19,7 @@ export type PreparedAxisPlotLine = {
|
|
|
19
19
|
opacity: number;
|
|
20
20
|
layerPlacement: AxisPlotLine['layerPlacement'];
|
|
21
21
|
};
|
|
22
|
-
export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels'> & {
|
|
22
|
+
export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines'> & {
|
|
23
23
|
type: ChartAxisType;
|
|
24
24
|
labels: PreparedAxisLabels;
|
|
25
25
|
title: {
|
|
@@ -48,6 +48,7 @@ export type PreparedTitle = ChartData['title'] & {
|
|
|
48
48
|
};
|
|
49
49
|
export type PreparedTooltip = ChartData['tooltip'] & {
|
|
50
50
|
enabled: boolean;
|
|
51
|
+
throttle: number;
|
|
51
52
|
};
|
|
52
53
|
export type ChartOptions = {
|
|
53
54
|
chart: PreparedChart;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import { DEFAULT_AXIS_LABEL_FONT_SIZE, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DashStyle, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
|
|
3
3
|
import { CHART_SERIES_WITH_VOLUME_ON_X_AXIS, calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
|
|
4
4
|
import { createXScale } from '../useAxisScales';
|
|
5
5
|
function getLabelSettings({ axis, series, width, autoRotation = true, }) {
|
|
@@ -102,7 +102,14 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
|
|
|
102
102
|
},
|
|
103
103
|
position: 'bottom',
|
|
104
104
|
plotIndex: 0,
|
|
105
|
-
plotLines: []
|
|
105
|
+
plotLines: get(xAxis, 'plotLines', []).map((d) => ({
|
|
106
|
+
value: get(d, 'value', 0),
|
|
107
|
+
color: get(d, 'color', 'var(--g-color-base-brand)'),
|
|
108
|
+
width: get(d, 'width', 1),
|
|
109
|
+
dashStyle: get(d, 'dashStyle', DashStyle.Solid),
|
|
110
|
+
opacity: get(d, 'opacity', 1),
|
|
111
|
+
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
112
|
+
})),
|
|
106
113
|
};
|
|
107
114
|
const { height, rotation } = getLabelSettings({
|
|
108
115
|
axis: preparedXAxis,
|
|
@@ -4,7 +4,7 @@ export const DEFAULT_DATALABELS_PADDING = 5;
|
|
|
4
4
|
export const DEFAULT_DATALABELS_STYLE = {
|
|
5
5
|
fontSize: '11px',
|
|
6
6
|
fontWeight: 'bold',
|
|
7
|
-
fontColor: 'var(--
|
|
7
|
+
fontColor: 'var(--gcharts-data-labels)',
|
|
8
8
|
};
|
|
9
9
|
export const DEFAULT_HALO_OPTIONS = {
|
|
10
10
|
enabled: true,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ChartSeriesOptions, RadarSeries } from '../../types';
|
|
2
|
+
import type { PreparedLegend, PreparedRadarSeries } from './types';
|
|
3
|
+
type PrepareRadarSeriesArgs = {
|
|
4
|
+
series: RadarSeries[];
|
|
5
|
+
seriesOptions?: ChartSeriesOptions;
|
|
6
|
+
legend: PreparedLegend;
|
|
7
|
+
};
|
|
8
|
+
export declare const DEFAULT_MARKER: {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
radius: number;
|
|
11
|
+
symbol: `${import("../../constants").SymbolType}`;
|
|
12
|
+
borderColor: string;
|
|
13
|
+
borderWidth: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function prepareRadarSeries(args: PrepareRadarSeriesArgs): PreparedRadarSeries[];
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { scaleOrdinal } from 'd3';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
import merge from 'lodash/merge';
|
|
4
|
+
import { DEFAULT_PALETTE } from '../../constants';
|
|
5
|
+
import { getUniqId } from '../../utils';
|
|
6
|
+
import { DEFAULT_DATALABELS_PADDING, DEFAULT_DATALABELS_STYLE, DEFAULT_HALO_OPTIONS, DEFAULT_POINT_MARKER_OPTIONS, } from './constants';
|
|
7
|
+
import { prepareLegendSymbol } from './utils';
|
|
8
|
+
export const DEFAULT_MARKER = Object.assign(Object.assign({}, DEFAULT_POINT_MARKER_OPTIONS), { enabled: true, radius: 2 });
|
|
9
|
+
function prepareMarker(series, seriesOptions) {
|
|
10
|
+
var _a;
|
|
11
|
+
const seriesHoverState = get(seriesOptions, 'radar.states.hover');
|
|
12
|
+
const markerNormalState = Object.assign({}, DEFAULT_MARKER, (_a = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions.radar) === null || _a === void 0 ? void 0 : _a.marker, series.marker);
|
|
13
|
+
const hoveredMarkerDefaultOptions = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
radius: markerNormalState.radius + 1,
|
|
16
|
+
borderWidth: 1,
|
|
17
|
+
borderColor: '#ffffff',
|
|
18
|
+
halo: DEFAULT_HALO_OPTIONS,
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
states: {
|
|
22
|
+
normal: markerNormalState,
|
|
23
|
+
hover: merge(hoveredMarkerDefaultOptions, seriesHoverState === null || seriesHoverState === void 0 ? void 0 : seriesHoverState.marker),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function prepareRadarSeries(args) {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const { series: radarSeries, seriesOptions, legend } = args;
|
|
30
|
+
const colorScale = scaleOrdinal(radarSeries.map((s, index) => { var _a; return (_a = s.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`; }), DEFAULT_PALETTE);
|
|
31
|
+
const categories = (_b = (_a = radarSeries.find((s) => s.categories)) === null || _a === void 0 ? void 0 : _a.categories) !== null && _b !== void 0 ? _b : [];
|
|
32
|
+
return radarSeries.map((series, index) => {
|
|
33
|
+
var _a, _b, _c, _d, _e;
|
|
34
|
+
const name = (_a = series.name) !== null && _a !== void 0 ? _a : `Series ${index + 1}`;
|
|
35
|
+
const color = (_b = series.color) !== null && _b !== void 0 ? _b : colorScale(name);
|
|
36
|
+
const preparedSeries = {
|
|
37
|
+
type: 'radar',
|
|
38
|
+
data: series.data,
|
|
39
|
+
categories,
|
|
40
|
+
id: getUniqId(),
|
|
41
|
+
name,
|
|
42
|
+
color,
|
|
43
|
+
visible: typeof series.visible === 'boolean' ? series.visible : true,
|
|
44
|
+
legend: {
|
|
45
|
+
enabled: get(series, 'legend.enabled', legend.enabled),
|
|
46
|
+
symbol: prepareLegendSymbol(series),
|
|
47
|
+
},
|
|
48
|
+
borderColor: series.borderColor || color,
|
|
49
|
+
borderWidth: (_c = series.borderWidth) !== null && _c !== void 0 ? _c : 1,
|
|
50
|
+
fillOpacity: (_d = series.fillOpacity) !== null && _d !== void 0 ? _d : 0.25,
|
|
51
|
+
dataLabels: {
|
|
52
|
+
enabled: get(series, 'dataLabels.enabled', true),
|
|
53
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_e = series.dataLabels) === null || _e === void 0 ? void 0 : _e.style),
|
|
54
|
+
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
55
|
+
allowOverlap: get(series, 'dataLabels.allowOverlap', false),
|
|
56
|
+
html: get(series, 'dataLabels.html', false),
|
|
57
|
+
},
|
|
58
|
+
cursor: get(series, 'cursor', null),
|
|
59
|
+
marker: prepareMarker(series, seriesOptions),
|
|
60
|
+
};
|
|
61
|
+
return preparedSeries;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
@@ -4,6 +4,7 @@ import { prepareBarXSeries } from './prepare-bar-x';
|
|
|
4
4
|
import { prepareBarYSeries } from './prepare-bar-y';
|
|
5
5
|
import { prepareLineSeries } from './prepare-line';
|
|
6
6
|
import { preparePieSeries } from './prepare-pie';
|
|
7
|
+
import { prepareRadarSeries } from './prepare-radar';
|
|
7
8
|
import { prepareSankeySeries } from './prepare-sankey';
|
|
8
9
|
import { prepareScatterSeries } from './prepare-scatter';
|
|
9
10
|
import { prepareTreemap } from './prepare-treemap';
|
|
@@ -75,6 +76,13 @@ export function prepareSeries(args) {
|
|
|
75
76
|
legend,
|
|
76
77
|
});
|
|
77
78
|
}
|
|
79
|
+
case 'radar': {
|
|
80
|
+
return prepareRadarSeries({
|
|
81
|
+
series: series,
|
|
82
|
+
seriesOptions,
|
|
83
|
+
legend,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
78
86
|
default: {
|
|
79
87
|
throw new ChartError({
|
|
80
88
|
message: `Series type "${type}" does not support data preparation for series that do not support the presence of axes`,
|