@gravity-ui/charts 1.20.0 → 1.22.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/dist/cjs/components/AxisY/AxisY.js +8 -1
- package/dist/cjs/components/AxisY/prepare-axis-data.js +39 -12
- package/dist/cjs/components/AxisY/types.d.ts +3 -0
- package/dist/cjs/components/ChartInner/index.js +23 -8
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +24 -13
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +41 -107
- package/dist/cjs/components/ChartInner/useChartInnerState.d.ts +4 -2
- package/dist/cjs/components/ChartInner/useChartInnerState.js +9 -0
- package/dist/cjs/components/ChartInner/utils.d.ts +12 -3
- package/dist/cjs/components/ChartInner/utils.js +61 -1
- package/dist/cjs/components/Title/index.d.ts +0 -1
- package/dist/cjs/components/Title/index.js +6 -4
- package/dist/cjs/hooks/index.d.ts +7 -3
- package/dist/cjs/hooks/index.js +7 -3
- package/dist/cjs/hooks/useAxis/index.d.ts +19 -0
- package/dist/cjs/hooks/useAxis/index.js +63 -0
- package/dist/cjs/hooks/useChartOptions/chart.js +6 -1
- package/dist/cjs/hooks/useChartOptions/index.d.ts +1 -4
- package/dist/cjs/hooks/useChartOptions/index.js +2 -5
- package/dist/cjs/hooks/useChartOptions/title.js +4 -2
- package/dist/cjs/hooks/useChartOptions/types.d.ts +0 -1
- package/dist/cjs/hooks/useChartOptions/utils.d.ts +1 -4
- package/dist/cjs/hooks/useChartOptions/utils.js +29 -6
- package/dist/cjs/hooks/useChartOptions/x-axis.js +2 -2
- package/dist/cjs/hooks/useChartOptions/y-axis.js +10 -11
- package/dist/cjs/hooks/useNormalizedOriginalData/index.d.ts +40 -0
- package/dist/cjs/hooks/useNormalizedOriginalData/index.js +33 -0
- package/dist/cjs/hooks/useSeries/index.d.ts +0 -9
- package/dist/cjs/hooks/useSeries/index.js +0 -18
- package/dist/cjs/hooks/useSeries/types.d.ts +3 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +4 -0
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +4 -0
- package/dist/cjs/hooks/useShapes/scatter/prepare-data.d.ts +2 -2
- package/dist/cjs/hooks/useShapes/scatter/prepare-data.js +40 -5
- package/dist/cjs/types/chart/axis.d.ts +20 -2
- package/dist/cjs/types/chart/zoom.d.ts +29 -0
- package/dist/cjs/utils/chart/get-closest-data.js +1 -1
- package/dist/cjs/utils/chart/series/sorting.d.ts +2 -2
- package/dist/cjs/utils/chart/series/sorting.js +3 -3
- package/dist/cjs/utils/chart/text.js +24 -21
- package/dist/cjs/utils/chart/zoom.d.ts +7 -6
- package/dist/cjs/utils/chart/zoom.js +14 -6
- package/dist/esm/components/AxisY/AxisY.js +8 -1
- package/dist/esm/components/AxisY/prepare-axis-data.js +39 -12
- package/dist/esm/components/AxisY/types.d.ts +3 -0
- package/dist/esm/components/ChartInner/index.js +23 -8
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +23 -12
- package/dist/esm/components/ChartInner/useChartInnerProps.js +41 -107
- package/dist/esm/components/ChartInner/useChartInnerState.d.ts +4 -2
- package/dist/esm/components/ChartInner/useChartInnerState.js +9 -0
- package/dist/esm/components/ChartInner/utils.d.ts +12 -3
- package/dist/esm/components/ChartInner/utils.js +61 -1
- package/dist/esm/components/Title/index.d.ts +0 -1
- package/dist/esm/components/Title/index.js +6 -4
- package/dist/esm/hooks/index.d.ts +7 -3
- package/dist/esm/hooks/index.js +7 -3
- package/dist/esm/hooks/useAxis/index.d.ts +19 -0
- package/dist/esm/hooks/useAxis/index.js +63 -0
- package/dist/esm/hooks/useChartOptions/chart.js +6 -1
- package/dist/esm/hooks/useChartOptions/index.d.ts +1 -4
- package/dist/esm/hooks/useChartOptions/index.js +2 -5
- package/dist/esm/hooks/useChartOptions/title.js +4 -2
- package/dist/esm/hooks/useChartOptions/types.d.ts +0 -1
- package/dist/esm/hooks/useChartOptions/utils.d.ts +1 -4
- package/dist/esm/hooks/useChartOptions/utils.js +29 -6
- package/dist/esm/hooks/useChartOptions/x-axis.js +2 -2
- package/dist/esm/hooks/useChartOptions/y-axis.js +10 -11
- package/dist/esm/hooks/useNormalizedOriginalData/index.d.ts +40 -0
- package/dist/esm/hooks/useNormalizedOriginalData/index.js +33 -0
- package/dist/esm/hooks/useSeries/index.d.ts +0 -9
- package/dist/esm/hooks/useSeries/index.js +0 -18
- package/dist/esm/hooks/useSeries/types.d.ts +3 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +4 -0
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +4 -0
- package/dist/esm/hooks/useShapes/scatter/prepare-data.d.ts +2 -2
- package/dist/esm/hooks/useShapes/scatter/prepare-data.js +40 -5
- package/dist/esm/types/chart/axis.d.ts +20 -2
- package/dist/esm/types/chart/zoom.d.ts +29 -0
- package/dist/esm/utils/chart/get-closest-data.js +1 -1
- package/dist/esm/utils/chart/series/sorting.d.ts +2 -2
- package/dist/esm/utils/chart/series/sorting.js +3 -3
- package/dist/esm/utils/chart/text.js +24 -21
- package/dist/esm/utils/chart/zoom.d.ts +7 -6
- package/dist/esm/utils/chart/zoom.js +14 -6
- package/package.json +7 -16
- package/dist/cjs/components/Title/styles.css +0 -5
- package/dist/esm/components/Title/styles.css +0 -5
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
export * from './useAxis';
|
|
2
|
+
export * from './useAxisScales';
|
|
1
3
|
export * from './useChartDimensions';
|
|
2
4
|
export * from './useChartOptions';
|
|
3
5
|
export * from './useChartOptions/types';
|
|
4
|
-
export * from './
|
|
6
|
+
export * from './useCrosshair';
|
|
7
|
+
export * from './useNormalizedOriginalData';
|
|
5
8
|
export * from './usePrevious';
|
|
6
9
|
export * from './useSeries';
|
|
7
10
|
export * from './useSeries/types';
|
|
8
11
|
export * from './useShapes';
|
|
9
|
-
export * from './useTooltip';
|
|
10
12
|
export * from './useSplit';
|
|
11
13
|
export * from './useSplit/types';
|
|
12
|
-
export * from './
|
|
14
|
+
export * from './useTooltip';
|
|
15
|
+
export * from './useZoom';
|
|
16
|
+
export * from './useZoom/types';
|
package/dist/cjs/hooks/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
export * from './useAxis';
|
|
2
|
+
export * from './useAxisScales';
|
|
1
3
|
export * from './useChartDimensions';
|
|
2
4
|
export * from './useChartOptions';
|
|
3
5
|
export * from './useChartOptions/types';
|
|
4
|
-
export * from './
|
|
6
|
+
export * from './useCrosshair';
|
|
7
|
+
export * from './useNormalizedOriginalData';
|
|
5
8
|
export * from './usePrevious';
|
|
6
9
|
export * from './useSeries';
|
|
7
10
|
export * from './useSeries/types';
|
|
8
11
|
export * from './useShapes';
|
|
9
|
-
export * from './useTooltip';
|
|
10
12
|
export * from './useSplit';
|
|
11
13
|
export * from './useSplit/types';
|
|
12
|
-
export * from './
|
|
14
|
+
export * from './useTooltip';
|
|
15
|
+
export * from './useZoom';
|
|
16
|
+
export * from './useZoom/types';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ChartXAxis, ChartYAxis } from '../../types';
|
|
2
|
+
import type { PreparedAxis, PreparedChart } from '../useChartOptions/types';
|
|
3
|
+
import type { PreparedLegend, PreparedSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
4
|
+
interface UseAxesProps {
|
|
5
|
+
height: number;
|
|
6
|
+
preparedChart: PreparedChart;
|
|
7
|
+
preparedLegend: PreparedLegend | null;
|
|
8
|
+
preparedSeries: PreparedSeries[];
|
|
9
|
+
preparedSeriesOptions: PreparedSeriesOptions;
|
|
10
|
+
width: number;
|
|
11
|
+
boundsHeight?: number;
|
|
12
|
+
xAxis?: ChartXAxis;
|
|
13
|
+
yAxis?: ChartYAxis[];
|
|
14
|
+
}
|
|
15
|
+
export declare function useAxis(props: UseAxesProps): {
|
|
16
|
+
xAxis: PreparedAxis | null;
|
|
17
|
+
yAxis: PreparedAxis[];
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
import { getPreparedXAxis } from '../useChartOptions/x-axis';
|
|
4
|
+
import { getPreparedYAxis } from '../useChartOptions/y-axis';
|
|
5
|
+
export function useAxis(props) {
|
|
6
|
+
const { boundsHeight, height, preparedChart, preparedLegend, preparedSeries, preparedSeriesOptions, width, xAxis, yAxis, } = props;
|
|
7
|
+
const [axesState, setValue] = React.useState({ xAxis: null, yAxis: [] });
|
|
8
|
+
const axesStateRunRef = React.useRef(0);
|
|
9
|
+
const prevAxesStateValue = React.useRef(axesState);
|
|
10
|
+
const axesStateReady = React.useRef(false);
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
axesStateRunRef.current++;
|
|
13
|
+
axesStateReady.current = false;
|
|
14
|
+
(async function () {
|
|
15
|
+
const currentRun = axesStateRunRef.current;
|
|
16
|
+
const seriesData = preparedSeries.filter((s) => s.visible);
|
|
17
|
+
const preparedXAxis = await getPreparedXAxis({
|
|
18
|
+
xAxis,
|
|
19
|
+
width,
|
|
20
|
+
seriesData,
|
|
21
|
+
seriesOptions: preparedSeriesOptions,
|
|
22
|
+
});
|
|
23
|
+
let estimatedBoundsHeight = boundsHeight !== null && boundsHeight !== void 0 ? boundsHeight : height;
|
|
24
|
+
if (preparedXAxis && typeof boundsHeight !== 'number') {
|
|
25
|
+
estimatedBoundsHeight =
|
|
26
|
+
height -
|
|
27
|
+
(preparedXAxis.title.height +
|
|
28
|
+
preparedXAxis.title.margin +
|
|
29
|
+
preparedXAxis.labels.margin +
|
|
30
|
+
preparedXAxis.labels.height +
|
|
31
|
+
(preparedLegend ? preparedLegend.height + preparedLegend.margin : 0) +
|
|
32
|
+
preparedChart.margin.top +
|
|
33
|
+
preparedChart.margin.bottom);
|
|
34
|
+
}
|
|
35
|
+
const preparedYAxis = await getPreparedYAxis({
|
|
36
|
+
height,
|
|
37
|
+
boundsHeight: estimatedBoundsHeight,
|
|
38
|
+
width,
|
|
39
|
+
seriesData,
|
|
40
|
+
yAxis,
|
|
41
|
+
});
|
|
42
|
+
const newStateValue = { xAxis: preparedXAxis, yAxis: preparedYAxis };
|
|
43
|
+
if (axesStateRunRef.current === currentRun) {
|
|
44
|
+
if (!isEqual(prevAxesStateValue.current, newStateValue)) {
|
|
45
|
+
setValue(newStateValue);
|
|
46
|
+
prevAxesStateValue.current = newStateValue;
|
|
47
|
+
}
|
|
48
|
+
axesStateReady.current = true;
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
}, [
|
|
52
|
+
boundsHeight,
|
|
53
|
+
height,
|
|
54
|
+
preparedChart.margin,
|
|
55
|
+
preparedLegend,
|
|
56
|
+
preparedSeries,
|
|
57
|
+
preparedSeriesOptions,
|
|
58
|
+
width,
|
|
59
|
+
xAxis,
|
|
60
|
+
yAxis,
|
|
61
|
+
]);
|
|
62
|
+
return axesStateReady.current ? axesState : { xAxis: null, yAxis: [] };
|
|
63
|
+
}
|
|
@@ -72,7 +72,7 @@ function getZoomType(args) {
|
|
|
72
72
|
return undefined;
|
|
73
73
|
}
|
|
74
74
|
function getPreparedZoom(args) {
|
|
75
|
-
var _a;
|
|
75
|
+
var _a, _b, _c, _d;
|
|
76
76
|
const { zoom, seriesData } = args;
|
|
77
77
|
if (!(zoom === null || zoom === void 0 ? void 0 : zoom.enabled)) {
|
|
78
78
|
return null;
|
|
@@ -86,6 +86,11 @@ function getPreparedZoom(args) {
|
|
|
86
86
|
brush: {
|
|
87
87
|
style: Object.assign({ fillOpacity: 1 }, (_a = zoom === null || zoom === void 0 ? void 0 : zoom.brush) === null || _a === void 0 ? void 0 : _a.style),
|
|
88
88
|
},
|
|
89
|
+
resetButton: {
|
|
90
|
+
align: ((_b = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _b === void 0 ? void 0 : _b.align) || 'top-right',
|
|
91
|
+
offset: Object.assign({ x: 0, y: 0 }, (_c = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _c === void 0 ? void 0 : _c.offset),
|
|
92
|
+
relativeTo: ((_d = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _d === void 0 ? void 0 : _d.relativeTo) || 'chart-box',
|
|
93
|
+
},
|
|
89
94
|
};
|
|
90
95
|
}
|
|
91
96
|
export const getPreparedChart = (args) => {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { ChartSeries, ChartTitle,
|
|
1
|
+
import type { ChartSeries, ChartTitle, ChartOptions as GeneralChartOptions } from '../../types';
|
|
2
2
|
import type { ChartOptions } from './types';
|
|
3
3
|
type Args = {
|
|
4
4
|
seriesData: ChartSeries[];
|
|
5
5
|
chart?: GeneralChartOptions;
|
|
6
6
|
colors?: string[];
|
|
7
7
|
title?: ChartTitle;
|
|
8
|
-
tooltip?: ChartTooltip;
|
|
9
|
-
yAxes?: ChartYAxis[];
|
|
10
|
-
xAxis?: ChartXAxis;
|
|
11
8
|
};
|
|
12
9
|
export declare const useChartOptions: (args: Args) => ChartOptions;
|
|
13
10
|
export {};
|
|
@@ -2,12 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import { DEFAULT_PALETTE } from '../../constants';
|
|
3
3
|
import { getPreparedChart } from './chart';
|
|
4
4
|
import { getPreparedTitle } from './title';
|
|
5
|
-
import { getPreparedTooltip } from './tooltip';
|
|
6
5
|
export const useChartOptions = (args) => {
|
|
7
|
-
const { chart, colors, seriesData, title
|
|
6
|
+
const { chart, colors, seriesData, title } = args;
|
|
8
7
|
const options = React.useMemo(() => {
|
|
9
8
|
const preparedTitle = getPreparedTitle({ title });
|
|
10
|
-
const preparedTooltip = getPreparedTooltip({ tooltip, seriesData, yAxes, xAxis });
|
|
11
9
|
const preparedChart = getPreparedChart({
|
|
12
10
|
chart,
|
|
13
11
|
preparedTitle,
|
|
@@ -17,8 +15,7 @@ export const useChartOptions = (args) => {
|
|
|
17
15
|
colors: colors !== null && colors !== void 0 ? colors : DEFAULT_PALETTE,
|
|
18
16
|
chart: preparedChart,
|
|
19
17
|
title: preparedTitle,
|
|
20
|
-
tooltip: preparedTooltip,
|
|
21
18
|
};
|
|
22
|
-
}, [chart, colors, seriesData, title
|
|
19
|
+
}, [chart, colors, seriesData, title]);
|
|
23
20
|
return options;
|
|
24
21
|
};
|
|
@@ -3,10 +3,12 @@ import { getHorizontalSvgTextHeight } from '../../utils';
|
|
|
3
3
|
const DEFAULT_TITLE_FONT_SIZE = '15px';
|
|
4
4
|
const TITLE_PADDINGS = 8 * 2;
|
|
5
5
|
export const getPreparedTitle = ({ title, }) => {
|
|
6
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6
7
|
const titleText = get(title, 'text');
|
|
7
8
|
const titleStyle = {
|
|
8
|
-
fontSize:
|
|
9
|
-
fontWeight:
|
|
9
|
+
fontSize: (_b = (_a = title === null || title === void 0 ? void 0 : title.style) === null || _a === void 0 ? void 0 : _a.fontSize) !== null && _b !== void 0 ? _b : DEFAULT_TITLE_FONT_SIZE,
|
|
10
|
+
fontWeight: (_d = (_c = title === null || title === void 0 ? void 0 : title.style) === null || _c === void 0 ? void 0 : _c.fontWeight) !== null && _d !== void 0 ? _d : 'var(--g-text-subheader-font-weight)',
|
|
11
|
+
fontColor: (_f = (_e = title === null || title === void 0 ? void 0 : title.style) === null || _e === void 0 ? void 0 : _e.fontColor) !== null && _f !== void 0 ? _f : 'var(--g-color-text-primary)',
|
|
10
12
|
};
|
|
11
13
|
const titleHeight = titleText
|
|
12
14
|
? getHorizontalSvgTextHeight({ text: titleText, style: titleStyle }) + TITLE_PADDINGS
|
|
@@ -8,7 +8,4 @@ export declare function prepareAxisPlotLabel(d: AxisPlot): {
|
|
|
8
8
|
};
|
|
9
9
|
padding: number;
|
|
10
10
|
};
|
|
11
|
-
export declare function getAxisCategories({ categories, order, }?:
|
|
12
|
-
categories?: string[];
|
|
13
|
-
order?: ChartAxis['order'];
|
|
14
|
-
}): string[] | undefined;
|
|
11
|
+
export declare function getAxisCategories({ categories: originalCategories, max, min, order, }?: Partial<ChartAxis>): string[] | undefined;
|
|
@@ -8,19 +8,42 @@ export function prepareAxisPlotLabel(d) {
|
|
|
8
8
|
padding: (_e = (_d = d.label) === null || _d === void 0 ? void 0 : _d.padding) !== null && _e !== void 0 ? _e : 5,
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
function getNormalizedIndexMinMax(args) {
|
|
12
|
+
const { max, min } = args;
|
|
13
|
+
if (typeof min === 'number' && typeof max === 'number') {
|
|
14
|
+
return min > max ? [max, min] : [min, max];
|
|
15
|
+
}
|
|
16
|
+
return [min, max];
|
|
17
|
+
}
|
|
18
|
+
function getNormalizedStartEnd(args) {
|
|
19
|
+
const { length, max, min } = args;
|
|
20
|
+
const [normalizedMin, normalizedMax] = getNormalizedIndexMinMax({ max, min });
|
|
21
|
+
const start = typeof normalizedMin === 'number' && normalizedMin >= 0 ? normalizedMin : 0;
|
|
22
|
+
const end = typeof normalizedMax === 'number' && normalizedMax <= length ? normalizedMax + 1 : length;
|
|
23
|
+
return [start, end];
|
|
24
|
+
}
|
|
25
|
+
export function getAxisCategories({ categories: originalCategories, max, min, order, } = {}) {
|
|
26
|
+
if (originalCategories) {
|
|
27
|
+
let categories = originalCategories;
|
|
13
28
|
switch (order) {
|
|
14
29
|
case 'reverse': {
|
|
15
|
-
|
|
30
|
+
categories = reverse(originalCategories);
|
|
31
|
+
break;
|
|
16
32
|
}
|
|
17
33
|
case 'sortAsc': {
|
|
18
|
-
|
|
34
|
+
categories = sort(originalCategories, (a, b) => ascending(a, b));
|
|
35
|
+
break;
|
|
19
36
|
}
|
|
20
37
|
case 'sortDesc': {
|
|
21
|
-
|
|
38
|
+
categories = sort(originalCategories, (a, b) => descending(a, b));
|
|
39
|
+
break;
|
|
22
40
|
}
|
|
23
41
|
}
|
|
42
|
+
if (typeof min === 'number' || typeof max === 'number') {
|
|
43
|
+
const [start, end] = getNormalizedStartEnd({ length: categories.length, max, min });
|
|
44
|
+
categories = categories.slice(start, end);
|
|
45
|
+
}
|
|
46
|
+
return categories;
|
|
24
47
|
}
|
|
25
|
-
return
|
|
48
|
+
return originalCategories;
|
|
26
49
|
}
|
|
@@ -2,7 +2,7 @@ import get from 'lodash/get';
|
|
|
2
2
|
import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, SeriesType, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
|
|
3
3
|
import { calculateCos, calculateNumericProperty, formatAxisTickLabel, getAxisItems, getClosestPointsRange, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, hasOverlappingLabels, isAxisRelatedSeries, wrapText, } from '../../utils';
|
|
4
4
|
import { createXScale } from '../useAxisScales';
|
|
5
|
-
import {
|
|
5
|
+
import { prepareAxisPlotLabel } from './utils';
|
|
6
6
|
async function setLabelSettings({ axis, seriesData, seriesOptions, width, autoRotation = true, }) {
|
|
7
7
|
const scale = createXScale({ axis, series: seriesData, seriesOptions, boundsWidth: width });
|
|
8
8
|
if (!scale) {
|
|
@@ -98,7 +98,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, seriesOptions, width
|
|
|
98
98
|
html: labelsHtml,
|
|
99
99
|
},
|
|
100
100
|
lineColor: get(xAxis, 'lineColor'),
|
|
101
|
-
categories:
|
|
101
|
+
categories: xAxis === null || xAxis === void 0 ? void 0 : xAxis.categories,
|
|
102
102
|
timestamps: get(xAxis, 'timestamps'),
|
|
103
103
|
title: {
|
|
104
104
|
text: titleText,
|
|
@@ -3,7 +3,7 @@ import { getTickValues } from '../../components/AxisY/utils';
|
|
|
3
3
|
import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, SeriesType, axisCrosshairDefaults, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
|
|
4
4
|
import { calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getDefaultMinYAxisValue, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../../utils';
|
|
5
5
|
import { createYScale } from '../useAxisScales';
|
|
6
|
-
import {
|
|
6
|
+
import { prepareAxisPlotLabel } from './utils';
|
|
7
7
|
const getAxisLabelMaxWidth = async (args) => {
|
|
8
8
|
const { axis, seriesData, height } = args;
|
|
9
9
|
if (!axis.labels.enabled) {
|
|
@@ -50,7 +50,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
50
50
|
if (!hasAxisRelatedSeries) {
|
|
51
51
|
return Promise.resolve([]);
|
|
52
52
|
}
|
|
53
|
-
return Promise.all(axisItems.map(async (axisItem) => {
|
|
53
|
+
return Promise.all(axisItems.map(async (axisItem, axisIndex) => {
|
|
54
54
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
55
55
|
const plotIndex = get(axisItem, 'plotIndex', 0);
|
|
56
56
|
const firstPlotAxis = !axisByPlot[plotIndex];
|
|
@@ -59,6 +59,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
59
59
|
}
|
|
60
60
|
axisByPlot[plotIndex].push(axisItem);
|
|
61
61
|
const defaultAxisPosition = firstPlotAxis ? 'left' : 'right';
|
|
62
|
+
const axisSeriesData = seriesData.filter((s) => get(s, 'yAxis', 0) === axisIndex);
|
|
62
63
|
const labelsEnabled = get(axisItem, 'labels.enabled', true);
|
|
63
64
|
const labelsStyle = {
|
|
64
65
|
fontSize: get(axisItem, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE),
|
|
@@ -77,7 +78,8 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
77
78
|
})).slice(0, titleMaxRowsCount);
|
|
78
79
|
const titleSize = await getLabelsSize({ labels: [titleText], style: titleStyle });
|
|
79
80
|
const axisType = get(axisItem, 'type', DEFAULT_AXIS_TYPE);
|
|
80
|
-
const shouldHideGrid = axisItem.visible === false ||
|
|
81
|
+
const shouldHideGrid = axisItem.visible === false ||
|
|
82
|
+
axisSeriesData.some((s) => s.type === SeriesType.Heatmap);
|
|
81
83
|
const preparedAxis = {
|
|
82
84
|
type: axisType,
|
|
83
85
|
labels: {
|
|
@@ -97,7 +99,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
97
99
|
html: labelsHtml,
|
|
98
100
|
},
|
|
99
101
|
lineColor: get(axisItem, 'lineColor'),
|
|
100
|
-
categories:
|
|
102
|
+
categories: axisItem.categories,
|
|
101
103
|
timestamps: get(axisItem, 'timestamps'),
|
|
102
104
|
title: {
|
|
103
105
|
text: titleText,
|
|
@@ -108,9 +110,9 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
108
110
|
align: get(axisItem, 'title.align', yAxisTitleDefaults.align),
|
|
109
111
|
maxRowCount: titleMaxRowsCount,
|
|
110
112
|
},
|
|
111
|
-
min: (_c = get(axisItem, 'min')) !== null && _c !== void 0 ? _c : getDefaultMinYAxisValue(
|
|
113
|
+
min: (_c = get(axisItem, 'min')) !== null && _c !== void 0 ? _c : getDefaultMinYAxisValue(axisSeriesData),
|
|
112
114
|
max: get(axisItem, 'max'),
|
|
113
|
-
maxPadding: get(axisItem, 'maxPadding', getMaxPaddingBySeries({ series:
|
|
115
|
+
maxPadding: get(axisItem, 'maxPadding', getMaxPaddingBySeries({ series: axisSeriesData })),
|
|
114
116
|
grid: {
|
|
115
117
|
enabled: shouldHideGrid
|
|
116
118
|
? false
|
|
@@ -159,14 +161,11 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
|
|
|
159
161
|
if (labelsEnabled) {
|
|
160
162
|
const { height: labelsHeight, width: labelsWidth } = await getAxisLabelMaxWidth({
|
|
161
163
|
axis: preparedAxis,
|
|
162
|
-
seriesData,
|
|
164
|
+
seriesData: axisSeriesData,
|
|
163
165
|
height: boundsHeight,
|
|
164
166
|
});
|
|
165
167
|
preparedAxis.labels.height = labelsHeight;
|
|
166
|
-
preparedAxis.labels.width =
|
|
167
|
-
labelsWidth > preparedAxis.labels.maxWidth
|
|
168
|
-
? preparedAxis.labels.maxWidth
|
|
169
|
-
: labelsWidth;
|
|
168
|
+
preparedAxis.labels.width = Math.min(preparedAxis.labels.maxWidth, labelsWidth);
|
|
170
169
|
}
|
|
171
170
|
return preparedAxis;
|
|
172
171
|
}));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ChartData } from '../../types';
|
|
2
|
+
interface UseOriginalDataProps {
|
|
3
|
+
seriesData: ChartData['series']['data'];
|
|
4
|
+
xAxis: ChartData['xAxis'];
|
|
5
|
+
yAxis: ChartData['yAxis'];
|
|
6
|
+
}
|
|
7
|
+
export declare function useNormalizedOriginalData(props: UseOriginalDataProps): {
|
|
8
|
+
normalizedSeriesData: import("../../types").ChartSeries[];
|
|
9
|
+
normalizedXAxis: {
|
|
10
|
+
categories: string[] | undefined;
|
|
11
|
+
crosshair?: import("../../types").AxisCrosshair;
|
|
12
|
+
timestamps?: number[];
|
|
13
|
+
type?: import("../../types").ChartAxisType;
|
|
14
|
+
labels?: import("../../types").ChartAxisLabels;
|
|
15
|
+
lineColor?: string;
|
|
16
|
+
title?: {
|
|
17
|
+
text?: string;
|
|
18
|
+
style?: Partial<import("../../types").BaseTextStyle>;
|
|
19
|
+
margin?: number;
|
|
20
|
+
align?: import("../../types").ChartAxisTitleAlignment;
|
|
21
|
+
maxRowCount?: number;
|
|
22
|
+
};
|
|
23
|
+
min?: number;
|
|
24
|
+
max?: number;
|
|
25
|
+
grid?: {
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
};
|
|
28
|
+
ticks?: {
|
|
29
|
+
pixelInterval?: number;
|
|
30
|
+
interval?: number | string;
|
|
31
|
+
};
|
|
32
|
+
maxPadding?: number;
|
|
33
|
+
plotLines?: import("../../types").AxisPlotLine[];
|
|
34
|
+
plotBands?: import("../../types").AxisPlotBand[];
|
|
35
|
+
visible?: boolean;
|
|
36
|
+
order?: "sortAsc" | "sortDesc" | "reverse";
|
|
37
|
+
};
|
|
38
|
+
normalizedYAxis: import("../../types").ChartYAxis[] | undefined;
|
|
39
|
+
};
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getSortedSeriesData } from '../../utils';
|
|
3
|
+
import { getAxisCategories } from '../useChartOptions/utils';
|
|
4
|
+
export function useNormalizedOriginalData(props) {
|
|
5
|
+
const normalizedSeriesData = React.useMemo(() => {
|
|
6
|
+
return getSortedSeriesData({
|
|
7
|
+
seriesData: props.seriesData,
|
|
8
|
+
xAxis: props.xAxis,
|
|
9
|
+
yAxis: props.yAxis,
|
|
10
|
+
});
|
|
11
|
+
}, [props.seriesData, props.xAxis, props.yAxis]);
|
|
12
|
+
const normalizedXAxis = React.useMemo(() => {
|
|
13
|
+
var _a;
|
|
14
|
+
let categories = (_a = props.xAxis) === null || _a === void 0 ? void 0 : _a.categories;
|
|
15
|
+
if (props.xAxis && props.xAxis.categories) {
|
|
16
|
+
categories = getAxisCategories(props.xAxis);
|
|
17
|
+
}
|
|
18
|
+
return Object.assign(Object.assign({}, props.xAxis), { categories });
|
|
19
|
+
}, [props.xAxis]);
|
|
20
|
+
const normalizedYAxis = React.useMemo(() => {
|
|
21
|
+
if (Array.isArray(props.yAxis) && props.yAxis.some((axis) => axis.categories)) {
|
|
22
|
+
return props.yAxis.map((axis) => {
|
|
23
|
+
let categories = axis.categories;
|
|
24
|
+
if (axis.categories) {
|
|
25
|
+
categories = getAxisCategories(axis);
|
|
26
|
+
}
|
|
27
|
+
return Object.assign(Object.assign({}, axis), { categories });
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return props.yAxis;
|
|
31
|
+
}, [props.yAxis]);
|
|
32
|
+
return { normalizedSeriesData, normalizedXAxis, normalizedYAxis };
|
|
33
|
+
}
|
|
@@ -13,13 +13,4 @@ export declare const useSeries: (args: Args) => {
|
|
|
13
13
|
preparedSeries: PreparedSeries[];
|
|
14
14
|
handleLegendItemClick: OnLegendItemClick;
|
|
15
15
|
};
|
|
16
|
-
export declare const useShapeSeries: ({ seriesData, seriesOptions, colors, preparedLegend, activeLegendItems, }: {
|
|
17
|
-
colors: string[];
|
|
18
|
-
seriesData: ChartData["series"]["data"];
|
|
19
|
-
seriesOptions: ChartData["series"]["options"];
|
|
20
|
-
activeLegendItems: string[];
|
|
21
|
-
preparedLegend?: PreparedLegend | null;
|
|
22
|
-
}) => {
|
|
23
|
-
preparedSeries: PreparedSeries[];
|
|
24
|
-
};
|
|
25
16
|
export {};
|
|
@@ -93,21 +93,3 @@ export const useSeries = (args) => {
|
|
|
93
93
|
handleLegendItemClick,
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
|
-
export const useShapeSeries = ({ seriesData, seriesOptions, colors, preparedLegend, activeLegendItems, }) => {
|
|
97
|
-
const [preparedSeries, setPreparedSeries] = React.useState([]);
|
|
98
|
-
React.useEffect(() => {
|
|
99
|
-
(async () => {
|
|
100
|
-
const items = await getPreparedSeries({
|
|
101
|
-
seriesData,
|
|
102
|
-
seriesOptions,
|
|
103
|
-
preparedLegend,
|
|
104
|
-
colors,
|
|
105
|
-
});
|
|
106
|
-
setPreparedSeries(items);
|
|
107
|
-
})();
|
|
108
|
-
}, [seriesData, seriesOptions, preparedLegend, colors]);
|
|
109
|
-
const chartSeries = useVisibleSeries({ preparedSeries, activeLegendItems });
|
|
110
|
-
return {
|
|
111
|
-
preparedSeries: chartSeries,
|
|
112
|
-
};
|
|
113
|
-
};
|
|
@@ -326,6 +326,9 @@ export type PreparedRadarSeries = {
|
|
|
326
326
|
};
|
|
327
327
|
} & BasePreparedSeries;
|
|
328
328
|
export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedBarYSeries | PreparedPieSeries | PreparedLineSeries | PreparedAreaSeries | PreparedTreemapSeries | PreparedWaterfallSeries | PreparedSankeySeries | PreparedRadarSeries | PreparedHeatmapSeries;
|
|
329
|
+
export type PreparedZoomableSeries = Extract<PreparedSeries, {
|
|
330
|
+
data: Array<unknown>;
|
|
331
|
+
}>;
|
|
329
332
|
export type PreparedSeriesOptions = SeriesOptionsDefaults;
|
|
330
333
|
export type StackedSeries = BarXSeries | AreaSeries | BarYSeries;
|
|
331
334
|
export {};
|
|
@@ -118,6 +118,10 @@ export const prepareBarXData = async (args) => {
|
|
|
118
118
|
let xCenter;
|
|
119
119
|
if (xAxis.type === 'category') {
|
|
120
120
|
const xBandScale = xScale;
|
|
121
|
+
const xBandScaleDomain = xBandScale.domain();
|
|
122
|
+
if (xBandScaleDomain.indexOf(xValue) === -1) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
121
125
|
xCenter = (xBandScale(xValue) || 0) + xBandScale.bandwidth() / 2;
|
|
122
126
|
}
|
|
123
127
|
else {
|
|
@@ -67,6 +67,10 @@ export async function prepareBarYData(args) {
|
|
|
67
67
|
let center;
|
|
68
68
|
if (yAxis[0].type === 'category') {
|
|
69
69
|
const bandScale = yScale;
|
|
70
|
+
const bandScaleDomain = bandScale.domain();
|
|
71
|
+
if (bandScaleDomain.indexOf(yValue) === -1) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
70
74
|
center = (bandScale(yValue) || 0) + bandSize / 2;
|
|
71
75
|
}
|
|
72
76
|
else {
|
|
@@ -2,11 +2,11 @@ import type { ChartScale } from '../../useAxisScales';
|
|
|
2
2
|
import type { PreparedAxis } from '../../useChartOptions/types';
|
|
3
3
|
import type { PreparedScatterSeries } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedScatterData } from './types';
|
|
5
|
-
export declare
|
|
5
|
+
export declare function prepareScatterData(args: {
|
|
6
6
|
series: PreparedScatterSeries[];
|
|
7
7
|
xAxis: PreparedAxis;
|
|
8
8
|
xScale: ChartScale;
|
|
9
9
|
yAxis: PreparedAxis[];
|
|
10
10
|
yScale: (ChartScale | undefined)[];
|
|
11
11
|
isOutsideBounds: (x: number, y: number) => boolean;
|
|
12
|
-
})
|
|
12
|
+
}): PreparedScatterData[];
|
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
+
import { getDataCategoryValue } from '../../../utils';
|
|
2
3
|
import { getXValue, getYValue } from '../utils';
|
|
3
|
-
|
|
4
|
+
function getFilteredLinearScatterData(data) {
|
|
4
5
|
return data.filter((d) => typeof d.x === 'number' && typeof d.y === 'number');
|
|
5
|
-
}
|
|
6
|
-
|
|
6
|
+
}
|
|
7
|
+
function getFilteredCategoryScatterData(args) {
|
|
8
|
+
const { data, xAxis, xScale, yAxis, yScale } = args;
|
|
9
|
+
const xDomain = xScale.domain();
|
|
10
|
+
const xCategories = get(xAxis, 'categories', []);
|
|
11
|
+
const yDomain = yScale.domain();
|
|
12
|
+
const yCategories = get(yAxis, 'categories', []);
|
|
13
|
+
return data.filter((d) => {
|
|
14
|
+
let xInRange = true;
|
|
15
|
+
let yInRange = true;
|
|
16
|
+
if (xAxis.type === 'category') {
|
|
17
|
+
const dataCategory = getDataCategoryValue({
|
|
18
|
+
axisDirection: 'x',
|
|
19
|
+
categories: xCategories,
|
|
20
|
+
data: d,
|
|
21
|
+
});
|
|
22
|
+
xInRange = xDomain.indexOf(dataCategory) !== -1;
|
|
23
|
+
}
|
|
24
|
+
if (yAxis.type === 'category') {
|
|
25
|
+
const dataCategory = getDataCategoryValue({
|
|
26
|
+
axisDirection: 'y',
|
|
27
|
+
categories: yCategories,
|
|
28
|
+
data: d,
|
|
29
|
+
});
|
|
30
|
+
yInRange = yDomain.indexOf(dataCategory) !== -1;
|
|
31
|
+
}
|
|
32
|
+
return xInRange && yInRange;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export function prepareScatterData(args) {
|
|
7
36
|
const { series, xAxis, xScale, yAxis, yScale, isOutsideBounds } = args;
|
|
8
37
|
return series.reduce((acc, s) => {
|
|
9
38
|
const yAxisIndex = get(s, 'yAxis', 0);
|
|
@@ -13,7 +42,13 @@ export const prepareScatterData = (args) => {
|
|
|
13
42
|
return acc;
|
|
14
43
|
}
|
|
15
44
|
const filteredData = xAxis.type === 'category' || seriesYAxis.type === 'category'
|
|
16
|
-
?
|
|
45
|
+
? getFilteredCategoryScatterData({
|
|
46
|
+
data: s.data,
|
|
47
|
+
xAxis,
|
|
48
|
+
xScale,
|
|
49
|
+
yAxis: seriesYAxis,
|
|
50
|
+
yScale: seriesYScale,
|
|
51
|
+
})
|
|
17
52
|
: getFilteredLinearScatterData(s.data);
|
|
18
53
|
filteredData.forEach((d) => {
|
|
19
54
|
var _a;
|
|
@@ -39,4 +74,4 @@ export const prepareScatterData = (args) => {
|
|
|
39
74
|
});
|
|
40
75
|
return acc;
|
|
41
76
|
}, []);
|
|
42
|
-
}
|
|
77
|
+
}
|
|
@@ -65,9 +65,27 @@ export interface ChartAxis {
|
|
|
65
65
|
*/
|
|
66
66
|
maxRowCount?: number;
|
|
67
67
|
};
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* The minimum value of the axis. If undefined the min value is automatically calculated.
|
|
70
|
+
*
|
|
71
|
+
* The value type depends on the axis scale:
|
|
72
|
+
* - For `linear` and `logarithmic` axes: numeric value
|
|
73
|
+
* - For `datetime` axes: timestamp (milliseconds since Unix epoch)
|
|
74
|
+
* - For `category` axes: index of the element in the categories array (which has been processed according to the specified `order` property)
|
|
75
|
+
*
|
|
76
|
+
* Note: min/max is not supported for category axes in waterfall and heatmap visualizations.
|
|
77
|
+
*/
|
|
69
78
|
min?: number;
|
|
70
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* The maximum value of the axis. If undefined the max value is automatically calculated.
|
|
81
|
+
*
|
|
82
|
+
* The value type depends on the axis scale:
|
|
83
|
+
* - For `linear` and `logarithmic` axes: numeric value
|
|
84
|
+
* - For `datetime` axes: timestamp (milliseconds since Unix epoch)
|
|
85
|
+
* - For `category` axes: index of the element in the categories array (which has been processed according to the specified `order` property)
|
|
86
|
+
*
|
|
87
|
+
* Note: min/max is not supported for category axes in waterfall and heatmap visualizations.
|
|
88
|
+
*/
|
|
71
89
|
max?: number;
|
|
72
90
|
/** The grid lines settings.
|
|
73
91
|
* Unavailable for some visualizations, such as a heatmap.
|
|
@@ -33,4 +33,33 @@ export interface ChartZoom {
|
|
|
33
33
|
fillOpacity?: number;
|
|
34
34
|
};
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Reset zoom button configuration.
|
|
38
|
+
* The button appears only after the zoom has been applied.
|
|
39
|
+
*/
|
|
40
|
+
resetButton?: {
|
|
41
|
+
/**
|
|
42
|
+
* The alignment of the button.
|
|
43
|
+
*
|
|
44
|
+
* @default 'top-right'
|
|
45
|
+
*/
|
|
46
|
+
align?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
47
|
+
/**
|
|
48
|
+
* The offset of the button.
|
|
49
|
+
*
|
|
50
|
+
* @default {x: 0, y: 0}
|
|
51
|
+
*/
|
|
52
|
+
offset?: {
|
|
53
|
+
x?: number;
|
|
54
|
+
y?: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* The box to which the button is positioned relative to.
|
|
58
|
+
* - `chart-box` refers to the entire chart area, including titles and legends.
|
|
59
|
+
* - `plot-box` refers to the area where the series are drawn.
|
|
60
|
+
*
|
|
61
|
+
* @default 'chart-box'
|
|
62
|
+
*/
|
|
63
|
+
relativeTo?: 'chart-box' | 'plot-box';
|
|
64
|
+
};
|
|
36
65
|
}
|