@gravity-ui/chartkit 4.5.0 → 4.6.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/plugins/d3/renderer/D3Widget.js +11 -1
- package/build/plugins/d3/renderer/components/AxisX.d.ts +1 -2
- package/build/plugins/d3/renderer/components/AxisX.js +39 -61
- 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 -62
- 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 +9 -68
- 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/hooks/useShapes/bar-x.js +2 -1
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +21 -0
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +104 -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 +43 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +7 -4
- package/build/plugins/d3/renderer/utils/index.js +16 -6
- package/build/plugins/d3/renderer/utils/text.d.ts +20 -2
- package/build/plugins/d3/renderer/utils/text.js +51 -1
- 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 +1 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.d.ts +0 -6
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +0 -12
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './defaults';
|
|
1
2
|
export const DEFAULT_PALETTE = [
|
|
2
3
|
'#4DA2F1',
|
|
3
4
|
'#FF3D64',
|
|
@@ -21,5 +22,4 @@ export const DEFAULT_PALETTE = [
|
|
|
21
22
|
'#DCA3D7',
|
|
22
23
|
];
|
|
23
24
|
export const DEFAULT_AXIS_LABEL_FONT_SIZE = '11px';
|
|
24
|
-
export const DEFAULT_AXIS_LABEL_PADDING = 10;
|
|
25
25
|
export const DEFAULT_AXIS_TITLE_FONT_SIZE = '14px';
|
|
@@ -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,108 +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
|
-
const xAxisMinPadding = boundsWidth * xAxis.maxPadding;
|
|
37
|
-
const xRange = [0, boundsWidth - xAxisMinPadding];
|
|
38
|
-
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) {
|
|
39
26
|
case 'linear': {
|
|
40
|
-
const domain =
|
|
27
|
+
const domain = getDomainDataYBySeries(series);
|
|
28
|
+
const range = [boundsHeight, boundsHeight * axis.maxPadding];
|
|
41
29
|
if (isNumericalArrayData(domain)) {
|
|
42
|
-
const [
|
|
43
|
-
const
|
|
44
|
-
|
|
30
|
+
const [domainYMin, yMax] = extent(domain);
|
|
31
|
+
const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
|
|
32
|
+
return scaleLinear().domain([yMinValue, yMax]).range(range).nice();
|
|
45
33
|
}
|
|
46
34
|
break;
|
|
47
35
|
}
|
|
48
36
|
case 'category': {
|
|
49
|
-
if (
|
|
37
|
+
if (yCategories) {
|
|
50
38
|
const filteredCategories = filterCategoriesByVisibleSeries({
|
|
51
|
-
axisDirection: '
|
|
52
|
-
categories:
|
|
53
|
-
series:
|
|
39
|
+
axisDirection: 'y',
|
|
40
|
+
categories: yCategories,
|
|
41
|
+
series: series,
|
|
54
42
|
});
|
|
55
|
-
|
|
56
|
-
if (xScale.step() / 2 < xAxisMinPadding) {
|
|
57
|
-
xScale.range(xRange);
|
|
58
|
-
}
|
|
43
|
+
return scaleBand().domain(filteredCategories).range([boundsHeight, 0]);
|
|
59
44
|
}
|
|
60
45
|
break;
|
|
61
46
|
}
|
|
62
47
|
case 'datetime': {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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();
|
|
66
52
|
}
|
|
67
53
|
else {
|
|
68
|
-
const domain =
|
|
54
|
+
const domain = getDomainDataYBySeries(series);
|
|
69
55
|
if (isNumericalArrayData(domain)) {
|
|
70
|
-
const [
|
|
71
|
-
|
|
56
|
+
const [yMin, yMax] = extent(domain);
|
|
57
|
+
return scaleUtc().domain([yMin, yMax]).range(range).nice();
|
|
72
58
|
}
|
|
73
59
|
}
|
|
74
60
|
break;
|
|
75
61
|
}
|
|
76
62
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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) {
|
|
81
73
|
case 'linear': {
|
|
82
|
-
const domain =
|
|
83
|
-
const range = [boundsHeight, boundsHeight * yAxis[0].maxPadding];
|
|
74
|
+
const domain = getDomainDataXBySeries(series);
|
|
84
75
|
if (isNumericalArrayData(domain)) {
|
|
85
|
-
const [
|
|
86
|
-
const
|
|
87
|
-
|
|
76
|
+
const [domainXMin, xMax] = extent(domain);
|
|
77
|
+
const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
|
|
78
|
+
return scaleLinear().domain([xMinValue, xMax]).range(xRange).nice();
|
|
88
79
|
}
|
|
89
80
|
break;
|
|
90
81
|
}
|
|
91
82
|
case 'category': {
|
|
92
|
-
if (
|
|
83
|
+
if (xCategories) {
|
|
93
84
|
const filteredCategories = filterCategoriesByVisibleSeries({
|
|
94
|
-
axisDirection: '
|
|
95
|
-
categories:
|
|
96
|
-
series:
|
|
85
|
+
axisDirection: 'x',
|
|
86
|
+
categories: xCategories,
|
|
87
|
+
series: series,
|
|
97
88
|
});
|
|
98
|
-
|
|
89
|
+
const xScale = scaleBand().domain(filteredCategories).range([0, boundsWidth]);
|
|
90
|
+
if (xScale.step() / 2 < xAxisMinPadding) {
|
|
91
|
+
xScale.range(xRange);
|
|
92
|
+
}
|
|
93
|
+
return xScale;
|
|
99
94
|
}
|
|
100
95
|
break;
|
|
101
96
|
}
|
|
102
97
|
case 'datetime': {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
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();
|
|
107
101
|
}
|
|
108
102
|
else {
|
|
109
|
-
const domain =
|
|
103
|
+
const domain = getDomainDataXBySeries(series);
|
|
110
104
|
if (isNumericalArrayData(domain)) {
|
|
111
|
-
const [
|
|
112
|
-
|
|
105
|
+
const [xMin, xMax] = extent(domain);
|
|
106
|
+
return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
|
|
113
107
|
}
|
|
114
108
|
}
|
|
115
109
|
break;
|
|
116
110
|
}
|
|
117
111
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
+
};
|
|
122
124
|
};
|
|
123
125
|
/**
|
|
124
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,27 +13,14 @@ 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;
|
|
@@ -84,16 +30,11 @@ const getMarginRight = (args) => {
|
|
|
84
30
|
return get(chart, 'margin.right', 0);
|
|
85
31
|
};
|
|
86
32
|
export const getPreparedChart = (args) => {
|
|
87
|
-
const { chart, series,
|
|
33
|
+
const { chart, series, preparedY1Axis, preparedTitle } = args;
|
|
88
34
|
const hasAxisRelatedSeries = series.data.some(isAxisRelatedSeries);
|
|
89
35
|
const marginTop = getMarginTop({ chart, hasAxisRelatedSeries, preparedY1Axis, preparedTitle });
|
|
90
|
-
const marginBottom =
|
|
91
|
-
|
|
92
|
-
hasAxisRelatedSeries,
|
|
93
|
-
preparedLegend,
|
|
94
|
-
preparedXAxis,
|
|
95
|
-
});
|
|
96
|
-
const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, series, preparedY1Axis });
|
|
36
|
+
const marginBottom = get(chart, 'margin.bottom', 0);
|
|
37
|
+
const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, preparedY1Axis });
|
|
97
38
|
const marginRight = getMarginRight({ chart });
|
|
98
39
|
return {
|
|
99
40
|
margin: {
|
|
@@ -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
|
};
|