@gravity-ui/chartkit 4.8.0 → 4.9.1
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/components/ChartKit.d.ts +1 -1
- package/build/components/ChartKit.js +1 -1
- package/build/components/Loader/Loader.d.ts +5 -2
- package/build/components/Loader/Loader.js +8 -1
- package/build/plugins/d3/examples/bar-x/GroupedColumns.js +4 -2
- package/build/plugins/d3/examples/bar-y/Basic.d.ts +2 -0
- package/build/plugins/d3/examples/bar-y/Basic.js +43 -0
- package/build/plugins/d3/examples/bar-y/GroupedColumns.d.ts +2 -0
- package/build/plugins/d3/examples/bar-y/GroupedColumns.js +48 -0
- package/build/plugins/d3/examples/bar-y/StackedColumns.d.ts +2 -0
- package/build/plugins/d3/examples/bar-y/StackedColumns.js +47 -0
- package/build/plugins/d3/examples/combined/LineAndBarX.d.ts +2 -0
- package/build/plugins/d3/examples/combined/LineAndBarX.js +61 -0
- package/build/plugins/d3/examples/line/Basic.d.ts +2 -0
- package/build/plugins/d3/examples/line/Basic.js +66 -0
- package/build/plugins/d3/examples/nintendoGames.d.ts +40 -10
- package/build/plugins/d3/examples/nintendoGames.js +2416 -2189
- package/build/plugins/d3/renderer/D3Widget.d.ts +1 -1
- package/build/plugins/d3/renderer/D3Widget.js +27 -11
- package/build/plugins/d3/renderer/components/Chart.d.ts +0 -2
- package/build/plugins/d3/renderer/components/Chart.js +4 -6
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.d.ts +2 -2
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +42 -35
- package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.d.ts +0 -2
- package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.js +118 -48
- package/build/plugins/d3/renderer/components/Tooltip/index.d.ts +1 -0
- package/build/plugins/d3/renderer/components/Tooltip/index.js +5 -4
- package/build/plugins/d3/renderer/components/styles.css +1 -0
- package/build/plugins/d3/renderer/constants/defaults/series-options.d.ts +9 -2
- package/build/plugins/d3/renderer/constants/defaults/series-options.js +27 -0
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +15 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +3 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +3 -3
- package/build/plugins/d3/renderer/hooks/useSeries/constants.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useSeries/constants.js +5 -0
- package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +1 -1
- package/build/plugins/d3/renderer/hooks/useSeries/index.js +2 -1
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.d.ts +10 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.js +38 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.d.ts +10 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.js +50 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-line-series.d.ts +11 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-line-series.js +32 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +21 -60
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +24 -2
- package/build/plugins/d3/renderer/hooks/useSeries/utils.d.ts +3 -1
- package/build/plugins/d3/renderer/hooks/useSeries/utils.js +13 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +4 -6
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.d.ts +11 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.js +87 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.d.ts +12 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +114 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.d.ts +10 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/constants.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useShapes/constants.js +3 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +4 -4
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +35 -5
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.d.ts +11 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.js +98 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.d.ts +11 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +21 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/types.d.ts +16 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/types.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +0 -2
- package/build/plugins/d3/renderer/hooks/useShapes/pie.js +3 -3
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.d.ts +0 -2
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +6 -6
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +3 -34
- package/build/plugins/d3/renderer/hooks/useShapes/styles.css +6 -0
- package/build/plugins/d3/renderer/hooks/useShapes/utils.d.ts +17 -0
- package/build/plugins/d3/renderer/hooks/useShapes/utils.js +25 -0
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +3 -3
- package/build/plugins/d3/renderer/utils/text.d.ts +5 -7
- package/build/plugins/d3/renderer/utils/text.js +4 -15
- package/build/plugins/highcharts/renderer/HighchartsWidget.d.ts +1 -1
- package/build/plugins/indicator/renderer/IndicatorWidget.d.ts +1 -1
- package/build/plugins/yagr/renderer/YagrWidget.d.ts +1 -1
- package/build/types/index.d.ts +2 -1
- package/build/types/widget-data/bar-y.d.ts +55 -0
- package/build/types/widget-data/bar-y.js +1 -0
- package/build/types/widget-data/base.d.ts +4 -0
- package/build/types/widget-data/index.d.ts +2 -0
- package/build/types/widget-data/index.js +2 -0
- package/build/types/widget-data/line.d.ts +37 -0
- package/build/types/widget-data/line.js +1 -0
- package/build/types/widget-data/series.d.ts +53 -3
- package/build/types/widget-data/tooltip.d.ts +15 -1
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/performance.d.ts +3 -0
- package/build/utils/performance.js +8 -0
- package/package.json +3 -2
|
@@ -5,13 +5,13 @@ import type { ChartScale } from '../useAxisScales';
|
|
|
5
5
|
import type { PreparedSeries, PreparedSeriesOptions } from '../';
|
|
6
6
|
import type { PreparedBarXData } from './bar-x';
|
|
7
7
|
import type { PreparedScatterData } from './scatter';
|
|
8
|
-
import './
|
|
8
|
+
import type { PreparedLineData } from './line/types';
|
|
9
|
+
import type { PreparedBarYData } from './bar-y/types';
|
|
9
10
|
export type { PreparedBarXData } from './bar-x';
|
|
10
11
|
export type { PreparedScatterData } from './scatter';
|
|
11
|
-
|
|
12
|
+
import './styles.css';
|
|
13
|
+
export type ShapeData = PreparedBarXData | PreparedBarYData | PreparedScatterData | PreparedLineData;
|
|
12
14
|
type Args = {
|
|
13
|
-
top: number;
|
|
14
|
-
left: number;
|
|
15
15
|
boundsWidth: number;
|
|
16
16
|
boundsHeight: number;
|
|
17
17
|
dispatcher: Dispatch<object>;
|
|
@@ -4,9 +4,12 @@ import { getOnlyVisibleSeries } from '../../utils';
|
|
|
4
4
|
import { BarXSeriesShapes, prepareBarXData } from './bar-x';
|
|
5
5
|
import { ScatterSeriesShape, prepareScatterData } from './scatter';
|
|
6
6
|
import { PieSeriesComponent } from './pie';
|
|
7
|
+
import { prepareLineData } from './line/prepare-data';
|
|
8
|
+
import { LineSeriesShapes } from './line';
|
|
9
|
+
import { BarYSeriesShapes, prepareBarYData } from './bar-y';
|
|
7
10
|
import './styles.css';
|
|
8
11
|
export const useShapes = (args) => {
|
|
9
|
-
const {
|
|
12
|
+
const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, svgContainer, } = args;
|
|
10
13
|
const shapesComponents = React.useMemo(() => {
|
|
11
14
|
const visibleSeries = getOnlyVisibleSeries(series);
|
|
12
15
|
const groupedSeries = group(visibleSeries, (item) => item.type);
|
|
@@ -29,6 +32,35 @@ export const useShapes = (args) => {
|
|
|
29
32
|
}
|
|
30
33
|
break;
|
|
31
34
|
}
|
|
35
|
+
case 'bar-y': {
|
|
36
|
+
if (xScale && yScale) {
|
|
37
|
+
const preparedData = prepareBarYData({
|
|
38
|
+
series: chartSeries,
|
|
39
|
+
seriesOptions,
|
|
40
|
+
xAxis,
|
|
41
|
+
xScale,
|
|
42
|
+
yAxis,
|
|
43
|
+
yScale,
|
|
44
|
+
});
|
|
45
|
+
acc.push(React.createElement(BarYSeriesShapes, { key: "bar-y", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
46
|
+
shapesData.push(...preparedData);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case 'line': {
|
|
51
|
+
if (xScale && yScale) {
|
|
52
|
+
const preparedData = prepareLineData({
|
|
53
|
+
series: chartSeries,
|
|
54
|
+
xAxis,
|
|
55
|
+
xScale,
|
|
56
|
+
yAxis,
|
|
57
|
+
yScale,
|
|
58
|
+
});
|
|
59
|
+
acc.push(React.createElement(LineSeriesShapes, { key: "line", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
60
|
+
shapesData.push(...preparedData);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
32
64
|
case 'scatter': {
|
|
33
65
|
if (xScale && yScale) {
|
|
34
66
|
const preparedData = prepareScatterData({
|
|
@@ -38,14 +70,14 @@ export const useShapes = (args) => {
|
|
|
38
70
|
yAxis: yAxis[0],
|
|
39
71
|
yScale,
|
|
40
72
|
});
|
|
41
|
-
acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher,
|
|
73
|
+
acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, svgContainer: svgContainer }));
|
|
42
74
|
}
|
|
43
75
|
break;
|
|
44
76
|
}
|
|
45
77
|
case 'pie': {
|
|
46
78
|
const groupedPieSeries = group(chartSeries, (pieSeries) => pieSeries.stackId);
|
|
47
79
|
acc.push(...Array.from(groupedPieSeries).map(([key, pieSeries]) => {
|
|
48
|
-
return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, dispatcher: dispatcher,
|
|
80
|
+
return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, dispatcher: dispatcher, series: pieSeries, seriesOptions: seriesOptions, svgContainer: svgContainer }));
|
|
49
81
|
}));
|
|
50
82
|
}
|
|
51
83
|
}
|
|
@@ -63,8 +95,6 @@ export const useShapes = (args) => {
|
|
|
63
95
|
yAxis,
|
|
64
96
|
yScale,
|
|
65
97
|
svgContainer,
|
|
66
|
-
left,
|
|
67
|
-
top,
|
|
68
98
|
]);
|
|
69
99
|
return { shapes: shapesComponents.shapes, shapesData: shapesComponents.shapesData };
|
|
70
100
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Dispatch } from 'd3';
|
|
3
|
+
import type { PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
|
+
import { PreparedLineData } from './types';
|
|
5
|
+
type Args = {
|
|
6
|
+
dispatcher: Dispatch<object>;
|
|
7
|
+
preparedData: PreparedLineData[];
|
|
8
|
+
seriesOptions: PreparedSeriesOptions;
|
|
9
|
+
};
|
|
10
|
+
export declare const LineSeriesShapes: (args: Args) => React.JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { select, line as lineGenerator, color } from 'd3';
|
|
3
|
+
import get from 'lodash/get';
|
|
4
|
+
import { block } from '../../../../../../utils/cn';
|
|
5
|
+
import { shapeKey } from '../utils';
|
|
6
|
+
const b = block('d3-line');
|
|
7
|
+
export const LineSeriesShapes = (args) => {
|
|
8
|
+
const { dispatcher, preparedData, seriesOptions } = args;
|
|
9
|
+
const ref = React.useRef(null);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
if (!ref.current) {
|
|
12
|
+
return () => { };
|
|
13
|
+
}
|
|
14
|
+
const svgElement = select(ref.current);
|
|
15
|
+
const hoverOptions = get(seriesOptions, 'line.states.hover');
|
|
16
|
+
const inactiveOptions = get(seriesOptions, 'line.states.inactive');
|
|
17
|
+
const line = lineGenerator()
|
|
18
|
+
.x((d) => d.x)
|
|
19
|
+
.y((d) => d.y);
|
|
20
|
+
svgElement.selectAll('*').remove();
|
|
21
|
+
const selection = svgElement
|
|
22
|
+
.selectAll('path')
|
|
23
|
+
.data(preparedData, shapeKey)
|
|
24
|
+
.join('path')
|
|
25
|
+
.attr('d', (d) => line(d.points))
|
|
26
|
+
.attr('fill', 'none')
|
|
27
|
+
.attr('stroke', (d) => d.color)
|
|
28
|
+
.attr('stroke-width', (d) => d.width)
|
|
29
|
+
.attr('stroke-linejoin', 'round')
|
|
30
|
+
.attr('stroke-linecap', 'round');
|
|
31
|
+
const dataLabels = preparedData.reduce((acc, d) => {
|
|
32
|
+
if (d.series.dataLabels.enabled) {
|
|
33
|
+
acc.push(...d.points.map((p) => ({
|
|
34
|
+
x: p.x,
|
|
35
|
+
y: p.y,
|
|
36
|
+
data: p.data,
|
|
37
|
+
series: d.series,
|
|
38
|
+
})));
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, []);
|
|
42
|
+
svgElement
|
|
43
|
+
.selectAll('allLabels')
|
|
44
|
+
.data(dataLabels)
|
|
45
|
+
.join('text')
|
|
46
|
+
.text((d) => String(d.data.label || d.data.y))
|
|
47
|
+
.attr('class', b('label'))
|
|
48
|
+
.attr('x', (d) => d.x)
|
|
49
|
+
.attr('y', (d) => {
|
|
50
|
+
return d.y - d.series.dataLabels.padding;
|
|
51
|
+
})
|
|
52
|
+
.attr('text-anchor', 'middle')
|
|
53
|
+
.style('font-size', (d) => d.series.dataLabels.style.fontSize)
|
|
54
|
+
.style('font-weight', (d) => d.series.dataLabels.style.fontWeight || null)
|
|
55
|
+
.style('fill', (d) => d.series.dataLabels.style.fontColor || null);
|
|
56
|
+
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
57
|
+
const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
|
|
58
|
+
dispatcher.on('hover-shape.line', (data) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
const selectedSeriesId = (_b = (_a = data === null || data === void 0 ? void 0 : data.find((d) => d.series.type === 'line')) === null || _a === void 0 ? void 0 : _a.series) === null || _b === void 0 ? void 0 : _b.id;
|
|
61
|
+
const updates = [];
|
|
62
|
+
preparedData.forEach((p) => {
|
|
63
|
+
const hovered = Boolean(hoverEnabled && p.id === selectedSeriesId);
|
|
64
|
+
if (p.hovered !== hovered) {
|
|
65
|
+
p.hovered = hovered;
|
|
66
|
+
updates.push(p);
|
|
67
|
+
}
|
|
68
|
+
const active = Boolean(!inactiveEnabled || !selectedSeriesId || selectedSeriesId === p.id);
|
|
69
|
+
if (p.active !== active) {
|
|
70
|
+
p.active = active;
|
|
71
|
+
updates.push(p);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
selection.data(updates, shapeKey).join('shape', (update) => {
|
|
75
|
+
update
|
|
76
|
+
.attr('stroke', (d) => {
|
|
77
|
+
var _a;
|
|
78
|
+
const initialColor = d.color || '';
|
|
79
|
+
if (d.hovered) {
|
|
80
|
+
return (((_a = color(initialColor)) === null || _a === void 0 ? void 0 : _a.brighter(hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.brightness).toString()) || initialColor);
|
|
81
|
+
}
|
|
82
|
+
return initialColor;
|
|
83
|
+
})
|
|
84
|
+
.attr('opacity', function (d) {
|
|
85
|
+
if (!d.active) {
|
|
86
|
+
return (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
});
|
|
90
|
+
return update;
|
|
91
|
+
}, (exit) => exit);
|
|
92
|
+
});
|
|
93
|
+
return () => {
|
|
94
|
+
dispatcher.on('hover-shape.line', null);
|
|
95
|
+
};
|
|
96
|
+
}, [dispatcher, preparedData, seriesOptions]);
|
|
97
|
+
return React.createElement("g", { ref: ref, className: b() });
|
|
98
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PreparedLineSeries } from '../../useSeries/types';
|
|
2
|
+
import { PreparedAxis } from '../../useChartOptions/types';
|
|
3
|
+
import { ChartScale } from '../../useAxisScales';
|
|
4
|
+
import { PreparedLineData } from './types';
|
|
5
|
+
export declare const prepareLineData: (args: {
|
|
6
|
+
series: PreparedLineSeries[];
|
|
7
|
+
xAxis: PreparedAxis;
|
|
8
|
+
xScale: ChartScale;
|
|
9
|
+
yAxis: PreparedAxis[];
|
|
10
|
+
yScale: ChartScale;
|
|
11
|
+
}) => PreparedLineData[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getXValue, getYValue } from '../utils';
|
|
2
|
+
export const prepareLineData = (args) => {
|
|
3
|
+
const { series, xAxis, xScale, yScale } = args;
|
|
4
|
+
const yAxis = args.yAxis[0];
|
|
5
|
+
return series.reduce((acc, s) => {
|
|
6
|
+
acc.push({
|
|
7
|
+
points: s.data.map((d) => ({
|
|
8
|
+
x: getXValue({ point: d, xAxis, xScale }),
|
|
9
|
+
y: getYValue({ point: d, yAxis, yScale }),
|
|
10
|
+
data: d,
|
|
11
|
+
})),
|
|
12
|
+
color: s.color,
|
|
13
|
+
width: s.lineWidth,
|
|
14
|
+
series: s,
|
|
15
|
+
hovered: false,
|
|
16
|
+
active: true,
|
|
17
|
+
id: s.id,
|
|
18
|
+
});
|
|
19
|
+
return acc;
|
|
20
|
+
}, []);
|
|
21
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PreparedLineSeries } from '../../useSeries/types';
|
|
2
|
+
import { LineSeriesData } from '../../../../../../types';
|
|
3
|
+
export type PointData = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
data: LineSeriesData;
|
|
7
|
+
};
|
|
8
|
+
export type PreparedLineData = {
|
|
9
|
+
id: string;
|
|
10
|
+
points: PointData[];
|
|
11
|
+
color: string;
|
|
12
|
+
width: number;
|
|
13
|
+
series: PreparedLineSeries;
|
|
14
|
+
hovered: boolean;
|
|
15
|
+
active: boolean;
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -32,7 +32,7 @@ const isNodeContainsPieData = (node) => {
|
|
|
32
32
|
};
|
|
33
33
|
export function PieSeriesComponent(args) {
|
|
34
34
|
var _a;
|
|
35
|
-
const { boundsWidth, boundsHeight, dispatcher,
|
|
35
|
+
const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, svgContainer } = args;
|
|
36
36
|
const ref = React.useRef(null);
|
|
37
37
|
const [x, y] = getCenter(boundsWidth, boundsHeight, (_a = series[0]) === null || _a === void 0 ? void 0 : _a.center);
|
|
38
38
|
React.useEffect(() => {
|
|
@@ -154,7 +154,7 @@ export function PieSeriesComponent(args) {
|
|
|
154
154
|
}
|
|
155
155
|
const [pointerX, pointerY] = pointer(e, svgContainer);
|
|
156
156
|
const segmentData = extractD3DataFromNode(segment).data;
|
|
157
|
-
dispatcher.call('hover-shape', {}, [segmentData], [pointerX
|
|
157
|
+
dispatcher.call('hover-shape', {}, [segmentData], [pointerX, pointerY]);
|
|
158
158
|
})
|
|
159
159
|
.on('mouseleave', () => {
|
|
160
160
|
dispatcher.call('hover-shape', {}, undefined);
|
|
@@ -199,6 +199,6 @@ export function PieSeriesComponent(args) {
|
|
|
199
199
|
return () => {
|
|
200
200
|
dispatcher.on(eventName, null);
|
|
201
201
|
};
|
|
202
|
-
}, [boundsWidth, boundsHeight, dispatcher,
|
|
202
|
+
}, [boundsWidth, boundsHeight, dispatcher, series, seriesOptions, svgContainer]);
|
|
203
203
|
return React.createElement("g", { ref: ref, className: b(), transform: `translate(${x}, ${y})` });
|
|
204
204
|
}
|
|
@@ -6,8 +6,6 @@ export { prepareScatterData } from './prepare-data';
|
|
|
6
6
|
export type { PreparedScatterData } from './prepare-data';
|
|
7
7
|
type ScatterSeriesShapeProps = {
|
|
8
8
|
dispatcher: Dispatch<object>;
|
|
9
|
-
top: number;
|
|
10
|
-
left: number;
|
|
11
9
|
preparedData: PreparedScatterData[];
|
|
12
10
|
seriesOptions: PreparedSeriesOptions;
|
|
13
11
|
svgContainer: SVGSVGElement | null;
|
|
@@ -3,16 +3,16 @@ import get from 'lodash/get';
|
|
|
3
3
|
import { color, pointer, select } from 'd3';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
5
|
import { extractD3DataFromNode, isNodeContainsD3Data } from '../../../utils';
|
|
6
|
+
import { shapeKey } from '../utils';
|
|
6
7
|
export { prepareScatterData } from './prepare-data';
|
|
7
8
|
const b = block('d3-scatter');
|
|
8
9
|
const DEFAULT_SCATTER_POINT_RADIUS = 4;
|
|
9
10
|
const EMPTY_SELECTION = null;
|
|
10
|
-
const key = (d) => d.id || -1;
|
|
11
11
|
const isNodeContainsScatterData = (node) => {
|
|
12
12
|
return isNodeContainsD3Data(node);
|
|
13
13
|
};
|
|
14
14
|
export function ScatterSeriesShape(props) {
|
|
15
|
-
const { dispatcher,
|
|
15
|
+
const { dispatcher, preparedData, seriesOptions, svgContainer } = props;
|
|
16
16
|
const ref = React.useRef(null);
|
|
17
17
|
React.useEffect(() => {
|
|
18
18
|
if (!ref.current) {
|
|
@@ -23,7 +23,7 @@ export function ScatterSeriesShape(props) {
|
|
|
23
23
|
const inactiveOptions = get(seriesOptions, 'scatter.states.inactive');
|
|
24
24
|
const selection = svgElement
|
|
25
25
|
.selectAll(`circle`)
|
|
26
|
-
.data(preparedData,
|
|
26
|
+
.data(preparedData, shapeKey)
|
|
27
27
|
.join((enter) => enter.append('circle').attr('class', b('point')), (update) => update, (exit) => exit.remove())
|
|
28
28
|
.attr('fill', (d) => d.data.color || d.series.color || '')
|
|
29
29
|
.attr('r', (d) => d.data.radius || DEFAULT_SCATTER_POINT_RADIUS)
|
|
@@ -37,7 +37,7 @@ export function ScatterSeriesShape(props) {
|
|
|
37
37
|
}
|
|
38
38
|
const [pointerX, pointerY] = pointer(e, svgContainer);
|
|
39
39
|
const segmentData = extractD3DataFromNode(point);
|
|
40
|
-
dispatcher.call('hover-shape', {}, [segmentData], [pointerX
|
|
40
|
+
dispatcher.call('hover-shape', {}, [segmentData], [pointerX, pointerY]);
|
|
41
41
|
})
|
|
42
42
|
.on('mouseleave', () => {
|
|
43
43
|
dispatcher.call('hover-shape', {}, undefined);
|
|
@@ -62,7 +62,7 @@ export function ScatterSeriesShape(props) {
|
|
|
62
62
|
updates.push(p);
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
|
-
selection.data(updates,
|
|
65
|
+
selection.data(updates, shapeKey).join(() => EMPTY_SELECTION, (update) => {
|
|
66
66
|
update
|
|
67
67
|
.attr('fill', (d) => {
|
|
68
68
|
var _a;
|
|
@@ -84,6 +84,6 @@ export function ScatterSeriesShape(props) {
|
|
|
84
84
|
return () => {
|
|
85
85
|
dispatcher.on('hover-shape.scatter', null);
|
|
86
86
|
};
|
|
87
|
-
}, [dispatcher,
|
|
87
|
+
}, [dispatcher, preparedData, seriesOptions, svgContainer]);
|
|
88
88
|
return React.createElement("g", { ref: ref, className: b() });
|
|
89
89
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TooltipDataChunkScatter } from '../../../../../../types
|
|
1
|
+
import type { TooltipDataChunkScatter } from '../../../../../../types';
|
|
2
2
|
import type { ChartScale } from '../../useAxisScales';
|
|
3
3
|
import type { PreparedAxis } from '../../useChartOptions/types';
|
|
4
4
|
import { PreparedScatterSeries } from '../../useSeries/types';
|
|
@@ -1,35 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { getDataCategoryValue } from '../../../utils';
|
|
3
|
-
const getCxAttr = (args) => {
|
|
4
|
-
const { point, xAxis, xScale } = args;
|
|
5
|
-
let cx;
|
|
6
|
-
if (xAxis.type === 'category') {
|
|
7
|
-
const xBandScale = xScale;
|
|
8
|
-
const categories = get(xAxis, 'categories', []);
|
|
9
|
-
const dataCategory = getDataCategoryValue({ axisDirection: 'x', categories, data: point });
|
|
10
|
-
cx = (xBandScale(dataCategory) || 0) + xBandScale.step() / 2;
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
const xLinearScale = xScale;
|
|
14
|
-
cx = xLinearScale(point.x);
|
|
15
|
-
}
|
|
16
|
-
return cx;
|
|
17
|
-
};
|
|
18
|
-
const getCyAttr = (args) => {
|
|
19
|
-
const { point, yAxis, yScale } = args;
|
|
20
|
-
let cy;
|
|
21
|
-
if (yAxis.type === 'category') {
|
|
22
|
-
const yBandScale = yScale;
|
|
23
|
-
const categories = get(yAxis, 'categories', []);
|
|
24
|
-
const dataCategory = getDataCategoryValue({ axisDirection: 'y', categories, data: point });
|
|
25
|
-
cy = (yBandScale(dataCategory) || 0) + yBandScale.step() / 2;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
const yLinearScale = yScale;
|
|
29
|
-
cy = yLinearScale(point.y);
|
|
30
|
-
}
|
|
31
|
-
return cy;
|
|
32
|
-
};
|
|
1
|
+
import { getXValue, getYValue } from '../utils';
|
|
33
2
|
const getFilteredLinearScatterData = (data) => {
|
|
34
3
|
return data.filter((d) => typeof d.x === 'number' && typeof d.y === 'number');
|
|
35
4
|
};
|
|
@@ -43,8 +12,8 @@ export const prepareScatterData = (args) => {
|
|
|
43
12
|
acc.push({
|
|
44
13
|
data: d,
|
|
45
14
|
series: s,
|
|
46
|
-
cx:
|
|
47
|
-
cy:
|
|
15
|
+
cx: getXValue({ point: d, xAxis, xScale }),
|
|
16
|
+
cy: getYValue({ point: d, yAxis, yScale }),
|
|
48
17
|
hovered: false,
|
|
49
18
|
active: true,
|
|
50
19
|
id: acc.length - 1,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PreparedAxis } from '../useChartOptions/types';
|
|
2
|
+
import { ChartScale } from '../useAxisScales';
|
|
3
|
+
export declare function getXValue(args: {
|
|
4
|
+
point: {
|
|
5
|
+
x?: number | string;
|
|
6
|
+
};
|
|
7
|
+
xAxis: PreparedAxis;
|
|
8
|
+
xScale: ChartScale;
|
|
9
|
+
}): number;
|
|
10
|
+
export declare function getYValue(args: {
|
|
11
|
+
point: {
|
|
12
|
+
y?: number | string;
|
|
13
|
+
};
|
|
14
|
+
yAxis: PreparedAxis;
|
|
15
|
+
yScale: ChartScale;
|
|
16
|
+
}): number;
|
|
17
|
+
export declare const shapeKey: (d: unknown) => string | number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { getDataCategoryValue } from '../../utils';
|
|
3
|
+
export function getXValue(args) {
|
|
4
|
+
const { point, xAxis, xScale } = args;
|
|
5
|
+
if (xAxis.type === 'category') {
|
|
6
|
+
const xBandScale = xScale;
|
|
7
|
+
const categories = get(xAxis, 'categories', []);
|
|
8
|
+
const dataCategory = getDataCategoryValue({ axisDirection: 'x', categories, data: point });
|
|
9
|
+
return (xBandScale(dataCategory) || 0) + xBandScale.step() / 2;
|
|
10
|
+
}
|
|
11
|
+
const xLinearScale = xScale;
|
|
12
|
+
return xLinearScale(point.x);
|
|
13
|
+
}
|
|
14
|
+
export function getYValue(args) {
|
|
15
|
+
const { point, yAxis, yScale } = args;
|
|
16
|
+
if (yAxis.type === 'category') {
|
|
17
|
+
const yBandScale = yScale;
|
|
18
|
+
const categories = get(yAxis, 'categories', []);
|
|
19
|
+
const dataCategory = getDataCategoryValue({ axisDirection: 'y', categories, data: point });
|
|
20
|
+
return (yBandScale(dataCategory) || 0) + yBandScale.step() / 2;
|
|
21
|
+
}
|
|
22
|
+
const yLinearScale = yScale;
|
|
23
|
+
return yLinearScale(point.y);
|
|
24
|
+
}
|
|
25
|
+
export const shapeKey = (d) => d.id || -1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { select } from 'd3';
|
|
2
2
|
import { getXAxisItems, getXAxisOffset, getXTickPosition } from '../axis';
|
|
3
|
-
import {
|
|
3
|
+
import { getLabelsSize, setEllipsisForOverflowText } from '../text';
|
|
4
4
|
import { calculateCos, calculateSin } from '../math';
|
|
5
5
|
function addDomain(selection, options) {
|
|
6
6
|
const { size, color } = options;
|
|
@@ -18,10 +18,10 @@ export function axisBottom(args) {
|
|
|
18
18
|
const offset = getXAxisOffset();
|
|
19
19
|
const position = getXTickPosition({ scale, offset });
|
|
20
20
|
const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
|
|
21
|
-
const labelHeight =
|
|
21
|
+
const labelHeight = getLabelsSize({
|
|
22
22
|
labels: values,
|
|
23
23
|
style: { 'font-size': (labelsStyle === null || labelsStyle === void 0 ? void 0 : labelsStyle.fontSize) || '' },
|
|
24
|
-
});
|
|
24
|
+
}).maxHeight;
|
|
25
25
|
return function (selection) {
|
|
26
26
|
var _a, _b;
|
|
27
27
|
const x = ((_b = (_a = selection.node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.x) || 0;
|
|
@@ -8,13 +8,11 @@ export declare function hasOverlappingLabels({ width, labels, padding, style, }:
|
|
|
8
8
|
style?: BaseTextStyle;
|
|
9
9
|
padding?: number;
|
|
10
10
|
}): boolean;
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function getLabelsSize({ labels, style, rotation, }: {
|
|
12
12
|
labels: string[];
|
|
13
13
|
style?: Record<string, string>;
|
|
14
14
|
rotation?: number;
|
|
15
|
-
}):
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
rotation?: number;
|
|
20
|
-
}): number;
|
|
15
|
+
}): {
|
|
16
|
+
maxHeight: number;
|
|
17
|
+
maxWidth: number;
|
|
18
|
+
};
|
|
@@ -46,19 +46,8 @@ function renderLabels(selection, { labels, style = {}, attrs = {}, }) {
|
|
|
46
46
|
.text((d) => d);
|
|
47
47
|
return text;
|
|
48
48
|
}
|
|
49
|
-
export function
|
|
50
|
-
var _a
|
|
51
|
-
const svg = select(document.body).append('svg');
|
|
52
|
-
const textSelection = renderLabels(svg, { labels, style });
|
|
53
|
-
if (rotation) {
|
|
54
|
-
textSelection.attr('text-anchor', 'end').style('transform', `rotate(${rotation}deg)`);
|
|
55
|
-
}
|
|
56
|
-
const maxWidth = ((_b = (_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.width) || 0;
|
|
57
|
-
svg.remove();
|
|
58
|
-
return maxWidth;
|
|
59
|
-
}
|
|
60
|
-
export function getLabelsMaxHeight({ labels, style, rotation, }) {
|
|
61
|
-
var _a, _b;
|
|
49
|
+
export function getLabelsSize({ labels, style, rotation, }) {
|
|
50
|
+
var _a;
|
|
62
51
|
const svg = select(document.body).append('svg');
|
|
63
52
|
const textSelection = renderLabels(svg, { labels, style });
|
|
64
53
|
if (rotation) {
|
|
@@ -66,7 +55,7 @@ export function getLabelsMaxHeight({ labels, style, rotation, }) {
|
|
|
66
55
|
.attr('text-anchor', rotation > 0 ? 'start' : 'end')
|
|
67
56
|
.style('transform', `rotate(${rotation}deg)`);
|
|
68
57
|
}
|
|
69
|
-
const
|
|
58
|
+
const { height = 0, width = 0 } = ((_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {};
|
|
70
59
|
svg.remove();
|
|
71
|
-
return maxHeight;
|
|
60
|
+
return { maxHeight: height, maxWidth: width };
|
|
72
61
|
}
|
|
@@ -10,7 +10,7 @@ declare const HighchartsWidget: React.ForwardRefExoticComponent<{
|
|
|
10
10
|
onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"highcharts">) => void) | undefined;
|
|
11
11
|
onError?: import("../../../types").ChartKitOnError | undefined;
|
|
12
12
|
renderError?: import("../../../types").RenderError | undefined;
|
|
13
|
-
renderPluginLoader?: (
|
|
13
|
+
renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
|
|
14
14
|
} & {
|
|
15
15
|
hoistConfigError?: boolean | undefined;
|
|
16
16
|
nonBodyScroll?: boolean | undefined;
|
|
@@ -11,7 +11,7 @@ declare const IndicatorWidget: React.ForwardRefExoticComponent<{
|
|
|
11
11
|
onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"indicator">) => void) | undefined;
|
|
12
12
|
onError?: import("../../../types").ChartKitOnError | undefined;
|
|
13
13
|
renderError?: import("../../../types").RenderError | undefined;
|
|
14
|
-
renderPluginLoader?: (
|
|
14
|
+
renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
|
|
15
15
|
} & {
|
|
16
16
|
formatNumber?: (<T = any>(value: number, options?: T | undefined) => string) | undefined;
|
|
17
17
|
} & React.RefAttributes<ChartKitWidgetRef | undefined>>;
|
|
@@ -13,7 +13,7 @@ declare const YagrWidget: React.ForwardRefExoticComponent<{
|
|
|
13
13
|
onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"yagr">) => void) | undefined;
|
|
14
14
|
onError?: import("../../../types").ChartKitOnError | undefined;
|
|
15
15
|
renderError?: import("../../../types").RenderError | undefined;
|
|
16
|
-
renderPluginLoader?: (
|
|
16
|
+
renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
|
|
17
17
|
} & {
|
|
18
18
|
tooltip?: (<T extends import("../types").CustomTooltipProps = import("../types").CustomTooltipProps>(props: T) => React.ReactNode) | undefined;
|
|
19
19
|
} & {
|
package/build/types/index.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type ChartKitOnChartLoad<T extends ChartKitType> = {
|
|
|
24
24
|
export type ChartKitOnError = (data: {
|
|
25
25
|
error: any;
|
|
26
26
|
}) => void;
|
|
27
|
+
export type ChartKitRenderPluginLoader = () => React.ReactNode;
|
|
27
28
|
export type ChartKitProps<T extends ChartKitType> = {
|
|
28
29
|
type: T;
|
|
29
30
|
data: ChartKitWidget[T]['data'];
|
|
@@ -39,7 +40,7 @@ export type ChartKitProps<T extends ChartKitType> = {
|
|
|
39
40
|
/** Used to render user's error component */
|
|
40
41
|
renderError?: RenderError;
|
|
41
42
|
/** Used to render user's plugin loader component */
|
|
42
|
-
renderPluginLoader?:
|
|
43
|
+
renderPluginLoader?: ChartKitRenderPluginLoader;
|
|
43
44
|
} & {
|
|
44
45
|
[key in keyof Omit<ChartKitWidget[T], 'data' | 'widget'>]: ChartKitWidget[T][key];
|
|
45
46
|
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { BaseSeries, BaseSeriesData } from './base';
|
|
2
|
+
import type { ChartKitWidgetSeriesOptions } from './series';
|
|
3
|
+
import { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
4
|
+
export type BarYSeriesData<T = any> = BaseSeriesData<T> & {
|
|
5
|
+
/**
|
|
6
|
+
* The `x` value of the bar. Depending on the context , it may represents:
|
|
7
|
+
* - numeric value (for `linear` x axis)
|
|
8
|
+
* - timestamp value (for `datetime` x axis)
|
|
9
|
+
* - x axis category value (for `category` x axis). If the type is a string, then it is a category value itself. If the type is a number, then it is the index of an element in the array of categories described in `xAxis.categories`
|
|
10
|
+
*/
|
|
11
|
+
x?: string | number;
|
|
12
|
+
/**
|
|
13
|
+
* The `y` value of the bar. Depending on the context , it may represents:
|
|
14
|
+
* - numeric value (for `linear` y axis)
|
|
15
|
+
* - timestamp value (for `datetime` y axis)
|
|
16
|
+
* - y axis category value (for `category` y axis). If the type is a string, then it is a category value itself. If the type is a number, then it is the index of an element in the array of categories described in `yAxis[0].categories`
|
|
17
|
+
*/
|
|
18
|
+
y?: string | number;
|
|
19
|
+
/** Data label value of the bar. If not specified, the x value is used. */
|
|
20
|
+
label?: string | number;
|
|
21
|
+
};
|
|
22
|
+
export type BarYSeries<T = any> = BaseSeries & {
|
|
23
|
+
type: 'bar-y';
|
|
24
|
+
data: BarYSeriesData<T>[];
|
|
25
|
+
/** The name of the series (used in legend, tooltip etc) */
|
|
26
|
+
name: string;
|
|
27
|
+
/** The main color of the series (hex, rgba) */
|
|
28
|
+
color?: string;
|
|
29
|
+
/** Whether to stack the values of each series on top of each other.
|
|
30
|
+
* Possible values are undefined to disable, "normal" to stack by value or "percent"
|
|
31
|
+
*
|
|
32
|
+
* @default undefined
|
|
33
|
+
* */
|
|
34
|
+
stacking?: 'normal' | 'percent';
|
|
35
|
+
/** This option allows grouping series in a stacked chart */
|
|
36
|
+
stackId?: string;
|
|
37
|
+
/** Whether to group non-stacked columns or to let them render independent of each other.
|
|
38
|
+
* When false columns will be laid out individually and overlap each other.
|
|
39
|
+
*
|
|
40
|
+
* @default true
|
|
41
|
+
* */
|
|
42
|
+
grouping?: boolean;
|
|
43
|
+
dataLabels?: ChartKitWidgetSeriesOptions['dataLabels'] & {
|
|
44
|
+
/**
|
|
45
|
+
* Whether to align the data label inside or outside the box
|
|
46
|
+
*
|
|
47
|
+
* @default false
|
|
48
|
+
* */
|
|
49
|
+
inside?: boolean;
|
|
50
|
+
};
|
|
51
|
+
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
52
|
+
legend?: ChartKitWidgetLegend & {
|
|
53
|
+
symbol?: RectLegendSymbolOptions;
|
|
54
|
+
};
|
|
55
|
+
};
|