@gravity-ui/charts 1.11.3 → 1.12.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/ChartInner/index.js +1 -1
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +19 -12
- package/dist/cjs/components/Legend/index.d.ts +0 -1
- package/dist/cjs/components/Legend/index.js +13 -23
- package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +1 -0
- package/dist/cjs/components/Tooltip/ChartTooltipContent.js +3 -3
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.d.ts +9 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/Row.js +10 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/RowTotals.d.ts +9 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/RowTotals.js +23 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.d.ts +11 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +102 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +30 -0
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +126 -0
- package/dist/cjs/components/Tooltip/index.js +1 -1
- package/dist/cjs/components/Tooltip/styles.css +14 -2
- package/dist/cjs/components/Tooltip/utils.d.ts +30 -0
- package/dist/cjs/components/Tooltip/utils.js +126 -0
- package/dist/cjs/constants/axis.d.ts +6 -0
- package/dist/cjs/constants/axis.js +6 -0
- package/dist/cjs/constants/index.d.ts +6 -4
- package/dist/cjs/constants/index.js +6 -4
- package/dist/cjs/constants/tooltip.d.ts +3 -0
- package/dist/cjs/constants/tooltip.js +3 -0
- package/dist/cjs/hooks/useAxisScales/index.d.ts +14 -3
- package/dist/cjs/hooks/useAxisScales/index.js +73 -22
- package/dist/cjs/hooks/useChartOptions/x-axis.js +1 -1
- package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +4 -2
- package/dist/cjs/hooks/useChartOptions/y-axis.js +9 -3
- package/dist/cjs/hooks/useSeries/index.d.ts +9 -0
- package/dist/cjs/hooks/useSeries/index.js +59 -29
- package/dist/cjs/hooks/useSeries/prepare-legend.d.ts +2 -2
- package/dist/cjs/hooks/useSeries/prepare-legend.js +4 -6
- package/dist/cjs/hooks/useSeries/types.d.ts +1 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +1 -1
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +17 -62
- package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +1 -1
- package/dist/cjs/hooks/utils/bar-y.d.ts +27 -0
- package/dist/cjs/hooks/utils/bar-y.js +69 -0
- package/dist/cjs/hooks/utils/index.d.ts +1 -0
- package/dist/cjs/hooks/utils/index.js +1 -0
- package/dist/cjs/i18n/keysets/en.json +7 -1
- package/dist/cjs/i18n/keysets/ru.json +7 -1
- package/dist/cjs/types/chart/axis.d.ts +2 -2
- package/dist/cjs/types/chart/tooltip.d.ts +21 -0
- package/dist/cjs/validation/index.js +55 -1
- package/dist/esm/components/ChartInner/index.js +1 -1
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +1 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.js +19 -12
- package/dist/esm/components/Legend/index.d.ts +0 -1
- package/dist/esm/components/Legend/index.js +13 -23
- package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +1 -0
- package/dist/esm/components/Tooltip/ChartTooltipContent.js +3 -3
- package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.d.ts +9 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/Row.js +10 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/RowTotals.d.ts +9 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/RowTotals.js +23 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/index.d.ts +11 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +102 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +30 -0
- package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +126 -0
- package/dist/esm/components/Tooltip/index.js +1 -1
- package/dist/esm/components/Tooltip/styles.css +14 -2
- package/dist/esm/components/Tooltip/utils.d.ts +30 -0
- package/dist/esm/components/Tooltip/utils.js +126 -0
- package/dist/esm/constants/axis.d.ts +6 -0
- package/dist/esm/constants/axis.js +6 -0
- package/dist/esm/constants/index.d.ts +6 -4
- package/dist/esm/constants/index.js +6 -4
- package/dist/esm/constants/tooltip.d.ts +3 -0
- package/dist/esm/constants/tooltip.js +3 -0
- package/dist/esm/hooks/useAxisScales/index.d.ts +14 -3
- package/dist/esm/hooks/useAxisScales/index.js +73 -22
- package/dist/esm/hooks/useChartOptions/x-axis.js +1 -1
- package/dist/esm/hooks/useChartOptions/y-axis.d.ts +4 -2
- package/dist/esm/hooks/useChartOptions/y-axis.js +9 -3
- package/dist/esm/hooks/useSeries/index.d.ts +9 -0
- package/dist/esm/hooks/useSeries/index.js +59 -29
- package/dist/esm/hooks/useSeries/prepare-legend.d.ts +2 -2
- package/dist/esm/hooks/useSeries/prepare-legend.js +4 -6
- package/dist/esm/hooks/useSeries/types.d.ts +1 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +1 -1
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +17 -62
- package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +1 -1
- package/dist/esm/hooks/utils/bar-y.d.ts +27 -0
- package/dist/esm/hooks/utils/bar-y.js +69 -0
- package/dist/esm/hooks/utils/index.d.ts +1 -0
- package/dist/esm/hooks/utils/index.js +1 -0
- package/dist/esm/i18n/keysets/en.json +7 -1
- package/dist/esm/i18n/keysets/ru.json +7 -1
- package/dist/esm/types/chart/axis.d.ts +2 -2
- package/dist/esm/types/chart/tooltip.d.ts +21 -0
- package/dist/esm/validation/index.js +55 -1
- package/package.json +1 -1
- package/dist/cjs/components/Tooltip/DefaultContent.d.ts +0 -10
- package/dist/cjs/components/Tooltip/DefaultContent.js +0 -187
- package/dist/esm/components/Tooltip/DefaultContent.d.ts +0 -10
- package/dist/esm/components/Tooltip/DefaultContent.js +0 -187
- /package/dist/cjs/hooks/{useShapes/constants.d.ts → constants.d.ts} +0 -0
- /package/dist/cjs/hooks/{useShapes/constants.js → constants.js} +0 -0
- /package/dist/esm/hooks/{useShapes/constants.d.ts → constants.d.ts} +0 -0
- /package/dist/esm/hooks/{useShapes/constants.js → constants.js} +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { extent, scaleBand, scaleLinear, scaleLog, scaleUtc } from 'd3';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
|
-
import { DEFAULT_AXIS_TYPE } from '../../constants';
|
|
4
|
+
import { DEFAULT_AXIS_TYPE, SeriesType } from '../../constants';
|
|
5
5
|
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, getAxisHeight, getDataCategoryValue, getDefaultMaxXAxisValue, getDefaultMinXAxisValue, getDomainDataXBySeries, getDomainDataYBySeries, getOnlyVisibleSeries, isAxisRelatedSeries, isSeriesWithCategoryValues, } from '../../utils';
|
|
6
|
+
import { getBarYLayoutForNumericScale } from '../utils';
|
|
6
7
|
const X_AXIS_ZOOM_PADDING = 0.02;
|
|
7
|
-
|
|
8
|
+
function isNumericalArrayData(data) {
|
|
8
9
|
return data.every((d) => typeof d === 'number' || d === null);
|
|
9
|
-
}
|
|
10
|
-
|
|
10
|
+
}
|
|
11
|
+
function filterCategoriesByVisibleSeries(args) {
|
|
11
12
|
const { axisDirection, categories, series } = args;
|
|
12
13
|
const visibleCategories = new Set();
|
|
13
14
|
series.forEach((s) => {
|
|
@@ -18,18 +19,61 @@ const filterCategoriesByVisibleSeries = (args) => {
|
|
|
18
19
|
}
|
|
19
20
|
});
|
|
20
21
|
return categories.filter((c) => visibleCategories.has(c));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
}
|
|
23
|
+
// axis is validated in `validation/index.ts`, so the value of `axis.type` is definitely valid.
|
|
24
|
+
// eslint-disable-next-line consistent-return
|
|
25
|
+
function getYScaleRange(args) {
|
|
26
|
+
const { axis, boundsHeight, series, seriesOptions } = args;
|
|
27
|
+
switch (axis.type) {
|
|
28
|
+
case 'datetime':
|
|
29
|
+
case 'linear':
|
|
30
|
+
case 'logarithmic': {
|
|
31
|
+
const barYSeries = series.filter((s) => s.type === SeriesType.BarY);
|
|
32
|
+
if (barYSeries.length) {
|
|
33
|
+
const { barSize, dataLength } = getBarYLayoutForNumericScale({
|
|
34
|
+
plotHeight: boundsHeight - boundsHeight * axis.maxPadding,
|
|
35
|
+
series: barYSeries,
|
|
36
|
+
seriesOptions: seriesOptions,
|
|
37
|
+
});
|
|
38
|
+
if (dataLength > 1) {
|
|
39
|
+
const alreadyCountedStackingIds = new Set();
|
|
40
|
+
const offsetMultiplier = barYSeries.reduce((acc, s) => {
|
|
41
|
+
let count = 0;
|
|
42
|
+
if (s.stackId) {
|
|
43
|
+
if (!alreadyCountedStackingIds.has(s.stackId)) {
|
|
44
|
+
alreadyCountedStackingIds.add(s.stackId);
|
|
45
|
+
count = 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
count = 1;
|
|
50
|
+
}
|
|
51
|
+
return acc + count;
|
|
52
|
+
}, 0);
|
|
53
|
+
const offset = (barSize * Math.max(offsetMultiplier, 1)) / 2;
|
|
54
|
+
const start = boundsHeight - offset;
|
|
55
|
+
const end = boundsHeight * axis.maxPadding + offset;
|
|
56
|
+
return [start, end];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return [boundsHeight, boundsHeight * axis.maxPadding];
|
|
60
|
+
}
|
|
61
|
+
case 'category': {
|
|
62
|
+
return [boundsHeight, 0];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function createYScale(args) {
|
|
67
|
+
const { axis, boundsHeight, series, seriesOptions } = args;
|
|
24
68
|
const yMinProps = get(axis, 'min');
|
|
25
69
|
const yMaxProps = get(axis, 'max');
|
|
26
70
|
const yCategories = get(axis, 'categories');
|
|
27
71
|
const yTimestamps = get(axis, 'timestamps');
|
|
28
|
-
|
|
72
|
+
const range = getYScaleRange({ axis, boundsHeight, series, seriesOptions });
|
|
73
|
+
switch (axis.type) {
|
|
29
74
|
case 'linear':
|
|
30
75
|
case 'logarithmic': {
|
|
31
76
|
const domain = getDomainDataYBySeries(series);
|
|
32
|
-
const range = [boundsHeight, boundsHeight * axis.maxPadding];
|
|
33
77
|
if (isNumericalArrayData(domain)) {
|
|
34
78
|
const [yMinDomain, yMaxDomain] = extent(domain);
|
|
35
79
|
const yMin = typeof yMinProps === 'number' ? yMinProps : yMinDomain;
|
|
@@ -41,7 +85,7 @@ export function createYScale(axis, series, boundsHeight) {
|
|
|
41
85
|
const hasSeriesWithVolumeOnYAxis = series.some((s) => CHART_SERIES_WITH_VOLUME_ON_Y_AXIS.includes(s.type));
|
|
42
86
|
yMax = hasSeriesWithVolumeOnYAxis ? Math.max(yMaxDomain, 0) : yMaxDomain;
|
|
43
87
|
}
|
|
44
|
-
const scaleFn =
|
|
88
|
+
const scaleFn = axis.type === 'logarithmic' ? scaleLog : scaleLinear;
|
|
45
89
|
return scaleFn().domain([yMin, yMax]).range(range).nice();
|
|
46
90
|
}
|
|
47
91
|
break;
|
|
@@ -53,12 +97,11 @@ export function createYScale(axis, series, boundsHeight) {
|
|
|
53
97
|
categories: yCategories,
|
|
54
98
|
series: series,
|
|
55
99
|
});
|
|
56
|
-
return scaleBand().domain(filteredCategories).range(
|
|
100
|
+
return scaleBand().domain(filteredCategories).range(range);
|
|
57
101
|
}
|
|
58
102
|
break;
|
|
59
103
|
}
|
|
60
104
|
case 'datetime': {
|
|
61
|
-
const range = [boundsHeight, boundsHeight * axis.maxPadding];
|
|
62
105
|
if (yTimestamps) {
|
|
63
106
|
const [yMinTimestamp, yMaxTimestamp] = extent(yTimestamps);
|
|
64
107
|
const yMin = typeof yMinProps === 'number' ? yMinProps : yMinTimestamp;
|
|
@@ -74,7 +117,6 @@ export function createYScale(axis, series, boundsHeight) {
|
|
|
74
117
|
return scaleUtc().domain([yMin, yMax]).range(range).nice();
|
|
75
118
|
}
|
|
76
119
|
}
|
|
77
|
-
break;
|
|
78
120
|
}
|
|
79
121
|
}
|
|
80
122
|
throw new Error('Failed to create yScale');
|
|
@@ -97,7 +139,8 @@ function calculateXAxisPadding(series) {
|
|
|
97
139
|
return result;
|
|
98
140
|
}
|
|
99
141
|
// eslint-disable-next-line complexity
|
|
100
|
-
export function createXScale(
|
|
142
|
+
export function createXScale(args) {
|
|
143
|
+
const { axis, boundsWidth, series, hasZoomX } = args;
|
|
101
144
|
const xMinProps = get(axis, 'min');
|
|
102
145
|
const xMaxProps = get(axis, 'max');
|
|
103
146
|
const xType = get(axis, 'type', DEFAULT_AXIS_TYPE);
|
|
@@ -193,13 +236,15 @@ export function createXScale(axis, series, boundsWidth, hasZoomX) {
|
|
|
193
236
|
throw new Error('Failed to create xScale');
|
|
194
237
|
}
|
|
195
238
|
const createScales = (args) => {
|
|
196
|
-
const { boundsWidth, boundsHeight,
|
|
239
|
+
const { boundsWidth, boundsHeight, hasZoomX, series, seriesOptions, split, xAxis, yAxis } = args;
|
|
197
240
|
let visibleSeries = getOnlyVisibleSeries(series);
|
|
198
241
|
// Reassign to all series in case of all series unselected,
|
|
199
242
|
// otherwise we will get an empty space without grid
|
|
200
243
|
visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
|
|
201
244
|
return {
|
|
202
|
-
xScale: xAxis
|
|
245
|
+
xScale: xAxis
|
|
246
|
+
? createXScale({ axis: xAxis, boundsWidth, series: visibleSeries, hasZoomX })
|
|
247
|
+
: undefined,
|
|
203
248
|
yScale: yAxis.map((axis, index) => {
|
|
204
249
|
const axisSeries = series.filter((s) => {
|
|
205
250
|
const seriesAxisIndex = get(s, 'yAxis', 0);
|
|
@@ -207,7 +252,12 @@ const createScales = (args) => {
|
|
|
207
252
|
});
|
|
208
253
|
const visibleAxisSeries = getOnlyVisibleSeries(axisSeries);
|
|
209
254
|
const axisHeight = getAxisHeight({ boundsHeight, split });
|
|
210
|
-
return createYScale(
|
|
255
|
+
return createYScale({
|
|
256
|
+
axis,
|
|
257
|
+
boundsHeight: axisHeight,
|
|
258
|
+
series: visibleAxisSeries.length ? visibleAxisSeries : axisSeries,
|
|
259
|
+
seriesOptions,
|
|
260
|
+
});
|
|
211
261
|
}),
|
|
212
262
|
};
|
|
213
263
|
};
|
|
@@ -215,7 +265,7 @@ const createScales = (args) => {
|
|
|
215
265
|
* Uses to create scales for axis related series
|
|
216
266
|
*/
|
|
217
267
|
export const useAxisScales = (args) => {
|
|
218
|
-
const { boundsWidth, boundsHeight,
|
|
268
|
+
const { boundsWidth, boundsHeight, hasZoomX, hasZoomY, series, seriesOptions, split, xAxis, yAxis, } = args;
|
|
219
269
|
return React.useMemo(() => {
|
|
220
270
|
let xScale;
|
|
221
271
|
let yScale;
|
|
@@ -224,14 +274,15 @@ export const useAxisScales = (args) => {
|
|
|
224
274
|
({ xScale, yScale } = createScales({
|
|
225
275
|
boundsWidth,
|
|
226
276
|
boundsHeight,
|
|
277
|
+
hasZoomX,
|
|
278
|
+
hasZoomY,
|
|
227
279
|
series,
|
|
280
|
+
seriesOptions,
|
|
281
|
+
split,
|
|
228
282
|
xAxis,
|
|
229
283
|
yAxis,
|
|
230
|
-
split,
|
|
231
|
-
hasZoomX,
|
|
232
|
-
hasZoomY,
|
|
233
284
|
}));
|
|
234
285
|
}
|
|
235
286
|
return { xScale, yScale };
|
|
236
|
-
}, [boundsWidth, boundsHeight,
|
|
287
|
+
}, [boundsWidth, boundsHeight, hasZoomX, hasZoomY, series, seriesOptions, split, xAxis, yAxis]);
|
|
237
288
|
};
|
|
@@ -3,7 +3,7 @@ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, axisCrosshairDefaults, axisLa
|
|
|
3
3
|
import { calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
|
|
4
4
|
import { createXScale } from '../useAxisScales';
|
|
5
5
|
async function getLabelSettings({ axis, seriesData, width, autoRotation = true, }) {
|
|
6
|
-
const scale = createXScale(axis, seriesData, width);
|
|
6
|
+
const scale = createXScale({ axis, series: seriesData, boundsWidth: width });
|
|
7
7
|
const tickCount = getTicksCount({ axis, range: width });
|
|
8
8
|
const ticks = getXAxisItems({
|
|
9
9
|
scale: scale,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ChartSeries, ChartYAxis } from '../../types';
|
|
2
|
+
import type { PreparedSeriesOptions } from '../useSeries/types';
|
|
2
3
|
import type { PreparedAxis } from './types';
|
|
3
|
-
export declare const getPreparedYAxis: ({ seriesData,
|
|
4
|
+
export declare const getPreparedYAxis: ({ height, seriesData, seriesOptions, yAxis, }: {
|
|
5
|
+
height: number;
|
|
4
6
|
seriesData: ChartSeries[];
|
|
7
|
+
seriesOptions: PreparedSeriesOptions;
|
|
5
8
|
yAxis: ChartYAxis[] | undefined;
|
|
6
|
-
height: number;
|
|
7
9
|
}) => Promise<PreparedAxis[]>;
|
|
@@ -3,11 +3,16 @@ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, axisCrossh
|
|
|
3
3
|
import { formatAxisTickLabel, getClosestPointsRange, getDefaultMinYAxisValue, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, isAxisRelatedSeries, wrapText, } from '../../utils';
|
|
4
4
|
import { createYScale } from '../useAxisScales';
|
|
5
5
|
const getAxisLabelMaxWidth = async (args) => {
|
|
6
|
-
const { axis, seriesData } = args;
|
|
6
|
+
const { axis, seriesData, seriesOptions } = args;
|
|
7
7
|
if (!axis.labels.enabled) {
|
|
8
8
|
return 0;
|
|
9
9
|
}
|
|
10
|
-
const scale = createYScale(
|
|
10
|
+
const scale = createYScale({
|
|
11
|
+
axis,
|
|
12
|
+
boundsHeight: 1,
|
|
13
|
+
series: seriesData,
|
|
14
|
+
seriesOptions,
|
|
15
|
+
});
|
|
11
16
|
const ticks = getScaleTicks(scale);
|
|
12
17
|
// FIXME: it is necessary to filter data, since we do not draw overlapping ticks
|
|
13
18
|
const step = getClosestPointsRange(axis, ticks);
|
|
@@ -23,7 +28,7 @@ const getAxisLabelMaxWidth = async (args) => {
|
|
|
23
28
|
});
|
|
24
29
|
return size.maxWidth;
|
|
25
30
|
};
|
|
26
|
-
export const getPreparedYAxis = ({ seriesData,
|
|
31
|
+
export const getPreparedYAxis = ({ height, seriesData, seriesOptions, yAxis, }) => {
|
|
27
32
|
const axisByPlot = [];
|
|
28
33
|
const axisItems = yAxis || [{}];
|
|
29
34
|
const hasAxisRelatedSeries = seriesData.some(isAxisRelatedSeries);
|
|
@@ -126,6 +131,7 @@ export const getPreparedYAxis = ({ seriesData, yAxis, height, }) => {
|
|
|
126
131
|
preparedAxis.labels.width = await getAxisLabelMaxWidth({
|
|
127
132
|
axis: preparedAxis,
|
|
128
133
|
seriesData,
|
|
134
|
+
seriesOptions,
|
|
129
135
|
});
|
|
130
136
|
}
|
|
131
137
|
return preparedAxis;
|
|
@@ -13,4 +13,13 @@ 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
|
+
};
|
|
16
25
|
export {};
|
|
@@ -5,6 +5,38 @@ import { usePrevious } from '../usePrevious';
|
|
|
5
5
|
import { getPreparedLegend } from './prepare-legend';
|
|
6
6
|
import { prepareSeries } from './prepareSeries';
|
|
7
7
|
import { getActiveLegendItems, getAllLegendItems } from './utils';
|
|
8
|
+
const useVisibleSeries = ({ preparedSeries, activeLegendItems, }) => {
|
|
9
|
+
return React.useMemo(() => {
|
|
10
|
+
return preparedSeries.map((singleSeries) => {
|
|
11
|
+
if (singleSeries.legend.enabled) {
|
|
12
|
+
return Object.assign(Object.assign({}, singleSeries), { visible: activeLegendItems.includes(singleSeries.name) });
|
|
13
|
+
}
|
|
14
|
+
return singleSeries;
|
|
15
|
+
});
|
|
16
|
+
}, [preparedSeries, activeLegendItems]);
|
|
17
|
+
};
|
|
18
|
+
const getPreparedSeries = async ({ seriesData, seriesOptions, colors, preparedLegend, }) => {
|
|
19
|
+
const seriesNames = getSeriesNames(seriesData);
|
|
20
|
+
const colorScale = scaleOrdinal(seriesNames, colors);
|
|
21
|
+
const groupedSeries = group(seriesData, (item) => item.type);
|
|
22
|
+
const acc = [];
|
|
23
|
+
if (!preparedLegend) {
|
|
24
|
+
return acc;
|
|
25
|
+
}
|
|
26
|
+
const list = Array.from(groupedSeries);
|
|
27
|
+
for (let i = 0; i < list.length; i++) {
|
|
28
|
+
const [seriesType, seriesList] = list[i];
|
|
29
|
+
acc.push(...(await prepareSeries({
|
|
30
|
+
type: seriesType,
|
|
31
|
+
series: seriesList,
|
|
32
|
+
seriesOptions,
|
|
33
|
+
legend: preparedLegend,
|
|
34
|
+
colorScale,
|
|
35
|
+
colors,
|
|
36
|
+
})));
|
|
37
|
+
}
|
|
38
|
+
return acc;
|
|
39
|
+
};
|
|
8
40
|
export const useSeries = (args) => {
|
|
9
41
|
const { legend, originalSeriesData, seriesData, seriesOptions, colors, preparedLegend: preparedLegendProps = null, } = args;
|
|
10
42
|
const [preparedLegend, setPreparedLegend] = React.useState(preparedLegendProps);
|
|
@@ -17,38 +49,18 @@ export const useSeries = (args) => {
|
|
|
17
49
|
const [activeLegendItems, setActiveLegendItems] = React.useState(getActiveLegendItems(preparedSeries));
|
|
18
50
|
React.useEffect(() => {
|
|
19
51
|
(async () => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
for (let i = 0; i < list.length; i++) {
|
|
29
|
-
const [seriesType, seriesList] = list[i];
|
|
30
|
-
acc.push(...(await prepareSeries({
|
|
31
|
-
type: seriesType,
|
|
32
|
-
series: seriesList,
|
|
33
|
-
seriesOptions,
|
|
34
|
-
legend: preparedLegend,
|
|
35
|
-
colorScale,
|
|
36
|
-
colors,
|
|
37
|
-
})));
|
|
38
|
-
}
|
|
39
|
-
setPreparedSeries(acc);
|
|
40
|
-
setActiveLegendItems(getActiveLegendItems(acc));
|
|
52
|
+
const items = await getPreparedSeries({
|
|
53
|
+
seriesData,
|
|
54
|
+
seriesOptions,
|
|
55
|
+
preparedLegend,
|
|
56
|
+
colors,
|
|
57
|
+
});
|
|
58
|
+
setPreparedSeries(items);
|
|
59
|
+
setActiveLegendItems(getActiveLegendItems(items));
|
|
41
60
|
})();
|
|
42
61
|
}, [seriesData, seriesOptions, preparedLegend, colors]);
|
|
43
62
|
const prevOriginalSeriesData = usePrevious(originalSeriesData);
|
|
44
|
-
const chartSeries =
|
|
45
|
-
return preparedSeries.map((singleSeries) => {
|
|
46
|
-
if (singleSeries.legend.enabled) {
|
|
47
|
-
return Object.assign(Object.assign({}, singleSeries), { visible: activeLegendItems.includes(singleSeries.name) });
|
|
48
|
-
}
|
|
49
|
-
return singleSeries;
|
|
50
|
-
});
|
|
51
|
-
}, [preparedSeries, activeLegendItems]);
|
|
63
|
+
const chartSeries = useVisibleSeries({ preparedSeries, activeLegendItems });
|
|
52
64
|
const handleLegendItemClick = React.useCallback(({ name, metaKey }) => {
|
|
53
65
|
const allItems = getAllLegendItems(preparedSeries);
|
|
54
66
|
const onlyItemSelected = activeLegendItems.length === 1 && activeLegendItems.includes(name);
|
|
@@ -81,3 +93,21 @@ export const useSeries = (args) => {
|
|
|
81
93
|
handleLegendItemClick,
|
|
82
94
|
};
|
|
83
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
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChartData } from '../../types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PreparedChart } from '../useChartOptions/types';
|
|
3
3
|
import type { LegendItem, PreparedLegend, PreparedSeries } from './types';
|
|
4
4
|
export declare function getPreparedLegend(args: {
|
|
5
5
|
legend: ChartData['legend'];
|
|
@@ -11,7 +11,6 @@ export declare function getLegendComponents(args: {
|
|
|
11
11
|
chartMargin: PreparedChart['margin'];
|
|
12
12
|
series: PreparedSeries[];
|
|
13
13
|
preparedLegend: PreparedLegend;
|
|
14
|
-
preparedYAxis: PreparedAxis[];
|
|
15
14
|
}): {
|
|
16
15
|
legendConfig: {
|
|
17
16
|
offset: {
|
|
@@ -24,6 +23,7 @@ export declare function getLegendComponents(args: {
|
|
|
24
23
|
end: number;
|
|
25
24
|
}[];
|
|
26
25
|
} | undefined;
|
|
26
|
+
maxWidth: number;
|
|
27
27
|
};
|
|
28
28
|
legendItems: LegendItem[][];
|
|
29
29
|
};
|
|
@@ -4,8 +4,6 @@ import get from 'lodash/get';
|
|
|
4
4
|
import merge from 'lodash/merge';
|
|
5
5
|
import { CONTINUOUS_LEGEND_SIZE, legendDefaults } from '../../constants';
|
|
6
6
|
import { getDefaultColorStops, getDomainForContinuousColorScale, getLabelsSize } from '../../utils';
|
|
7
|
-
import { getBoundsWidth } from '../useChartDimensions';
|
|
8
|
-
import { getYAxisWidth } from '../useChartDimensions/utils';
|
|
9
7
|
export async function getPreparedLegend(args) {
|
|
10
8
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
11
9
|
const { legend, series } = args;
|
|
@@ -168,8 +166,8 @@ function getPagination(args) {
|
|
|
168
166
|
return { pages };
|
|
169
167
|
}
|
|
170
168
|
export function getLegendComponents(args) {
|
|
171
|
-
const { chartWidth, chartHeight, chartMargin, series, preparedLegend
|
|
172
|
-
const maxLegendWidth =
|
|
169
|
+
const { chartWidth, chartHeight, chartMargin, series, preparedLegend } = args;
|
|
170
|
+
const maxLegendWidth = chartWidth - chartMargin.right - chartMargin.left;
|
|
173
171
|
const maxLegendHeight = (chartHeight - chartMargin.top - chartMargin.bottom - preparedLegend.margin) / 2;
|
|
174
172
|
const flattenLegendItems = getFlattenLegendItems(series, preparedLegend);
|
|
175
173
|
const items = getGroupedLegendItems({
|
|
@@ -199,8 +197,8 @@ export function getLegendComponents(args) {
|
|
|
199
197
|
}
|
|
200
198
|
const top = chartHeight - chartMargin.bottom - preparedLegend.height;
|
|
201
199
|
const offset = {
|
|
202
|
-
left: chartMargin.left
|
|
200
|
+
left: chartMargin.left,
|
|
203
201
|
top,
|
|
204
202
|
};
|
|
205
|
-
return { legendConfig: { offset, pagination }, legendItems: items };
|
|
203
|
+
return { legendConfig: { offset, pagination, maxWidth: maxLegendWidth }, legendItems: items };
|
|
206
204
|
}
|
|
@@ -2,7 +2,7 @@ import { ascending, descending, max, sort } from 'd3';
|
|
|
2
2
|
import get from 'lodash/get';
|
|
3
3
|
import { getDataCategoryValue, getLabelsSize } from '../../../utils';
|
|
4
4
|
import { getFormattedValue } from '../../../utils/chart/format';
|
|
5
|
-
import { MIN_BAR_GAP, MIN_BAR_GROUP_GAP, MIN_BAR_WIDTH } from '
|
|
5
|
+
import { MIN_BAR_GAP, MIN_BAR_GROUP_GAP, MIN_BAR_WIDTH } from '../../constants';
|
|
6
6
|
async function getLabelData(d) {
|
|
7
7
|
if (!d.series.dataLabels.enabled) {
|
|
8
8
|
return undefined;
|
|
@@ -1,54 +1,9 @@
|
|
|
1
|
-
import { ascending, descending,
|
|
1
|
+
import { ascending, descending, sort } from 'd3';
|
|
2
2
|
import get from 'lodash/get';
|
|
3
|
-
import {
|
|
3
|
+
import { getLabelsSize } from '../../../utils';
|
|
4
4
|
import { getFormattedValue } from '../../../utils/chart/format';
|
|
5
|
-
import {
|
|
5
|
+
import { getBarYLayoutForCategoryScale, getBarYLayoutForNumericScale, groupBarYDataByYValue, } from '../../utils';
|
|
6
6
|
const DEFAULT_LABEL_PADDING = 7;
|
|
7
|
-
function groupByYValue(series, yAxis) {
|
|
8
|
-
const data = {};
|
|
9
|
-
series.forEach((s) => {
|
|
10
|
-
s.data.forEach((d) => {
|
|
11
|
-
const axisIndex = get(s, 'yAxis', 0);
|
|
12
|
-
const seriesYAxis = yAxis[axisIndex];
|
|
13
|
-
const categories = get(seriesYAxis, 'categories', []);
|
|
14
|
-
const key = seriesYAxis.type === 'category'
|
|
15
|
-
? getDataCategoryValue({ axisDirection: 'y', categories, data: d })
|
|
16
|
-
: d.y;
|
|
17
|
-
if (key) {
|
|
18
|
-
if (!data[key]) {
|
|
19
|
-
data[key] = {};
|
|
20
|
-
}
|
|
21
|
-
if (!data[key][s.stackId]) {
|
|
22
|
-
data[key][s.stackId] = [];
|
|
23
|
-
}
|
|
24
|
-
data[key][s.stackId].push({ data: d, series: s });
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
return data;
|
|
29
|
-
}
|
|
30
|
-
function getBandWidth(series, yAxis, yScale) {
|
|
31
|
-
let bandWidth = Infinity;
|
|
32
|
-
if (yAxis[0].type === 'category') {
|
|
33
|
-
bandWidth = yScale.bandwidth();
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
const scale = yScale;
|
|
37
|
-
const axisValues = series.reduce((acc, s) => {
|
|
38
|
-
s.data.forEach((dataItem) => acc.push(Number(dataItem.y)));
|
|
39
|
-
return acc;
|
|
40
|
-
}, []);
|
|
41
|
-
axisValues.sort().forEach((value, index) => {
|
|
42
|
-
if (index > 0 && value !== axisValues[index - 1]) {
|
|
43
|
-
const dist = scale(value) - scale(axisValues[index - 1]);
|
|
44
|
-
if (dist < bandWidth) {
|
|
45
|
-
bandWidth = dist;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
return bandWidth;
|
|
51
|
-
}
|
|
52
7
|
async function setLabel(prepared) {
|
|
53
8
|
const dataLabels = prepared.series.dataLabels;
|
|
54
9
|
if (!dataLabels.enabled) {
|
|
@@ -89,10 +44,9 @@ async function setLabel(prepared) {
|
|
|
89
44
|
export const prepareBarYData = async (args) => {
|
|
90
45
|
const { series, seriesOptions, yAxis, xScale, yScale: [yScale], } = args;
|
|
91
46
|
const xLinearScale = xScale;
|
|
47
|
+
const yLinearScale = yScale;
|
|
48
|
+
const plotHeight = yLinearScale(yLinearScale.domain()[0]);
|
|
92
49
|
const plotWidth = xLinearScale(xLinearScale.domain()[1]);
|
|
93
|
-
const barMaxWidth = get(seriesOptions, 'bar-y.barMaxWidth');
|
|
94
|
-
const barPadding = get(seriesOptions, 'bar-y.barPadding');
|
|
95
|
-
const groupPadding = get(seriesOptions, 'bar-y.groupPadding');
|
|
96
50
|
const sortingOptions = get(seriesOptions, 'bar-y.dataSorting');
|
|
97
51
|
const comparator = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.direction) === 'desc' ? descending : ascending;
|
|
98
52
|
const sortKey = (() => {
|
|
@@ -108,17 +62,18 @@ export const prepareBarYData = async (args) => {
|
|
|
108
62
|
}
|
|
109
63
|
}
|
|
110
64
|
})();
|
|
111
|
-
const groupedData =
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
65
|
+
const groupedData = groupBarYDataByYValue(series, yAxis);
|
|
66
|
+
const { bandSize, barGap, barSize } = yAxis[0].type === 'category'
|
|
67
|
+
? getBarYLayoutForCategoryScale({ groupedData, seriesOptions, yScale })
|
|
68
|
+
: getBarYLayoutForNumericScale({
|
|
69
|
+
series,
|
|
70
|
+
seriesOptions,
|
|
71
|
+
plotHeight: plotHeight - plotHeight * yAxis[0].maxPadding,
|
|
72
|
+
});
|
|
118
73
|
const result = [];
|
|
119
74
|
Object.entries(groupedData).forEach(([yValue, val]) => {
|
|
120
75
|
const stacks = Object.values(val);
|
|
121
|
-
const currentBarHeight =
|
|
76
|
+
const currentBarHeight = barSize * stacks.length + barGap * (stacks.length - 1);
|
|
122
77
|
stacks.forEach((measureValues, groupItemIndex) => {
|
|
123
78
|
const base = xLinearScale(0);
|
|
124
79
|
let stackSum = base;
|
|
@@ -130,20 +85,20 @@ export const prepareBarYData = async (args) => {
|
|
|
130
85
|
let center;
|
|
131
86
|
if (yAxis[0].type === 'category') {
|
|
132
87
|
const bandScale = yScale;
|
|
133
|
-
center = (bandScale(yValue) || 0) +
|
|
88
|
+
center = (bandScale(yValue) || 0) + bandSize / 2;
|
|
134
89
|
}
|
|
135
90
|
else {
|
|
136
91
|
const scale = yScale;
|
|
137
92
|
center = scale(Number(yValue));
|
|
138
93
|
}
|
|
139
|
-
const y = center - currentBarHeight / 2 + (
|
|
94
|
+
const y = center - currentBarHeight / 2 + (barSize + barGap) * groupItemIndex;
|
|
140
95
|
const xValue = Number(data.x);
|
|
141
96
|
const width = xValue > 0 ? xLinearScale(xValue) - base : base - xLinearScale(xValue);
|
|
142
97
|
const item = {
|
|
143
98
|
x: xValue > 0 ? stackSum : stackSum - width,
|
|
144
99
|
y,
|
|
145
100
|
width,
|
|
146
|
-
height:
|
|
101
|
+
height: barSize,
|
|
147
102
|
color: data.color || s.color,
|
|
148
103
|
opacity: get(data, 'opacity', null),
|
|
149
104
|
data,
|
|
@@ -2,7 +2,7 @@ import get from 'lodash/get';
|
|
|
2
2
|
import sortBy from 'lodash/sortBy';
|
|
3
3
|
import { getLabelsSize } from '../../../utils';
|
|
4
4
|
import { getFormattedValue } from '../../../utils/chart/format';
|
|
5
|
-
import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '
|
|
5
|
+
import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '../../constants';
|
|
6
6
|
import { getXValue, getYValue } from '../utils';
|
|
7
7
|
async function getLabelData(d, plotHeight) {
|
|
8
8
|
var _a, _b;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { BarYSeries, BarYSeriesData } from '../../types';
|
|
2
|
+
import type { ChartScale } from '../useAxisScales';
|
|
3
|
+
import type { PreparedAxis } from '../useChartOptions/types';
|
|
4
|
+
import type { PreparedBarYSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
5
|
+
export declare function groupBarYDataByYValue(series: PreparedBarYSeries[], yAxis: PreparedAxis[]): Record<string | number, Record<string, {
|
|
6
|
+
data: BarYSeriesData;
|
|
7
|
+
series: PreparedBarYSeries;
|
|
8
|
+
}[]>>;
|
|
9
|
+
export declare function getBarYLayoutForNumericScale(args: {
|
|
10
|
+
plotHeight: number;
|
|
11
|
+
series: (BarYSeries | PreparedBarYSeries)[];
|
|
12
|
+
seriesOptions: PreparedSeriesOptions;
|
|
13
|
+
}): {
|
|
14
|
+
bandSize: number;
|
|
15
|
+
barGap: number;
|
|
16
|
+
barSize: number;
|
|
17
|
+
dataLength: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function getBarYLayoutForCategoryScale(args: {
|
|
20
|
+
groupedData: ReturnType<typeof groupBarYDataByYValue>;
|
|
21
|
+
seriesOptions: PreparedSeriesOptions;
|
|
22
|
+
yScale: ChartScale;
|
|
23
|
+
}): {
|
|
24
|
+
bandSize: number;
|
|
25
|
+
barGap: number;
|
|
26
|
+
barSize: number;
|
|
27
|
+
};
|