@gravity-ui/chartkit 4.4.1 → 4.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/AxisX.d.ts +2 -1
- package/build/plugins/d3/renderer/components/AxisX.js +51 -49
- package/build/plugins/d3/renderer/components/AxisY.js +28 -31
- package/build/plugins/d3/renderer/components/Chart.js +19 -7
- package/build/plugins/d3/renderer/components/Legend.d.ts +5 -6
- package/build/plugins/d3/renderer/components/Legend.js +139 -84
- package/build/plugins/d3/renderer/components/styles.css +27 -0
- package/build/plugins/d3/renderer/constants/defaults/axis.d.ts +5 -0
- package/build/plugins/d3/renderer/constants/defaults/axis.js +5 -0
- package/build/plugins/d3/renderer/constants/defaults/index.d.ts +2 -0
- package/build/plugins/d3/renderer/constants/defaults/index.js +2 -0
- package/build/plugins/d3/renderer/constants/defaults/legend.d.ts +4 -0
- package/build/plugins/d3/renderer/constants/defaults/legend.js +8 -0
- package/build/plugins/d3/renderer/{constants.d.ts → constants/index.d.ts} +1 -1
- package/build/plugins/d3/renderer/{constants.js → constants/index.js} +1 -1
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +3 -1
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +64 -59
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +7 -4
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +65 -7
- package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.d.ts +6 -0
- package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.js +7 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.d.ts +1 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +12 -75
- package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/index.js +3 -8
- package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +3 -6
- package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +4 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +3 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +31 -4
- package/build/plugins/d3/renderer/hooks/useSeries/constants.d.ts +1 -1
- package/build/plugins/d3/renderer/hooks/useSeries/constants.js +1 -1
- package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +19 -7
- package/build/plugins/d3/renderer/hooks/useSeries/index.js +26 -8
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.d.ts +27 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.js +92 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +1 -2
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +26 -1
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +21 -0
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +75 -0
- package/build/plugins/d3/renderer/utils/axis-generators/index.d.ts +1 -0
- package/build/plugins/d3/renderer/utils/axis-generators/index.js +1 -0
- package/build/plugins/d3/renderer/utils/axis.d.ts +22 -0
- package/build/plugins/d3/renderer/utils/axis.js +49 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +8 -4
- package/build/plugins/d3/renderer/utils/index.js +17 -6
- package/build/plugins/d3/renderer/utils/text.d.ts +20 -0
- package/build/plugins/d3/renderer/utils/text.js +62 -0
- package/build/plugins/d3/renderer/utils/time.d.ts +3 -0
- package/build/plugins/d3/renderer/utils/time.js +34 -0
- package/build/plugins/highcharts/renderer/components/HighchartsComponent.js +3 -3
- package/build/plugins/shared/format-number/format-number.d.ts +1 -0
- package/build/plugins/shared/format-number/format-number.js +19 -20
- package/build/types/widget-data/axis.d.ts +13 -1
- package/build/types/widget-data/legend.d.ts +24 -7
- package/build/utils/common.d.ts +1 -0
- package/build/utils/common.js +1 -1
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.js +1 -1
- package/package.json +2 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.d.ts +0 -6
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +0 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
|
-
import type { ChartOptions } from '../useChartOptions/types';
|
|
2
|
+
import type { ChartOptions, PreparedAxis } from '../useChartOptions/types';
|
|
3
3
|
import { PreparedSeries } from '../useSeries/types';
|
|
4
4
|
export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
|
|
5
5
|
type Args = {
|
|
@@ -13,6 +13,8 @@ type ReturnValue = {
|
|
|
13
13
|
xScale?: ChartScale;
|
|
14
14
|
yScale?: ChartScale;
|
|
15
15
|
};
|
|
16
|
+
export declare function createYScale(axis: PreparedAxis, series: PreparedSeries[], boundsHeight: number): ScaleLinear<number, number, never> | ScaleBand<string> | ScaleTime<number, number, never>;
|
|
17
|
+
export declare function createXScale(axis: PreparedAxis, series: PreparedSeries[], boundsWidth: number): ScaleLinear<number, number, never> | ScaleBand<string> | ScaleTime<number, number, never>;
|
|
16
18
|
/**
|
|
17
19
|
* Uses to create scales for axis related series
|
|
18
20
|
*/
|
|
@@ -17,105 +17,110 @@ const filterCategoriesByVisibleSeries = (args) => {
|
|
|
17
17
|
});
|
|
18
18
|
return categories.filter((c) => visibleCategories.has(c));
|
|
19
19
|
};
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const yType = get(yAxis[0], 'type', 'linear');
|
|
27
|
-
const yMin = get(yAxis[0], 'min');
|
|
28
|
-
const yCategories = get(yAxis[0], 'categories');
|
|
29
|
-
const yTimestamps = get(xAxis, 'timestamps');
|
|
30
|
-
let visibleSeries = getOnlyVisibleSeries(series);
|
|
31
|
-
// Reassign to all series in case of all series unselected,
|
|
32
|
-
// otherwise we will get an empty space without grid
|
|
33
|
-
visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
|
|
34
|
-
let xScale;
|
|
35
|
-
let yScale;
|
|
36
|
-
switch (xType) {
|
|
20
|
+
export function createYScale(axis, series, boundsHeight) {
|
|
21
|
+
const yType = get(axis, 'type', 'linear');
|
|
22
|
+
const yMin = get(axis, 'min');
|
|
23
|
+
const yCategories = get(axis, 'categories');
|
|
24
|
+
const yTimestamps = get(axis, 'timestamps');
|
|
25
|
+
switch (yType) {
|
|
37
26
|
case 'linear': {
|
|
38
|
-
const domain =
|
|
39
|
-
const range = [
|
|
27
|
+
const domain = getDomainDataYBySeries(series);
|
|
28
|
+
const range = [boundsHeight, boundsHeight * axis.maxPadding];
|
|
40
29
|
if (isNumericalArrayData(domain)) {
|
|
41
|
-
const [
|
|
42
|
-
const
|
|
43
|
-
|
|
30
|
+
const [domainYMin, yMax] = extent(domain);
|
|
31
|
+
const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
|
|
32
|
+
return scaleLinear().domain([yMinValue, yMax]).range(range).nice();
|
|
44
33
|
}
|
|
45
34
|
break;
|
|
46
35
|
}
|
|
47
36
|
case 'category': {
|
|
48
|
-
if (
|
|
37
|
+
if (yCategories) {
|
|
49
38
|
const filteredCategories = filterCategoriesByVisibleSeries({
|
|
50
|
-
axisDirection: '
|
|
51
|
-
categories:
|
|
52
|
-
series:
|
|
39
|
+
axisDirection: 'y',
|
|
40
|
+
categories: yCategories,
|
|
41
|
+
series: series,
|
|
53
42
|
});
|
|
54
|
-
|
|
43
|
+
return scaleBand().domain(filteredCategories).range([boundsHeight, 0]);
|
|
55
44
|
}
|
|
56
45
|
break;
|
|
57
46
|
}
|
|
58
47
|
case 'datetime': {
|
|
59
|
-
const range = [
|
|
60
|
-
if (
|
|
61
|
-
const [
|
|
62
|
-
|
|
48
|
+
const range = [boundsHeight, boundsHeight * axis.maxPadding];
|
|
49
|
+
if (yTimestamps) {
|
|
50
|
+
const [yMin, yMax] = extent(yTimestamps);
|
|
51
|
+
return scaleUtc().domain([yMin, yMax]).range(range).nice();
|
|
63
52
|
}
|
|
64
53
|
else {
|
|
65
|
-
const domain =
|
|
54
|
+
const domain = getDomainDataYBySeries(series);
|
|
66
55
|
if (isNumericalArrayData(domain)) {
|
|
67
|
-
const [
|
|
68
|
-
|
|
56
|
+
const [yMin, yMax] = extent(domain);
|
|
57
|
+
return scaleUtc().domain([yMin, yMax]).range(range).nice();
|
|
69
58
|
}
|
|
70
59
|
}
|
|
71
60
|
break;
|
|
72
61
|
}
|
|
73
62
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
63
|
+
throw new Error('Failed to create yScale');
|
|
64
|
+
}
|
|
65
|
+
export function createXScale(axis, series, boundsWidth) {
|
|
66
|
+
const xMin = get(axis, 'min');
|
|
67
|
+
const xType = get(axis, 'type', 'linear');
|
|
68
|
+
const xCategories = get(axis, 'categories');
|
|
69
|
+
const xTimestamps = get(axis, 'timestamps');
|
|
70
|
+
const xAxisMinPadding = boundsWidth * axis.maxPadding;
|
|
71
|
+
const xRange = [0, boundsWidth - xAxisMinPadding];
|
|
72
|
+
switch (xType) {
|
|
78
73
|
case 'linear': {
|
|
79
|
-
const domain =
|
|
80
|
-
const range = [boundsHeight, boundsHeight * yAxis[0].maxPadding];
|
|
74
|
+
const domain = getDomainDataXBySeries(series);
|
|
81
75
|
if (isNumericalArrayData(domain)) {
|
|
82
|
-
const [
|
|
83
|
-
const
|
|
84
|
-
|
|
76
|
+
const [domainXMin, xMax] = extent(domain);
|
|
77
|
+
const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
|
|
78
|
+
return scaleLinear().domain([xMinValue, xMax]).range(xRange).nice();
|
|
85
79
|
}
|
|
86
80
|
break;
|
|
87
81
|
}
|
|
88
82
|
case 'category': {
|
|
89
|
-
if (
|
|
83
|
+
if (xCategories) {
|
|
90
84
|
const filteredCategories = filterCategoriesByVisibleSeries({
|
|
91
|
-
axisDirection: '
|
|
92
|
-
categories:
|
|
93
|
-
series:
|
|
85
|
+
axisDirection: 'x',
|
|
86
|
+
categories: xCategories,
|
|
87
|
+
series: series,
|
|
94
88
|
});
|
|
95
|
-
|
|
89
|
+
const xScale = scaleBand().domain(filteredCategories).range([0, boundsWidth]);
|
|
90
|
+
if (xScale.step() / 2 < xAxisMinPadding) {
|
|
91
|
+
xScale.range(xRange);
|
|
92
|
+
}
|
|
93
|
+
return xScale;
|
|
96
94
|
}
|
|
97
95
|
break;
|
|
98
96
|
}
|
|
99
97
|
case 'datetime': {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
yScale = scaleUtc().domain([yMin, yMax]).range(range).nice();
|
|
98
|
+
if (xTimestamps) {
|
|
99
|
+
const [xMin, xMax] = extent(xTimestamps);
|
|
100
|
+
return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
|
|
104
101
|
}
|
|
105
102
|
else {
|
|
106
|
-
const domain =
|
|
103
|
+
const domain = getDomainDataXBySeries(series);
|
|
107
104
|
if (isNumericalArrayData(domain)) {
|
|
108
|
-
const [
|
|
109
|
-
|
|
105
|
+
const [xMin, xMax] = extent(domain);
|
|
106
|
+
return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
109
|
break;
|
|
113
110
|
}
|
|
114
111
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
throw new Error('Failed to create xScale');
|
|
113
|
+
}
|
|
114
|
+
const createScales = (args) => {
|
|
115
|
+
const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
|
|
116
|
+
let visibleSeries = getOnlyVisibleSeries(series);
|
|
117
|
+
// Reassign to all series in case of all series unselected,
|
|
118
|
+
// otherwise we will get an empty space without grid
|
|
119
|
+
visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
|
|
120
|
+
return {
|
|
121
|
+
xScale: createXScale(xAxis, visibleSeries, boundsWidth),
|
|
122
|
+
yScale: createYScale(yAxis[0], visibleSeries, boundsHeight),
|
|
123
|
+
};
|
|
119
124
|
};
|
|
120
125
|
/**
|
|
121
126
|
* Uses to create scales for axis related series
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import type { ChartMargin } from '../../../../../types
|
|
2
|
-
import type { PreparedAxis } from '
|
|
1
|
+
import type { ChartMargin } from '../../../../../types';
|
|
2
|
+
import type { PreparedAxis, PreparedLegend, PreparedSeries } from '../../hooks';
|
|
3
|
+
export { getBoundsWidth } from './utils';
|
|
3
4
|
type Args = {
|
|
4
5
|
width: number;
|
|
5
6
|
height: number;
|
|
6
7
|
margin: ChartMargin;
|
|
7
|
-
|
|
8
|
+
preparedLegend: PreparedLegend;
|
|
9
|
+
preparedXAxis: PreparedAxis;
|
|
10
|
+
preparedYAxis: PreparedAxis[];
|
|
11
|
+
preparedSeries: PreparedSeries[];
|
|
8
12
|
};
|
|
9
13
|
export declare const useChartDimensions: (args: Args) => {
|
|
10
14
|
boundsWidth: number;
|
|
11
15
|
boundsHeight: number;
|
|
12
16
|
};
|
|
13
|
-
export {};
|
|
@@ -1,9 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { createXScale } from '../../hooks';
|
|
3
|
+
import { formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsMaxHeight, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, isAxisRelatedSeries, } from '../../utils';
|
|
4
|
+
import { getBoundsWidth } from './utils';
|
|
5
|
+
export { getBoundsWidth } from './utils';
|
|
6
|
+
const getHeightOccupiedByXAxis = ({ preparedXAxis, preparedSeries, width, }) => {
|
|
7
|
+
let height = preparedXAxis.title.height;
|
|
8
|
+
if (preparedXAxis.labels.enabled) {
|
|
9
|
+
const scale = createXScale(preparedXAxis, preparedSeries, width);
|
|
10
|
+
const tickCount = getTicksCount({ axis: preparedXAxis, range: width });
|
|
11
|
+
const ticks = getXAxisItems({
|
|
12
|
+
scale: scale,
|
|
13
|
+
count: tickCount,
|
|
14
|
+
maxCount: getMaxTickCount({ width, axis: preparedXAxis }),
|
|
15
|
+
});
|
|
16
|
+
const step = getClosestPointsRange(preparedXAxis, ticks);
|
|
17
|
+
const labels = ticks.map((value) => {
|
|
18
|
+
return formatAxisTickLabel({
|
|
19
|
+
axis: preparedXAxis,
|
|
20
|
+
value,
|
|
21
|
+
step,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
const overlapping = hasOverlappingLabels({
|
|
25
|
+
width,
|
|
26
|
+
labels,
|
|
27
|
+
padding: preparedXAxis.labels.padding,
|
|
28
|
+
style: preparedXAxis.labels.style,
|
|
29
|
+
});
|
|
30
|
+
const labelsHeight = overlapping
|
|
31
|
+
? getLabelsMaxHeight({
|
|
32
|
+
labels,
|
|
33
|
+
style: preparedXAxis.labels.style,
|
|
34
|
+
transform: 'rotate(-45)',
|
|
35
|
+
})
|
|
36
|
+
: getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedXAxis.labels.style });
|
|
37
|
+
height += preparedXAxis.labels.margin + labelsHeight;
|
|
38
|
+
}
|
|
39
|
+
return height;
|
|
40
|
+
};
|
|
41
|
+
const getBottomOffset = (args) => {
|
|
42
|
+
const { hasAxisRelatedSeries, preparedLegend, preparedXAxis, preparedSeries, width } = args;
|
|
43
|
+
let result = 0;
|
|
44
|
+
if (preparedLegend.enabled) {
|
|
45
|
+
result += preparedLegend.height + preparedLegend.margin;
|
|
46
|
+
}
|
|
47
|
+
if (hasAxisRelatedSeries) {
|
|
48
|
+
result += getHeightOccupiedByXAxis({ preparedXAxis, preparedSeries, width });
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
1
52
|
export const useChartDimensions = (args) => {
|
|
2
|
-
const { margin, width, height,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
53
|
+
const { margin, width, height, preparedLegend, preparedXAxis, preparedYAxis, preparedSeries } = args;
|
|
54
|
+
return React.useMemo(() => {
|
|
55
|
+
const hasAxisRelatedSeries = preparedSeries.some(isAxisRelatedSeries);
|
|
56
|
+
const boundsWidth = getBoundsWidth({ chartWidth: width, chartMargin: margin, preparedYAxis });
|
|
57
|
+
const bottomOffset = getBottomOffset({
|
|
58
|
+
hasAxisRelatedSeries,
|
|
59
|
+
preparedLegend,
|
|
60
|
+
preparedXAxis,
|
|
61
|
+
preparedSeries,
|
|
62
|
+
width: boundsWidth,
|
|
63
|
+
});
|
|
64
|
+
const boundsHeight = height - margin.top - margin.bottom - bottomOffset;
|
|
65
|
+
return { boundsWidth, boundsHeight };
|
|
66
|
+
}, [margin, width, height, preparedLegend, preparedXAxis, preparedYAxis, preparedSeries]);
|
|
9
67
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const getBoundsWidth = (args) => {
|
|
2
|
+
const { chartWidth, chartMargin, preparedYAxis } = args;
|
|
3
|
+
const yAxisTitleHeight = preparedYAxis.reduce((acc, axis) => {
|
|
4
|
+
return acc + (axis.title.height || 0);
|
|
5
|
+
}, 0) || 0;
|
|
6
|
+
return chartWidth - chartMargin.right - chartMargin.left - yAxisTitleHeight;
|
|
7
|
+
};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
|
-
import type { PreparedAxis, PreparedChart, PreparedTitle
|
|
2
|
+
import type { PreparedAxis, PreparedChart, PreparedTitle } from './types';
|
|
3
3
|
export declare const getPreparedChart: (args: {
|
|
4
4
|
chart: ChartKitWidgetData['chart'];
|
|
5
5
|
series: ChartKitWidgetData['series'];
|
|
6
|
-
preparedLegend: PreparedLegend;
|
|
7
|
-
preparedXAxis: PreparedAxis;
|
|
8
6
|
preparedY1Axis: PreparedAxis;
|
|
9
7
|
preparedTitle?: PreparedTitle;
|
|
10
8
|
}) => PreparedChart;
|
|
@@ -1,47 +1,6 @@
|
|
|
1
|
-
import { select, max } from 'd3';
|
|
2
1
|
import get from 'lodash/get';
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
5
|
-
const getAxisLabelMaxWidth = (args) => {
|
|
6
|
-
const { axis, series } = args;
|
|
7
|
-
let maxDomainValue;
|
|
8
|
-
let width = 0;
|
|
9
|
-
switch (axis.type) {
|
|
10
|
-
case 'category': {
|
|
11
|
-
const yCategories = get(axis, 'categories', []);
|
|
12
|
-
maxDomainValue = [...yCategories].sort((c1, c2) => c2.length - c1.length)[0];
|
|
13
|
-
break;
|
|
14
|
-
}
|
|
15
|
-
case 'datetime': {
|
|
16
|
-
const yTimestamps = get(axis, 'timestamps');
|
|
17
|
-
const domain = yTimestamps || getDomainDataYBySeries(series);
|
|
18
|
-
maxDomainValue = max(domain);
|
|
19
|
-
break;
|
|
20
|
-
}
|
|
21
|
-
case 'linear': {
|
|
22
|
-
const domain = getDomainDataYBySeries(series);
|
|
23
|
-
maxDomainValue = max(domain);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
let formattedValue = '';
|
|
27
|
-
if (axis.labels.enabled) {
|
|
28
|
-
formattedValue = formatAxisTickLabel({
|
|
29
|
-
axisType: axis.type,
|
|
30
|
-
value: maxDomainValue,
|
|
31
|
-
dateFormat: axis.labels['dateFormat'],
|
|
32
|
-
numberFormat: axis.labels['numberFormat'],
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
select(document.body)
|
|
36
|
-
.append('text')
|
|
37
|
-
.style('font-size', axis.labels.style.fontSize)
|
|
38
|
-
.text(formattedValue)
|
|
39
|
-
.each(function () {
|
|
40
|
-
width = this.getBoundingClientRect().width;
|
|
41
|
-
})
|
|
42
|
-
.remove();
|
|
43
|
-
return width;
|
|
44
|
-
};
|
|
2
|
+
import { isAxisRelatedSeries, getHorisontalSvgTextHeight } from '../../utils';
|
|
3
|
+
const AXIS_LINE_WIDTH = 1;
|
|
45
4
|
const getMarginTop = (args) => {
|
|
46
5
|
const { chart, hasAxisRelatedSeries, preparedY1Axis, preparedTitle } = args;
|
|
47
6
|
let marginTop = get(chart, 'margin.top', 0);
|
|
@@ -54,51 +13,29 @@ const getMarginTop = (args) => {
|
|
|
54
13
|
}
|
|
55
14
|
return marginTop;
|
|
56
15
|
};
|
|
57
|
-
const getMarginBottom = (args) => {
|
|
58
|
-
const { chart, hasAxisRelatedSeries, preparedLegend, preparedXAxis } = args;
|
|
59
|
-
let marginBottom = get(chart, 'margin.bottom', 0) + preparedLegend.height;
|
|
60
|
-
if (hasAxisRelatedSeries) {
|
|
61
|
-
marginBottom +=
|
|
62
|
-
preparedXAxis.title.height +
|
|
63
|
-
getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedXAxis.labels.style });
|
|
64
|
-
if (preparedXAxis.labels.enabled) {
|
|
65
|
-
marginBottom += preparedXAxis.labels.padding;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return marginBottom;
|
|
69
|
-
};
|
|
70
16
|
const getMarginLeft = (args) => {
|
|
71
|
-
const { chart, hasAxisRelatedSeries,
|
|
17
|
+
const { chart, hasAxisRelatedSeries, preparedY1Axis } = args;
|
|
72
18
|
let marginLeft = get(chart, 'margin.left', 0);
|
|
73
19
|
if (hasAxisRelatedSeries) {
|
|
74
20
|
marginLeft +=
|
|
75
|
-
|
|
76
|
-
preparedY1Axis.labels.
|
|
77
|
-
|
|
21
|
+
AXIS_LINE_WIDTH +
|
|
22
|
+
preparedY1Axis.labels.margin +
|
|
23
|
+
(preparedY1Axis.labels.maxWidth || 0) +
|
|
78
24
|
preparedY1Axis.title.height;
|
|
79
25
|
}
|
|
80
26
|
return marginLeft;
|
|
81
27
|
};
|
|
82
28
|
const getMarginRight = (args) => {
|
|
83
|
-
const { chart
|
|
84
|
-
|
|
85
|
-
if (hasAxisRelatedSeries) {
|
|
86
|
-
marginRight += getAxisLabelMaxWidth({ axis: preparedXAxis, series: series.data }) / 2;
|
|
87
|
-
}
|
|
88
|
-
return marginRight;
|
|
29
|
+
const { chart } = args;
|
|
30
|
+
return get(chart, 'margin.right', 0);
|
|
89
31
|
};
|
|
90
32
|
export const getPreparedChart = (args) => {
|
|
91
|
-
const { chart, series,
|
|
33
|
+
const { chart, series, preparedY1Axis, preparedTitle } = args;
|
|
92
34
|
const hasAxisRelatedSeries = series.data.some(isAxisRelatedSeries);
|
|
93
35
|
const marginTop = getMarginTop({ chart, hasAxisRelatedSeries, preparedY1Axis, preparedTitle });
|
|
94
|
-
const marginBottom =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
preparedLegend,
|
|
98
|
-
preparedXAxis,
|
|
99
|
-
});
|
|
100
|
-
const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, series, preparedY1Axis });
|
|
101
|
-
const marginRight = getMarginRight({ chart, hasAxisRelatedSeries, series, preparedXAxis });
|
|
36
|
+
const marginBottom = get(chart, 'margin.bottom', 0);
|
|
37
|
+
const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, preparedY1Axis });
|
|
38
|
+
const marginRight = getMarginRight({ chart });
|
|
102
39
|
return {
|
|
103
40
|
margin: {
|
|
104
41
|
top: marginTop,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
2
|
import type { ChartOptions } from './types';
|
|
3
|
-
type Args =
|
|
3
|
+
type Args = {
|
|
4
|
+
data: ChartKitWidgetData;
|
|
5
|
+
};
|
|
4
6
|
export declare const useChartOptions: (args: Args) => ChartOptions;
|
|
5
7
|
export {};
|
|
@@ -1,34 +1,29 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { getPreparedChart } from './chart';
|
|
3
|
-
import { getPreparedLegend } from './legend';
|
|
4
3
|
import { getPreparedTitle } from './title';
|
|
5
4
|
import { getPreparedTooltip } from './tooltip';
|
|
6
5
|
import { getPreparedXAxis } from './x-axis';
|
|
7
6
|
import { getPreparedYAxis } from './y-axis';
|
|
8
7
|
export const useChartOptions = (args) => {
|
|
9
|
-
const { chart, series,
|
|
8
|
+
const { data: { chart, series, title, tooltip, xAxis, yAxis }, } = args;
|
|
10
9
|
const options = React.useMemo(() => {
|
|
11
10
|
const preparedTitle = getPreparedTitle({ title });
|
|
12
11
|
const preparedTooltip = getPreparedTooltip({ tooltip });
|
|
13
|
-
const
|
|
14
|
-
const preparedYAxis = getPreparedYAxis({ yAxis });
|
|
12
|
+
const preparedYAxis = getPreparedYAxis({ series: series.data, yAxis });
|
|
15
13
|
const preparedXAxis = getPreparedXAxis({ xAxis });
|
|
16
14
|
const preparedChart = getPreparedChart({
|
|
17
15
|
chart,
|
|
18
16
|
series,
|
|
19
17
|
preparedTitle,
|
|
20
|
-
preparedLegend,
|
|
21
|
-
preparedXAxis,
|
|
22
18
|
preparedY1Axis: preparedYAxis[0],
|
|
23
19
|
});
|
|
24
20
|
return {
|
|
25
21
|
chart: preparedChart,
|
|
26
|
-
legend: preparedLegend,
|
|
27
22
|
title: preparedTitle,
|
|
28
23
|
tooltip: preparedTooltip,
|
|
29
24
|
xAxis: preparedXAxis,
|
|
30
25
|
yAxis: preparedYAxis,
|
|
31
26
|
};
|
|
32
|
-
}, [chart,
|
|
27
|
+
}, [chart, title, tooltip, series, xAxis, yAxis]);
|
|
33
28
|
return options;
|
|
34
29
|
};
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type { BaseTextStyle, ChartKitWidgetData, ChartKitWidgetAxis, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels,
|
|
2
|
-
type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'style'> & Required<Pick<ChartKitWidgetAxisLabels, 'enabled' | 'padding'>> & {
|
|
1
|
+
import type { BaseTextStyle, ChartKitWidgetData, ChartKitWidgetAxis, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels, ChartMargin } from '../../../../../types/widget-data';
|
|
2
|
+
type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'style'> & Required<Pick<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'margin'>> & {
|
|
3
3
|
style: BaseTextStyle;
|
|
4
|
+
maxWidth?: number;
|
|
4
5
|
};
|
|
5
6
|
export type PreparedChart = {
|
|
6
7
|
margin: ChartMargin;
|
|
7
8
|
};
|
|
8
|
-
export type PreparedLegend = Required<ChartKitWidgetLegend> & {
|
|
9
|
-
height: number;
|
|
10
|
-
};
|
|
11
9
|
export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
|
|
12
10
|
type: ChartKitWidgetAxisType;
|
|
13
11
|
labels: PreparedAxisLabels;
|
|
@@ -33,7 +31,6 @@ export type PreparedTooltip = ChartKitWidgetData['tooltip'] & {
|
|
|
33
31
|
};
|
|
34
32
|
export type ChartOptions = {
|
|
35
33
|
chart: PreparedChart;
|
|
36
|
-
legend: PreparedLegend;
|
|
37
34
|
tooltip: PreparedTooltip;
|
|
38
35
|
xAxis: PreparedAxis;
|
|
39
36
|
yAxis: PreparedAxis[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import {
|
|
2
|
+
import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
|
|
3
3
|
import { getHorisontalSvgTextHeight } from '../../utils';
|
|
4
4
|
export const getPreparedXAxis = ({ xAxis }) => {
|
|
5
5
|
const titleText = get(xAxis, 'title.text', '');
|
|
@@ -10,9 +10,11 @@ export const getPreparedXAxis = ({ xAxis }) => {
|
|
|
10
10
|
type: get(xAxis, 'type', 'linear'),
|
|
11
11
|
labels: {
|
|
12
12
|
enabled: get(xAxis, 'labels.enabled', true),
|
|
13
|
-
|
|
13
|
+
margin: get(xAxis, 'labels.margin', axisLabelsDefaults.margin),
|
|
14
|
+
padding: get(xAxis, 'labels.padding', axisLabelsDefaults.padding),
|
|
14
15
|
dateFormat: get(xAxis, 'labels.dateFormat'),
|
|
15
16
|
numberFormat: get(xAxis, 'labels.numberFormat'),
|
|
17
|
+
autoRotation: get(xAxis, 'labels.autoRotation', true),
|
|
16
18
|
style: { fontSize: get(xAxis, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE) },
|
|
17
19
|
},
|
|
18
20
|
lineColor: get(xAxis, 'lineColor'),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
1
|
+
import type { ChartKitWidgetData, ChartKitWidgetSeries } from '../../../../../types/widget-data';
|
|
2
2
|
import type { PreparedAxis } from './types';
|
|
3
|
-
export declare const getPreparedYAxis: ({ yAxis }: {
|
|
3
|
+
export declare const getPreparedYAxis: ({ series, yAxis, }: {
|
|
4
|
+
series: ChartKitWidgetSeries[];
|
|
4
5
|
yAxis: ChartKitWidgetData['yAxis'];
|
|
5
6
|
}) => PreparedAxis[];
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import {
|
|
3
|
-
import { getHorisontalSvgTextHeight } from '../../utils';
|
|
4
|
-
|
|
2
|
+
import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
|
|
3
|
+
import { getHorisontalSvgTextHeight, formatAxisTickLabel, getClosestPointsRange, getScaleTicks, getLabelsMaxWidth, } from '../../utils';
|
|
4
|
+
import { createYScale } from '../useAxisScales';
|
|
5
|
+
const getAxisLabelMaxWidth = (args) => {
|
|
6
|
+
const { axis, series } = args;
|
|
7
|
+
if (!axis.labels.enabled) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
const scale = createYScale(axis, series, 1);
|
|
11
|
+
const ticks = getScaleTicks(scale);
|
|
12
|
+
// FIXME: it is necessary to filter data, since we do not draw overlapping ticks
|
|
13
|
+
const step = getClosestPointsRange(axis, ticks);
|
|
14
|
+
const labels = ticks.map((tick) => formatAxisTickLabel({
|
|
15
|
+
axis,
|
|
16
|
+
value: tick,
|
|
17
|
+
step,
|
|
18
|
+
}));
|
|
19
|
+
return getLabelsMaxWidth({
|
|
20
|
+
labels,
|
|
21
|
+
style: axis.labels.style,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
const applyLabelsMaxWidth = (args) => {
|
|
25
|
+
const { series, preparedYAxis } = args;
|
|
26
|
+
preparedYAxis.labels.maxWidth = getAxisLabelMaxWidth({ axis: preparedYAxis, series });
|
|
27
|
+
};
|
|
28
|
+
export const getPreparedYAxis = ({ series, yAxis, }) => {
|
|
5
29
|
// FIXME: add support for n axises
|
|
6
30
|
const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
|
|
7
31
|
const y1LabelsStyle = {
|
|
@@ -15,7 +39,9 @@ export const getPreparedYAxis = ({ yAxis }) => {
|
|
|
15
39
|
type: get(yAxis1, 'type', 'linear'),
|
|
16
40
|
labels: {
|
|
17
41
|
enabled: get(yAxis1, 'labels.enabled', true),
|
|
18
|
-
|
|
42
|
+
margin: get(yAxis1, 'labels.margin', axisLabelsDefaults.margin),
|
|
43
|
+
padding: get(yAxis1, 'labels.padding', axisLabelsDefaults.padding),
|
|
44
|
+
autoRotation: get(yAxis1, 'labels.autoRotation', false),
|
|
19
45
|
dateFormat: get(yAxis1, 'labels.dateFormat'),
|
|
20
46
|
numberFormat: get(yAxis1, 'labels.numberFormat'),
|
|
21
47
|
style: y1LabelsStyle,
|
|
@@ -39,5 +65,6 @@ export const getPreparedYAxis = ({ yAxis }) => {
|
|
|
39
65
|
pixelInterval: get(yAxis1, 'ticks.pixelInterval'),
|
|
40
66
|
},
|
|
41
67
|
};
|
|
68
|
+
applyLabelsMaxWidth({ series, preparedYAxis: preparedY1Axis });
|
|
42
69
|
return [preparedY1Axis];
|
|
43
70
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const DEFAULT_LEGEND_SYMBOL_SIZE =
|
|
1
|
+
export declare const DEFAULT_LEGEND_SYMBOL_SIZE = 8;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DEFAULT_LEGEND_SYMBOL_SIZE =
|
|
1
|
+
export const DEFAULT_LEGEND_SYMBOL_SIZE = 8;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
|
-
import {
|
|
3
|
-
import { PreparedSeries } from './types';
|
|
4
|
-
export type OnLegendItemClick = (data: {
|
|
5
|
-
name: string;
|
|
6
|
-
metaKey: boolean;
|
|
7
|
-
}) => void;
|
|
2
|
+
import type { PreparedAxis, PreparedChart } from '../useChartOptions/types';
|
|
3
|
+
import type { PreparedSeries, OnLegendItemClick } from './types';
|
|
8
4
|
type Args = {
|
|
9
|
-
|
|
5
|
+
chartWidth: number;
|
|
6
|
+
chartHeight: number;
|
|
7
|
+
chartMargin: PreparedChart['margin'];
|
|
8
|
+
legend: ChartKitWidgetData['legend'];
|
|
10
9
|
series: ChartKitWidgetData['series'];
|
|
10
|
+
preparedYAxis: PreparedAxis[];
|
|
11
11
|
};
|
|
12
12
|
export declare const useSeries: (args: Args) => {
|
|
13
|
+
legendItems: import("./types").LegendItem[][];
|
|
14
|
+
legendConfig: {
|
|
15
|
+
offset: {
|
|
16
|
+
left: number;
|
|
17
|
+
top: number;
|
|
18
|
+
};
|
|
19
|
+
pagination: {
|
|
20
|
+
limit: number;
|
|
21
|
+
maxPage: number;
|
|
22
|
+
} | undefined;
|
|
23
|
+
};
|
|
24
|
+
preparedLegend: import("./types").PreparedLegend;
|
|
13
25
|
preparedSeries: PreparedSeries[];
|
|
14
26
|
handleLegendItemClick: OnLegendItemClick;
|
|
15
27
|
};
|