@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
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { i18n } from '../../i18n';
|
|
3
|
+
import { getDataCategoryValue } from '../../utils';
|
|
4
|
+
import { getFormattedValue } from '../../utils/chart/format';
|
|
5
|
+
const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
|
|
6
|
+
function getRowData(fieldName, data, axis) {
|
|
7
|
+
switch (axis === null || axis === void 0 ? void 0 : axis.type) {
|
|
8
|
+
case 'category': {
|
|
9
|
+
const categories = get(axis, 'categories', []);
|
|
10
|
+
return getDataCategoryValue({ axisDirection: fieldName, categories, data });
|
|
11
|
+
}
|
|
12
|
+
default: {
|
|
13
|
+
return get(data, fieldName);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function getXRowData(data, xAxis) {
|
|
18
|
+
return getRowData('x', data, xAxis);
|
|
19
|
+
}
|
|
20
|
+
function getYRowData(data, yAxis) {
|
|
21
|
+
return getRowData('y', data, yAxis);
|
|
22
|
+
}
|
|
23
|
+
export function getDefaultValueFormat({ axis, }) {
|
|
24
|
+
switch (axis === null || axis === void 0 ? void 0 : axis.type) {
|
|
25
|
+
case 'linear':
|
|
26
|
+
case 'logarithmic': {
|
|
27
|
+
return {
|
|
28
|
+
type: 'number',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
case 'datetime': {
|
|
32
|
+
return {
|
|
33
|
+
type: 'date',
|
|
34
|
+
format: DEFAULT_DATE_FORMAT,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
default:
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export const getMeasureValue = ({ data, xAxis, yAxis, valueFormat, }) => {
|
|
42
|
+
var _a, _b, _c, _d;
|
|
43
|
+
if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (data.some((item) => item.series.type === 'radar')) {
|
|
47
|
+
return (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
|
|
48
|
+
}
|
|
49
|
+
if (data.some((item) => item.series.type === 'bar-y')) {
|
|
50
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
|
|
51
|
+
return getFormattedValue({
|
|
52
|
+
value: getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis),
|
|
53
|
+
format,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: xAxis });
|
|
57
|
+
return getFormattedValue({
|
|
58
|
+
value: getXRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, xAxis),
|
|
59
|
+
format,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
export function getHoveredValues(args) {
|
|
63
|
+
const { hovered, xAxis, yAxis } = args;
|
|
64
|
+
return hovered.map((seriesItem) => {
|
|
65
|
+
var _a;
|
|
66
|
+
const { data, series } = seriesItem;
|
|
67
|
+
switch (series.type) {
|
|
68
|
+
case 'area':
|
|
69
|
+
case 'line':
|
|
70
|
+
case 'bar-x':
|
|
71
|
+
case 'scatter': {
|
|
72
|
+
return getYRowData(data, yAxis);
|
|
73
|
+
}
|
|
74
|
+
case 'bar-y': {
|
|
75
|
+
return getXRowData(data, xAxis);
|
|
76
|
+
}
|
|
77
|
+
case 'pie':
|
|
78
|
+
case 'radar':
|
|
79
|
+
case 'treemap': {
|
|
80
|
+
const seriesData = data;
|
|
81
|
+
return seriesData.value;
|
|
82
|
+
}
|
|
83
|
+
case 'sankey': {
|
|
84
|
+
const { target, data: source } = seriesItem;
|
|
85
|
+
return (_a = source.links.find((d) => d.name === (target === null || target === void 0 ? void 0 : target.name))) === null || _a === void 0 ? void 0 : _a.value;
|
|
86
|
+
}
|
|
87
|
+
case 'waterfall': {
|
|
88
|
+
return getYRowData(data, yAxis);
|
|
89
|
+
}
|
|
90
|
+
default: {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function getBuiltInAggregatedValue(args) {
|
|
97
|
+
const { aggregation, values } = args;
|
|
98
|
+
switch (aggregation) {
|
|
99
|
+
case 'sum':
|
|
100
|
+
return values.reduce((acc, value) => {
|
|
101
|
+
return acc + (typeof value === 'number' ? value : 0);
|
|
102
|
+
}, 0);
|
|
103
|
+
default:
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export function getBuiltInAggregationLabel(args) {
|
|
108
|
+
const { aggregation } = args;
|
|
109
|
+
switch (aggregation) {
|
|
110
|
+
case 'sum':
|
|
111
|
+
return i18n('tooltip', 'label_totals_sum');
|
|
112
|
+
default:
|
|
113
|
+
return '';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export function getPreparedAggregation(args) {
|
|
117
|
+
const { hovered, totals, xAxis, yAxis } = args;
|
|
118
|
+
const aggregation = totals === null || totals === void 0 ? void 0 : totals.aggregation;
|
|
119
|
+
if (typeof aggregation === 'string') {
|
|
120
|
+
return aggregation;
|
|
121
|
+
}
|
|
122
|
+
if (typeof aggregation === 'function') {
|
|
123
|
+
return () => aggregation({ hovered, xAxis, yAxis });
|
|
124
|
+
}
|
|
125
|
+
return 'sum';
|
|
126
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './misc';
|
|
1
|
+
export * from './axis';
|
|
3
2
|
export * from './chart-types';
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './symbol-types';
|
|
3
|
+
export * from './defaults';
|
|
6
4
|
export * from './layout-algorithms';
|
|
5
|
+
export * from './line-styles';
|
|
6
|
+
export * from './misc';
|
|
7
7
|
export * from './palette';
|
|
8
|
+
export * from './symbol-types';
|
|
9
|
+
export * from './tooltip';
|
|
8
10
|
export * from './typography';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './misc';
|
|
1
|
+
export * from './axis';
|
|
3
2
|
export * from './chart-types';
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './symbol-types';
|
|
3
|
+
export * from './defaults';
|
|
6
4
|
export * from './layout-algorithms';
|
|
5
|
+
export * from './line-styles';
|
|
6
|
+
export * from './misc';
|
|
7
7
|
export * from './palette';
|
|
8
|
+
export * from './symbol-types';
|
|
9
|
+
export * from './tooltip';
|
|
8
10
|
export * from './typography';
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
2
|
import type { ChartAxis, ChartSeries } from '../../types';
|
|
3
3
|
import type { PreparedAxis } from '../useChartOptions/types';
|
|
4
|
-
import type { PreparedSeries } from '../useSeries/types';
|
|
4
|
+
import type { PreparedSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
5
5
|
import type { PreparedSplit } from '../useSplit/types';
|
|
6
6
|
export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
|
|
7
7
|
type Args = {
|
|
8
8
|
boundsWidth: number;
|
|
9
9
|
boundsHeight: number;
|
|
10
10
|
series: PreparedSeries[];
|
|
11
|
+
seriesOptions: PreparedSeriesOptions;
|
|
11
12
|
xAxis: PreparedAxis | null;
|
|
12
13
|
yAxis: PreparedAxis[];
|
|
13
14
|
split: PreparedSplit;
|
|
@@ -18,8 +19,18 @@ type ReturnValue = {
|
|
|
18
19
|
xScale?: ChartScale;
|
|
19
20
|
yScale?: ChartScale[];
|
|
20
21
|
};
|
|
21
|
-
export declare function createYScale(
|
|
22
|
-
|
|
22
|
+
export declare function createYScale(args: {
|
|
23
|
+
axis: PreparedAxis;
|
|
24
|
+
boundsHeight: number;
|
|
25
|
+
series: (PreparedSeries | ChartSeries)[];
|
|
26
|
+
seriesOptions: PreparedSeriesOptions;
|
|
27
|
+
}): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never>;
|
|
28
|
+
export declare function createXScale(args: {
|
|
29
|
+
axis: PreparedAxis | ChartAxis;
|
|
30
|
+
boundsWidth: number;
|
|
31
|
+
series: (PreparedSeries | ChartSeries)[];
|
|
32
|
+
hasZoomX?: boolean;
|
|
33
|
+
}): ScaleBand<string> | ScaleLinear<number, number, never> | ScaleTime<number, number, never>;
|
|
23
34
|
/**
|
|
24
35
|
* Uses to create scales for axis related series
|
|
25
36
|
*/
|
|
@@ -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;
|