@gravity-ui/chartkit 3.5.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/plugins/d3/renderer/components/Chart.js +7 -11
- package/build/plugins/d3/renderer/components/Legend.d.ts +3 -2
- package/build/plugins/d3/renderer/components/Legend.js +42 -21
- package/build/plugins/d3/renderer/constants.d.ts +3 -0
- package/build/plugins/d3/renderer/constants.js +3 -0
- package/build/plugins/d3/renderer/hooks/index.d.ts +1 -1
- package/build/plugins/d3/renderer/hooks/index.js +1 -1
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +2 -2
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +2 -4
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +5 -6
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +7 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/title.js +2 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +3 -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 +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/constants.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +10 -8
- package/build/plugins/d3/renderer/hooks/useSeries/index.js +44 -53
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +9 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +85 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +29 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/utils.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useSeries/utils.js +11 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x.js +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +4 -1
- package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useShapes/pie.js +87 -12
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +0 -1
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +4 -2
- package/build/plugins/d3/renderer/hooks/useShapes/styles.css +6 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +42 -6
- package/build/plugins/d3/renderer/utils/index.js +43 -6
- package/build/types/widget-data/bar-x.d.ts +5 -0
- package/build/types/widget-data/base.d.ts +12 -3
- package/build/types/widget-data/legend.d.ts +32 -0
- package/build/types/widget-data/pie.d.ts +23 -4
- package/build/types/widget-data/scatter.d.ts +5 -0
- package/package.json +1 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.d.ts +0 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.js +0 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.d.ts +0 -5
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.js +0 -18
- package/build/plugins/d3/renderer/hooks/useLegend/index.d.ts +0 -13
- package/build/plugins/d3/renderer/hooks/useLegend/index.js +0 -59
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BarXSeries, BarXSeriesData, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData } from '../../../../../types/widget-data';
|
|
2
|
+
export type RectLegendSymbol = {
|
|
3
|
+
shape: 'rect';
|
|
4
|
+
} & Required<RectLegendSymbolOptions>;
|
|
5
|
+
export type PreparedLegendSymbol = RectLegendSymbol;
|
|
6
|
+
type BasePreparedSeries = {
|
|
7
|
+
color: string;
|
|
8
|
+
name: string;
|
|
9
|
+
visible: boolean;
|
|
10
|
+
legend: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
symbol: PreparedLegendSymbol;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export type PreparedScatterSeries = {
|
|
16
|
+
type: ScatterSeries['type'];
|
|
17
|
+
data: ScatterSeriesData[];
|
|
18
|
+
} & BasePreparedSeries;
|
|
19
|
+
export type PreparedBarXSeries = {
|
|
20
|
+
type: BarXSeries['type'];
|
|
21
|
+
data: BarXSeriesData[];
|
|
22
|
+
} & BasePreparedSeries;
|
|
23
|
+
export type PreparedPieSeries = BasePreparedSeries & Required<Omit<PieSeries, 'data'>> & {
|
|
24
|
+
data: PieSeriesData['value'];
|
|
25
|
+
stackId: string;
|
|
26
|
+
label?: PieSeriesData['label'];
|
|
27
|
+
};
|
|
28
|
+
export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedPieSeries;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const getActiveLegendItems = (series) => {
|
|
2
|
+
return series.reduce((acc, s) => {
|
|
3
|
+
if (s.legend.enabled && s.visible) {
|
|
4
|
+
acc.push(s.name);
|
|
5
|
+
}
|
|
6
|
+
return acc;
|
|
7
|
+
}, []);
|
|
8
|
+
};
|
|
9
|
+
export const getAllLegendItems = (series) => {
|
|
10
|
+
return series.map((s) => s.name);
|
|
11
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { block } from '../../../../../utils/cn';
|
|
3
3
|
import { pointer } from 'd3';
|
|
4
|
+
import { getRandomCKId } from '../../../../../utils';
|
|
4
5
|
const DEFAULT_BAR_RECT_WIDTH = 50;
|
|
5
6
|
const DEFAULT_LINEAR_BAR_RECT_WIDTH = 20;
|
|
6
7
|
const MIN_RECT_GAP = 1;
|
|
@@ -52,7 +53,7 @@ export function prepareBarXSeries(args) {
|
|
|
52
53
|
const seriesData = series.map(({ data }) => data).flat(2);
|
|
53
54
|
const minPointDistance = minDiff(seriesData.map((item) => Number(item.x)));
|
|
54
55
|
return series.reduce((result, item) => {
|
|
55
|
-
const randomKey =
|
|
56
|
+
const randomKey = getRandomCKId();
|
|
56
57
|
item.data.forEach((point, i) => {
|
|
57
58
|
const rectProps = getRectProperties({
|
|
58
59
|
point,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ChartOptions } from '../useChartOptions/types';
|
|
3
3
|
import type { ChartScale } from '../useAxisScales';
|
|
4
|
-
import type {
|
|
4
|
+
import type { PreparedSeries } from '../';
|
|
5
5
|
import type { OnSeriesMouseMove, OnSeriesMouseLeave } from '../useTooltip/types';
|
|
6
6
|
import './styles.css';
|
|
7
7
|
type Args = {
|
|
@@ -9,7 +9,7 @@ type Args = {
|
|
|
9
9
|
left: number;
|
|
10
10
|
boundsWidth: number;
|
|
11
11
|
boundsHeight: number;
|
|
12
|
-
series:
|
|
12
|
+
series: PreparedSeries[];
|
|
13
13
|
xAxis: ChartOptions['xAxis'];
|
|
14
14
|
yAxis: ChartOptions['yAxis'];
|
|
15
15
|
svgContainer: SVGSVGElement | null;
|
|
@@ -48,7 +48,10 @@ export const useShapes = (args) => {
|
|
|
48
48
|
break;
|
|
49
49
|
}
|
|
50
50
|
case 'pie': {
|
|
51
|
-
|
|
51
|
+
const groupedPieSeries = group(chartSeries, (item) => item.stackId);
|
|
52
|
+
acc.push(...Array.from(groupedPieSeries).map(([key, pieSeries]) => {
|
|
53
|
+
return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, series: pieSeries, onSeriesMouseMove: onSeriesMouseMove, onSeriesMouseLeave: onSeriesMouseLeave, svgContainer: svgContainer }));
|
|
54
|
+
}));
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
return acc;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { PieSeries } from '../../../../../types/widget-data';
|
|
3
2
|
import type { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
|
|
3
|
+
import { PreparedPieSeries } from '../useSeries/types';
|
|
4
4
|
type PreparePieSeriesArgs = {
|
|
5
5
|
boundsWidth: number;
|
|
6
6
|
boundsHeight: number;
|
|
7
|
-
series:
|
|
7
|
+
series: PreparedPieSeries[];
|
|
8
8
|
svgContainer: SVGSVGElement | null;
|
|
9
9
|
onSeriesMouseMove?: OnSeriesMouseMove;
|
|
10
10
|
onSeriesMouseLeave?: OnSeriesMouseLeave;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { arc, pie, select } from 'd3';
|
|
3
3
|
import { block } from '../../../../../utils/cn';
|
|
4
|
-
import { calculateNumericProperty } from '../../utils';
|
|
4
|
+
import { calculateNumericProperty, getHorisontalSvgTextHeight } from '../../utils';
|
|
5
5
|
const b = block('d3-pie');
|
|
6
6
|
const getCenter = (boundsWidth, boundsHeight, center) => {
|
|
7
7
|
var _a, _b;
|
|
@@ -16,36 +16,111 @@ const getCenter = (boundsWidth, boundsHeight, center) => {
|
|
|
16
16
|
return [resultX, resultY];
|
|
17
17
|
};
|
|
18
18
|
export function PieSeriesComponent(args) {
|
|
19
|
+
var _a;
|
|
19
20
|
const { boundsWidth, boundsHeight, series, onSeriesMouseMove, onSeriesMouseLeave, svgContainer } = args;
|
|
20
21
|
const ref = React.useRef(null);
|
|
21
|
-
const [x, y] = getCenter(boundsWidth, boundsHeight, series.center);
|
|
22
|
+
const [x, y] = getCenter(boundsWidth, boundsHeight, (_a = series[0]) === null || _a === void 0 ? void 0 : _a.center);
|
|
22
23
|
React.useEffect(() => {
|
|
23
|
-
var _a, _b, _c, _d;
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
24
25
|
if (!ref.current) {
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
28
|
const svgElement = select(ref.current);
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
const isLabelsEnabled = (_b = (_a = series[0]) === null || _a === void 0 ? void 0 : _a.dataLabels) === null || _b === void 0 ? void 0 : _b.enabled;
|
|
30
|
+
let radiusRelatedToChart = Math.min(boundsWidth, boundsHeight) / 2;
|
|
31
|
+
if (isLabelsEnabled) {
|
|
32
|
+
// To have enough space for labels
|
|
33
|
+
radiusRelatedToChart *= 0.9;
|
|
34
|
+
}
|
|
35
|
+
let radius = (_d = calculateNumericProperty({ value: (_c = series[0]) === null || _c === void 0 ? void 0 : _c.radius, base: radiusRelatedToChart })) !== null && _d !== void 0 ? _d : radiusRelatedToChart;
|
|
36
|
+
const labelsArcRadius = ((_e = series[0]) === null || _e === void 0 ? void 0 : _e.radius) ? radius : radiusRelatedToChart;
|
|
37
|
+
if (isLabelsEnabled) {
|
|
38
|
+
// To have enough space for labels lines
|
|
39
|
+
radius *= 0.9;
|
|
40
|
+
}
|
|
41
|
+
const innerRadius = (_f = calculateNumericProperty({ value: series[0].innerRadius, base: radius })) !== null && _f !== void 0 ? _f : 0;
|
|
42
|
+
const pieGenerator = pie().value((d) => d.data);
|
|
43
|
+
const visibleData = series.filter((d) => d.visible);
|
|
33
44
|
const dataReady = pieGenerator(visibleData);
|
|
34
45
|
const arcGenerator = arc()
|
|
35
46
|
.innerRadius(innerRadius)
|
|
36
47
|
.outerRadius(radius)
|
|
37
|
-
.cornerRadius((
|
|
48
|
+
.cornerRadius((d) => d.data.borderRadius);
|
|
38
49
|
svgElement.selectAll('*').remove();
|
|
39
50
|
svgElement
|
|
40
|
-
.selectAll('
|
|
51
|
+
.selectAll('allSlices')
|
|
41
52
|
.data(dataReady)
|
|
42
53
|
.enter()
|
|
43
54
|
.append('path')
|
|
44
55
|
.attr('d', arcGenerator)
|
|
45
56
|
.attr('class', b('segment'))
|
|
46
57
|
.attr('fill', (d) => d.data.color || '')
|
|
47
|
-
.style('stroke', series.borderColor || '')
|
|
48
|
-
.style('stroke-width', (
|
|
58
|
+
.style('stroke', ((_g = series[0]) === null || _g === void 0 ? void 0 : _g.borderColor) || '')
|
|
59
|
+
.style('stroke-width', (_j = (_h = series[0]) === null || _h === void 0 ? void 0 : _h.borderWidth) !== null && _j !== void 0 ? _j : 1);
|
|
60
|
+
if ((_l = (_k = series[0]) === null || _k === void 0 ? void 0 : _k.dataLabels) === null || _l === void 0 ? void 0 : _l.enabled) {
|
|
61
|
+
const labelHeight = getHorisontalSvgTextHeight({ text: 'tmp' });
|
|
62
|
+
const outerArc = arc()
|
|
63
|
+
.innerRadius(labelsArcRadius)
|
|
64
|
+
.outerRadius(labelsArcRadius);
|
|
65
|
+
// Add the polylines between chart and labels
|
|
66
|
+
svgElement
|
|
67
|
+
.selectAll('allPolylines')
|
|
68
|
+
.data(dataReady)
|
|
69
|
+
.enter()
|
|
70
|
+
.append('polyline')
|
|
71
|
+
.attr('stroke', (d) => d.data.color || '')
|
|
72
|
+
.style('fill', 'none')
|
|
73
|
+
.attr('stroke-width', 1)
|
|
74
|
+
.attr('points', (d) => {
|
|
75
|
+
// Line insertion in the slice
|
|
76
|
+
const posA = arcGenerator.centroid(d);
|
|
77
|
+
// Line break: we use the other arc generator that has been built only for that
|
|
78
|
+
const posB = outerArc.centroid(d);
|
|
79
|
+
const posC = outerArc.centroid(d);
|
|
80
|
+
// We need the angle to see if the X position will be at the extreme right or extreme left
|
|
81
|
+
const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
82
|
+
const result = [posA, posB, posC];
|
|
83
|
+
if (midangle < Math.PI) {
|
|
84
|
+
// polylines located to the right
|
|
85
|
+
const nextCx = radiusRelatedToChart * 0.95;
|
|
86
|
+
if (nextCx > result[1][0]) {
|
|
87
|
+
result[2][0] = nextCx;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
result.splice(2, 1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// polylines located to the left
|
|
95
|
+
const nextCx = radiusRelatedToChart * 0.95 * -1;
|
|
96
|
+
if (nextCx < result[1][0]) {
|
|
97
|
+
result[2][0] = nextCx;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
result.splice(2, 1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result.join(' ');
|
|
104
|
+
});
|
|
105
|
+
// Add the polylines between chart and labels
|
|
106
|
+
svgElement
|
|
107
|
+
.selectAll('allLabels')
|
|
108
|
+
.data(dataReady)
|
|
109
|
+
.join('text')
|
|
110
|
+
.text((d) => d.data.label || d.value)
|
|
111
|
+
.attr('class', b('label'))
|
|
112
|
+
.attr('transform', (d) => {
|
|
113
|
+
const pos = outerArc.centroid(d);
|
|
114
|
+
const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
115
|
+
pos[0] = radiusRelatedToChart * 0.99 * (midangle < Math.PI ? 1 : -1);
|
|
116
|
+
pos[1] += labelHeight / 4;
|
|
117
|
+
return `translate(${pos})`;
|
|
118
|
+
})
|
|
119
|
+
.style('text-anchor', (d) => {
|
|
120
|
+
const midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
121
|
+
return midangle < Math.PI ? 'start' : 'end';
|
|
122
|
+
});
|
|
123
|
+
}
|
|
49
124
|
}, [boundsWidth, boundsHeight, series, onSeriesMouseMove, onSeriesMouseLeave, svgContainer]);
|
|
50
125
|
return React.createElement("g", { ref: ref, className: b(), transform: `translate(${x}, ${y})` });
|
|
51
126
|
}
|
|
@@ -14,7 +14,6 @@ type PrepareScatterSeriesArgs = {
|
|
|
14
14
|
svgContainer: SVGSVGElement | null;
|
|
15
15
|
onSeriesMouseMove?: OnSeriesMouseMove;
|
|
16
16
|
onSeriesMouseLeave?: OnSeriesMouseLeave;
|
|
17
|
-
key?: string;
|
|
18
17
|
};
|
|
19
18
|
export declare function prepareScatterSeries(args: PrepareScatterSeriesArgs): React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
|
|
20
19
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { pointer } from 'd3';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { block } from '../../../../../utils/cn';
|
|
4
|
+
import { getRandomCKId } from '../../../../../utils';
|
|
4
5
|
const b = block('d3-scatter');
|
|
5
6
|
const DEFAULT_SCATTER_POINT_RADIUS = 4;
|
|
6
7
|
const prepareCategoricalScatterData = (data) => {
|
|
@@ -33,9 +34,10 @@ const getPointProperties = (args) => {
|
|
|
33
34
|
return { r, cx, cy };
|
|
34
35
|
};
|
|
35
36
|
export function prepareScatterSeries(args) {
|
|
36
|
-
const { top, left, series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave,
|
|
37
|
+
const { top, left, series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave, svgContainer, } = args;
|
|
37
38
|
return series.reduce((result, s) => {
|
|
38
39
|
var _a;
|
|
40
|
+
const randomKey = getRandomCKId();
|
|
39
41
|
const preparedData = xAxis.type === 'category' || ((_a = yAxis[0]) === null || _a === void 0 ? void 0 : _a.type) === 'category'
|
|
40
42
|
? prepareCategoricalScatterData(s.data)
|
|
41
43
|
: prepareLinearScatterData(s.data);
|
|
@@ -47,7 +49,7 @@ export function prepareScatterSeries(args) {
|
|
|
47
49
|
yAxis,
|
|
48
50
|
yScale,
|
|
49
51
|
});
|
|
50
|
-
return (React.createElement("circle", Object.assign({ key: `${i}-${
|
|
52
|
+
return (React.createElement("circle", Object.assign({ key: `${i}-${randomKey}`, className: b('point'), fill: s.color }, pointProps, { onMouseMove: function (e) {
|
|
51
53
|
const [x, y] = pointer(e, svgContainer);
|
|
52
54
|
onSeriesMouseMove === null || onSeriesMouseMove === void 0 ? void 0 : onSeriesMouseMove({
|
|
53
55
|
hovered: {
|
|
@@ -1,17 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { ChartKitWidgetSeries, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels } from '../../../../types/widget-data';
|
|
1
|
+
import { AxisDomain } from 'd3';
|
|
2
|
+
import type { BaseTextStyle, ChartKitWidgetSeries, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels } from '../../../../types/widget-data';
|
|
3
3
|
export * from './math';
|
|
4
|
+
type UnknownSeries = {
|
|
5
|
+
type: ChartKitWidgetSeries['type'];
|
|
6
|
+
data: unknown;
|
|
7
|
+
};
|
|
4
8
|
/**
|
|
5
9
|
* Checks whether the series should be drawn with axes.
|
|
6
10
|
*
|
|
7
11
|
* @param series - The series object to check.
|
|
8
12
|
* @returns `true` if the series should be drawn with axes, `false` otherwise.
|
|
9
13
|
*/
|
|
10
|
-
export declare
|
|
11
|
-
export declare
|
|
12
|
-
|
|
14
|
+
export declare function isAxisRelatedSeries(series: UnknownSeries): boolean;
|
|
15
|
+
export declare function isSeriesWithNumericalXValues(series: UnknownSeries): series is {
|
|
16
|
+
type: ChartKitWidgetSeries['type'];
|
|
17
|
+
data: {
|
|
18
|
+
x: number;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
21
|
+
export declare function isSeriesWithNumericalYValues(series: UnknownSeries): series is {
|
|
22
|
+
type: ChartKitWidgetSeries['type'];
|
|
23
|
+
data: {
|
|
24
|
+
y: number;
|
|
25
|
+
}[];
|
|
26
|
+
};
|
|
27
|
+
export declare function isSeriesWithCategoryValues(series: UnknownSeries): series is {
|
|
28
|
+
type: ChartKitWidgetSeries['type'];
|
|
29
|
+
data: {
|
|
30
|
+
category: string;
|
|
31
|
+
}[];
|
|
32
|
+
};
|
|
33
|
+
export declare const getDomainDataXBySeries: (series: UnknownSeries[]) => number[];
|
|
34
|
+
export declare const getDomainDataYBySeries: (series: UnknownSeries[]) => unknown[];
|
|
13
35
|
export declare const getSeriesNames: (series: ChartKitWidgetSeries[]) => string[];
|
|
14
|
-
export declare const getOnlyVisibleSeries: <T extends
|
|
36
|
+
export declare const getOnlyVisibleSeries: <T extends {
|
|
37
|
+
visible: boolean;
|
|
38
|
+
}>(series: T[]) => T[];
|
|
15
39
|
export declare const parseTransformStyle: (style: string | null) => {
|
|
16
40
|
x?: number | undefined;
|
|
17
41
|
y?: number | undefined;
|
|
@@ -22,3 +46,15 @@ export declare const formatAxisTickLabel: (args: {
|
|
|
22
46
|
dateFormat?: ChartKitWidgetAxisLabels['dateFormat'];
|
|
23
47
|
numberFormat?: ChartKitWidgetAxisLabels['numberFormat'];
|
|
24
48
|
}) => string;
|
|
49
|
+
/**
|
|
50
|
+
* Calculates the height of a text element in a horizontal SVG layout.
|
|
51
|
+
*
|
|
52
|
+
* @param {Object} args - The arguments for the function.
|
|
53
|
+
* @param {string} args.text - The text to be measured.
|
|
54
|
+
* @param {Partial<BaseTextStyle>} args.style - Optional style properties for the text element.
|
|
55
|
+
* @return {number} The height of the text element.
|
|
56
|
+
*/
|
|
57
|
+
export declare const getHorisontalSvgTextHeight: (args: {
|
|
58
|
+
text: string;
|
|
59
|
+
style?: Partial<BaseTextStyle>;
|
|
60
|
+
}) => number;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { select } from 'd3';
|
|
2
|
+
import get from 'lodash/get';
|
|
1
3
|
import { dateTime } from '@gravity-ui/date-utils';
|
|
2
4
|
import { formatNumber } from '../../../shared';
|
|
5
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE } from '../constants';
|
|
3
6
|
export * from './math';
|
|
4
7
|
const CHARTS_WITHOUT_AXIS = ['pie'];
|
|
5
8
|
/**
|
|
@@ -8,18 +11,29 @@ const CHARTS_WITHOUT_AXIS = ['pie'];
|
|
|
8
11
|
* @param series - The series object to check.
|
|
9
12
|
* @returns `true` if the series should be drawn with axes, `false` otherwise.
|
|
10
13
|
*/
|
|
11
|
-
export
|
|
14
|
+
export function isAxisRelatedSeries(series) {
|
|
12
15
|
return !CHARTS_WITHOUT_AXIS.includes(series.type);
|
|
13
|
-
}
|
|
16
|
+
}
|
|
17
|
+
export function isSeriesWithNumericalXValues(series) {
|
|
18
|
+
return isAxisRelatedSeries(series);
|
|
19
|
+
}
|
|
20
|
+
export function isSeriesWithNumericalYValues(series) {
|
|
21
|
+
return isAxisRelatedSeries(series);
|
|
22
|
+
}
|
|
23
|
+
export function isSeriesWithCategoryValues(series) {
|
|
24
|
+
return isAxisRelatedSeries(series);
|
|
25
|
+
}
|
|
14
26
|
export const getDomainDataXBySeries = (series) => {
|
|
15
|
-
return series.
|
|
16
|
-
|
|
27
|
+
return series.reduce((acc, s) => {
|
|
28
|
+
if (isSeriesWithNumericalXValues(s)) {
|
|
29
|
+
acc.push(...s.data.map((d) => d.x));
|
|
30
|
+
}
|
|
17
31
|
return acc;
|
|
18
32
|
}, []);
|
|
19
33
|
};
|
|
20
34
|
export const getDomainDataYBySeries = (series) => {
|
|
21
|
-
return series.filter(
|
|
22
|
-
acc.push(...s.data.map((d) =>
|
|
35
|
+
return series.filter(isSeriesWithNumericalYValues).reduce((acc, s) => {
|
|
36
|
+
acc.push(...s.data.map((d) => d.y));
|
|
23
37
|
return acc;
|
|
24
38
|
}, []);
|
|
25
39
|
};
|
|
@@ -64,3 +78,26 @@ export const formatAxisTickLabel = (args) => {
|
|
|
64
78
|
}
|
|
65
79
|
}
|
|
66
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* Calculates the height of a text element in a horizontal SVG layout.
|
|
83
|
+
*
|
|
84
|
+
* @param {Object} args - The arguments for the function.
|
|
85
|
+
* @param {string} args.text - The text to be measured.
|
|
86
|
+
* @param {Partial<BaseTextStyle>} args.style - Optional style properties for the text element.
|
|
87
|
+
* @return {number} The height of the text element.
|
|
88
|
+
*/
|
|
89
|
+
export const getHorisontalSvgTextHeight = (args) => {
|
|
90
|
+
const { text, style } = args;
|
|
91
|
+
const textSelection = select(document.body).append('text').text(text);
|
|
92
|
+
const fontSize = get(style, 'fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE);
|
|
93
|
+
let height = 0;
|
|
94
|
+
if (fontSize) {
|
|
95
|
+
textSelection.style('font-size', fontSize);
|
|
96
|
+
}
|
|
97
|
+
textSelection
|
|
98
|
+
.each(function () {
|
|
99
|
+
height = this.getBoundingClientRect().height;
|
|
100
|
+
})
|
|
101
|
+
.remove();
|
|
102
|
+
return height;
|
|
103
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
2
2
|
import type { ChartKitWidgetSeriesOptions } from './series';
|
|
3
|
+
import { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
3
4
|
export type BarXSeriesData<T = any> = BaseSeriesData<T> & {
|
|
4
5
|
/** The x value of the point */
|
|
5
6
|
x?: number;
|
|
@@ -28,4 +29,8 @@ export type BarXSeries<T = any> = BaseSeries & {
|
|
|
28
29
|
/** Whether to align the data label inside the box or to the actual value point */
|
|
29
30
|
inside?: boolean;
|
|
30
31
|
};
|
|
32
|
+
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
33
|
+
legend?: ChartKitWidgetLegend & {
|
|
34
|
+
symbol?: RectLegendSymbolOptions;
|
|
35
|
+
};
|
|
31
36
|
};
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import type { ChartKitWidgetLegend } from './legend';
|
|
2
1
|
export type BaseSeries = {
|
|
3
|
-
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
4
|
-
legend?: ChartKitWidgetLegend;
|
|
5
2
|
/** Initial visibility of the series */
|
|
6
3
|
visible?: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Options for the series data labels, appearing next to each data point.
|
|
6
|
+
*
|
|
7
|
+
* Note: now this option is supported only for `pie` charts.
|
|
8
|
+
* */
|
|
9
|
+
dataLabels?: {
|
|
10
|
+
/**
|
|
11
|
+
* Enable or disable the data labels
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
};
|
|
7
16
|
};
|
|
8
17
|
export type BaseSeriesData<T = any> = {
|
|
9
18
|
/**
|
|
@@ -1,3 +1,35 @@
|
|
|
1
1
|
export type ChartKitWidgetLegend = {
|
|
2
2
|
enabled?: boolean;
|
|
3
|
+
/** The horizontal alignment of the legend box within the chart area.
|
|
4
|
+
*
|
|
5
|
+
* @default center
|
|
6
|
+
* */
|
|
7
|
+
align?: 'left' | 'center' | 'right';
|
|
8
|
+
/** Defines the pixel distance between each legend item
|
|
9
|
+
*
|
|
10
|
+
* @default 20
|
|
11
|
+
* */
|
|
12
|
+
itemDistance?: number;
|
|
13
|
+
};
|
|
14
|
+
export type BaseLegendSymbol = {
|
|
15
|
+
/** The pixel padding between the legend item symbol and the legend item text.
|
|
16
|
+
*
|
|
17
|
+
* @default 5
|
|
18
|
+
* */
|
|
19
|
+
padding?: number;
|
|
20
|
+
};
|
|
21
|
+
export type RectLegendSymbolOptions = BaseLegendSymbol & {
|
|
22
|
+
/** The pixel width of the symbol for series types that use a rectangle in the legend
|
|
23
|
+
*
|
|
24
|
+
* @default 10
|
|
25
|
+
* */
|
|
26
|
+
width?: number;
|
|
27
|
+
/** The pixel width of the symbol for series types that use a rectangle in the legend
|
|
28
|
+
*
|
|
29
|
+
* @default 10
|
|
30
|
+
* */
|
|
31
|
+
height?: number;
|
|
32
|
+
/** The border radius of the symbol for series types that use a rectangle in the legend.
|
|
33
|
+
* Defaults to half the symbolHeight, effectively creating a circle. */
|
|
34
|
+
radius?: number;
|
|
3
35
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
2
|
+
import { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
2
3
|
export type PieSeriesData<T = any> = BaseSeriesData<T> & {
|
|
3
4
|
/** The value of the pie segment. */
|
|
4
5
|
value: number;
|
|
@@ -8,20 +9,38 @@ export type PieSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
8
9
|
color?: string;
|
|
9
10
|
/** Initial visibility of the pie segment. */
|
|
10
11
|
visible?: boolean;
|
|
12
|
+
/** Initial data label of the pie segment. If not specified, the value is used. */
|
|
13
|
+
label?: string;
|
|
11
14
|
};
|
|
12
15
|
export type PieSeries<T = any> = BaseSeries & {
|
|
13
16
|
type: 'pie';
|
|
14
17
|
data: PieSeriesData<T>[];
|
|
15
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The color of the border surrounding each segment.
|
|
20
|
+
* @default `--g-color-base-background` from @gravity-ui/uikit.
|
|
21
|
+
*/
|
|
16
22
|
borderColor?: string;
|
|
17
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* The width of the border surrounding each segment.
|
|
25
|
+
* @default '1px'
|
|
26
|
+
*/
|
|
18
27
|
borderWidth?: number;
|
|
19
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* The corner radius of the border surrounding each segment.
|
|
30
|
+
* @default 0
|
|
31
|
+
*/
|
|
20
32
|
borderRadius?: number;
|
|
21
33
|
/** The center of the pie chart relative to the chart area. */
|
|
22
34
|
center?: [string | number | null, string | number | null];
|
|
23
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* The inner radius of the pie.
|
|
37
|
+
* @default 0
|
|
38
|
+
*/
|
|
24
39
|
innerRadius?: string | number;
|
|
25
40
|
/** The radius of the pie relative to the chart area. The default behaviour is to scale to the chart area. */
|
|
26
41
|
radius?: string | number;
|
|
42
|
+
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
43
|
+
legend?: ChartKitWidgetLegend & {
|
|
44
|
+
symbol?: RectLegendSymbolOptions;
|
|
45
|
+
};
|
|
27
46
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
2
|
+
import type { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
2
3
|
export type ScatterSeriesData<T = any> = BaseSeriesData<T> & {
|
|
3
4
|
/** The x value of the point */
|
|
4
5
|
x?: number;
|
|
@@ -17,4 +18,8 @@ export type ScatterSeries<T = any> = BaseSeries & {
|
|
|
17
18
|
color?: string;
|
|
18
19
|
/** A predefined shape or symbol for the dot */
|
|
19
20
|
symbol?: string;
|
|
21
|
+
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
22
|
+
legend?: ChartKitWidgetLegend & {
|
|
23
|
+
symbol?: RectLegendSymbolOptions;
|
|
24
|
+
};
|
|
20
25
|
};
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { select } from 'd3';
|
|
2
|
-
import get from 'lodash/get';
|
|
3
|
-
import { DEFAULT_AXIS_LABEL_FONT_SIZE } from './constants';
|
|
4
|
-
export const getHorisontalSvgTextDimensions = (args) => {
|
|
5
|
-
const { text, style } = args;
|
|
6
|
-
const textSelection = select(document.body).append('text').text(text);
|
|
7
|
-
const fontSize = get(style, 'fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE);
|
|
8
|
-
let height = 0;
|
|
9
|
-
if (fontSize) {
|
|
10
|
-
textSelection.style('font-size', fontSize);
|
|
11
|
-
}
|
|
12
|
-
textSelection
|
|
13
|
-
.each(function () {
|
|
14
|
-
height = this.getBoundingClientRect().height;
|
|
15
|
-
})
|
|
16
|
-
.remove();
|
|
17
|
-
return height;
|
|
18
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
|
|
2
|
-
export type OnLegendItemClick = (data: {
|
|
3
|
-
name: string;
|
|
4
|
-
metaKey: boolean;
|
|
5
|
-
}) => void;
|
|
6
|
-
type Args = {
|
|
7
|
-
series: ChartKitWidgetSeries[];
|
|
8
|
-
};
|
|
9
|
-
export declare const useLegend: (args: Args) => {
|
|
10
|
-
activeLegendItems: string[];
|
|
11
|
-
handleLegendItemClick: OnLegendItemClick;
|
|
12
|
-
};
|
|
13
|
-
export {};
|