@gravity-ui/charts 1.20.0 → 1.21.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 +18 -7
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +8 -11
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +39 -104
- 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 +2 -2
- package/dist/cjs/components/ChartInner/utils.js +1 -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/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/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/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 +18 -7
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +7 -10
- package/dist/esm/components/ChartInner/useChartInnerProps.js +39 -104
- 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 +2 -2
- package/dist/esm/components/ChartInner/utils.js +1 -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/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/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/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,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.
|
|
@@ -105,7 +105,7 @@ export function getClosestPoints(args) {
|
|
|
105
105
|
case 'bar-y': {
|
|
106
106
|
const points = list;
|
|
107
107
|
const sorted = sort(points, (p) => p.y);
|
|
108
|
-
const closestYIndex = bisector((p) => p.y).center(sorted, pointerY);
|
|
108
|
+
const closestYIndex = bisector((p) => p.y + p.height / 2).center(sorted, pointerY);
|
|
109
109
|
const closestYPoint = sorted[closestYIndex];
|
|
110
110
|
let selectedPoints = [];
|
|
111
111
|
let closestPointXValue = -1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChartAxis, ChartSeries } from '../../../types';
|
|
2
|
-
export declare function getSortedSeriesData({ seriesData,
|
|
2
|
+
export declare function getSortedSeriesData({ seriesData, xAxis, yAxis, }: {
|
|
3
3
|
seriesData: ChartSeries[];
|
|
4
|
-
yAxes?: ChartAxis[];
|
|
5
4
|
xAxis?: ChartAxis;
|
|
5
|
+
yAxis?: ChartAxis[];
|
|
6
6
|
}): ChartSeries[];
|
|
@@ -20,11 +20,11 @@ function applyAxisCategoriesOrder({ series, axis, key, }) {
|
|
|
20
20
|
});
|
|
21
21
|
return Object.assign(Object.assign({}, series), { data: newSeriesData });
|
|
22
22
|
}
|
|
23
|
-
export function getSortedSeriesData({ seriesData,
|
|
23
|
+
export function getSortedSeriesData({ seriesData, xAxis, yAxis, }) {
|
|
24
24
|
return seriesData.map((s) => {
|
|
25
|
-
const
|
|
25
|
+
const yAxisItem = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
|
|
26
26
|
let sortedSeries = s;
|
|
27
|
-
sortedSeries = applyAxisCategoriesOrder({ series: sortedSeries, axis:
|
|
27
|
+
sortedSeries = applyAxisCategoriesOrder({ series: sortedSeries, axis: yAxisItem, key: 'y' });
|
|
28
28
|
sortedSeries = applyAxisCategoriesOrder({ series: sortedSeries, axis: xAxis, key: 'x' });
|
|
29
29
|
switch (sortedSeries.type) {
|
|
30
30
|
case SeriesType.Area: {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import type { PreparedAxis, PreparedSeries } from '../../hooks';
|
|
1
2
|
import type { ZoomState } from '../../hooks/useZoom/types';
|
|
2
|
-
import type {
|
|
3
|
+
import type { ChartXAxis, ChartYAxis } from '../../types';
|
|
3
4
|
export declare function getZoomedSeriesData(args: {
|
|
4
|
-
seriesData:
|
|
5
|
+
seriesData: PreparedSeries[];
|
|
5
6
|
zoomState: Partial<ZoomState>;
|
|
6
|
-
xAxis?: ChartXAxis;
|
|
7
|
-
|
|
7
|
+
xAxis?: ChartXAxis | PreparedAxis | null;
|
|
8
|
+
yAxis?: ChartYAxis[] | PreparedAxis[] | null;
|
|
8
9
|
}): {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
preparedSeries: PreparedSeries[];
|
|
11
|
+
preparedShapesSeries: PreparedSeries[];
|
|
11
12
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { SeriesType } from '../../constants';
|
|
2
|
-
import { getAxisCategories } from '../../hooks/useChartOptions/utils';
|
|
3
2
|
const SERIES_TYPE_WITH_HIDDEN_POINTS = [SeriesType.Area, SeriesType.Line];
|
|
4
3
|
// eslint-disable-next-line complexity
|
|
5
4
|
function isValueInRange(args) {
|
|
@@ -21,7 +20,7 @@ function isValueInRange(args) {
|
|
|
21
20
|
return numValue >= numMin && numValue <= numMax;
|
|
22
21
|
}
|
|
23
22
|
case 'category': {
|
|
24
|
-
const categories =
|
|
23
|
+
const categories = (axis === null || axis === void 0 ? void 0 : axis.categories) || [];
|
|
25
24
|
if (typeof value === 'string' && typeof min === 'number' && typeof max === 'number') {
|
|
26
25
|
const valueIndex = categories.indexOf(value);
|
|
27
26
|
if (min === -1 || max === -1 || valueIndex === -1) {
|
|
@@ -42,10 +41,13 @@ function isValueInRange(args) {
|
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
}
|
|
44
|
+
function isPreparedZoomableSeries(series) {
|
|
45
|
+
return Array.isArray(series.data);
|
|
46
|
+
}
|
|
45
47
|
export function getZoomedSeriesData(args) {
|
|
46
|
-
const { seriesData, xAxis,
|
|
48
|
+
const { seriesData, xAxis, yAxis, zoomState } = args;
|
|
47
49
|
if (Object.keys(zoomState).length <= 0) {
|
|
48
|
-
return {
|
|
50
|
+
return { preparedSeries: seriesData, preparedShapesSeries: seriesData };
|
|
49
51
|
}
|
|
50
52
|
const zoomedSeriesData = [];
|
|
51
53
|
const zoomedShapesSeriesData = [];
|
|
@@ -56,6 +58,9 @@ export function getZoomedSeriesData(args) {
|
|
|
56
58
|
const filteredShapesData = SERIES_TYPE_WITH_HIDDEN_POINTS.includes(seriesItem.type) && (xAxis === null || xAxis === void 0 ? void 0 : xAxis.type) !== 'category'
|
|
57
59
|
? []
|
|
58
60
|
: undefined;
|
|
61
|
+
if (!isPreparedZoomableSeries(seriesItem)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
59
64
|
seriesItem.data.forEach((point, i) => {
|
|
60
65
|
const prevPoint = seriesItem.data[i - 1];
|
|
61
66
|
const isFirstPoint = i === 0;
|
|
@@ -81,7 +86,7 @@ export function getZoomedSeriesData(args) {
|
|
|
81
86
|
const [yMin, yMax] = zoomStateY;
|
|
82
87
|
const y = 'y' in point ? point.y : undefined;
|
|
83
88
|
inYRange = isValueInRange({
|
|
84
|
-
axis:
|
|
89
|
+
axis: yAxis === null || yAxis === void 0 ? void 0 : yAxis[yAxisIndex],
|
|
85
90
|
value: y,
|
|
86
91
|
min: yMin,
|
|
87
92
|
max: yMax,
|
|
@@ -111,5 +116,8 @@ export function getZoomedSeriesData(args) {
|
|
|
111
116
|
zoomedSeriesData.push(Object.assign(Object.assign({}, seriesItem), { data: filteredData }));
|
|
112
117
|
zoomedShapesSeriesData.push(Object.assign(Object.assign({}, seriesItem), { data: filteredShapesData || filteredData }));
|
|
113
118
|
});
|
|
114
|
-
return {
|
|
119
|
+
return {
|
|
120
|
+
preparedSeries: zoomedSeriesData,
|
|
121
|
+
preparedShapesSeries: zoomedShapesSeriesData,
|
|
122
|
+
};
|
|
115
123
|
}
|
|
@@ -67,7 +67,14 @@ export const AxisY = (props) => {
|
|
|
67
67
|
}
|
|
68
68
|
if (tickData.svgLabel) {
|
|
69
69
|
const label = tickData.svgLabel;
|
|
70
|
-
const textSelection = tickSelection
|
|
70
|
+
const textSelection = tickSelection
|
|
71
|
+
.append('text')
|
|
72
|
+
.style('transform', [
|
|
73
|
+
`translate(${label.x}px, ${label.y}px)`,
|
|
74
|
+
label.angle ? `rotate(${label.angle}deg)` : '',
|
|
75
|
+
]
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.join(' '));
|
|
71
78
|
if (label.title) {
|
|
72
79
|
textSelection.append('title').html(label.title);
|
|
73
80
|
}
|