@gravity-ui/charts 1.0.1 → 1.2.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/Axis/AxisX.d.ts +1 -0
- package/dist/cjs/components/Axis/AxisX.js +57 -12
- package/dist/cjs/components/Axis/AxisY.d.ts +1 -0
- package/dist/cjs/components/Axis/AxisY.js +83 -12
- package/dist/cjs/components/ChartInner/index.js +3 -3
- package/dist/cjs/components/ChartInner/styles.css +2 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +14 -3
- package/dist/cjs/components/Legend/index.js +2 -2
- package/dist/cjs/components/Title/index.js +1 -1
- package/dist/cjs/components/Tooltip/DefaultContent.js +41 -23
- package/dist/cjs/hooks/useChartDimensions/index.js +3 -0
- package/dist/cjs/hooks/useChartDimensions/utils.js +3 -0
- package/dist/cjs/hooks/useChartOptions/types.d.ts +5 -3
- package/dist/cjs/hooks/useChartOptions/x-axis.js +8 -0
- package/dist/cjs/hooks/useChartOptions/y-axis.js +8 -0
- package/dist/cjs/hooks/useSeries/prepare-waterfall.js +40 -28
- package/dist/cjs/hooks/useSeries/types.d.ts +4 -3
- package/dist/cjs/hooks/useShapes/HtmlLayer.js +2 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/line/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/pie/index.js +1 -1
- package/dist/cjs/hooks/useShapes/pie/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/radar/prepare-data.js +1 -0
- package/dist/cjs/hooks/useShapes/treemap/index.js +1 -1
- package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +3 -2
- package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +4 -2
- package/dist/cjs/i18n/keysets/en.json +3 -1
- package/dist/cjs/i18n/keysets/ru.json +3 -1
- package/dist/cjs/libs/chart-error/index.d.ts +1 -0
- package/dist/cjs/libs/chart-error/index.js +1 -0
- package/dist/cjs/types/chart/axis.d.ts +32 -7
- package/dist/cjs/types/chart/waterfall.d.ts +9 -0
- package/dist/cjs/types/chart-ui.d.ts +1 -0
- package/dist/cjs/utils/chart/axis-generators/bottom.d.ts +1 -0
- package/dist/cjs/utils/chart/axis-generators/bottom.js +16 -1
- package/dist/cjs/utils/chart/axis.d.ts +12 -1
- package/dist/cjs/utils/chart/axis.js +35 -0
- package/dist/cjs/utils/chart/get-closest-data.js +23 -13
- package/dist/cjs/utils/chart/index.d.ts +2 -1
- package/dist/cjs/utils/chart/index.js +5 -5
- package/dist/cjs/utils/chart/series/waterfall.d.ts +2 -2
- package/dist/cjs/utils/chart/series/waterfall.js +1 -7
- package/dist/cjs/utils/chart/types.d.ts +1 -0
- package/dist/cjs/utils/chart/types.js +1 -0
- package/dist/cjs/utils/chart-ui/pie-center-text.d.ts +1 -0
- package/dist/cjs/utils/chart-ui/pie-center-text.js +3 -1
- package/dist/cjs/validation/index.js +144 -0
- package/dist/esm/components/Axis/AxisX.d.ts +1 -0
- package/dist/esm/components/Axis/AxisX.js +57 -12
- package/dist/esm/components/Axis/AxisY.d.ts +1 -0
- package/dist/esm/components/Axis/AxisY.js +83 -12
- package/dist/esm/components/ChartInner/index.js +3 -3
- package/dist/esm/components/ChartInner/styles.css +2 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.js +14 -3
- package/dist/esm/components/Legend/index.js +2 -2
- package/dist/esm/components/Title/index.js +1 -1
- package/dist/esm/components/Tooltip/DefaultContent.js +41 -23
- package/dist/esm/hooks/useChartDimensions/index.js +3 -0
- package/dist/esm/hooks/useChartDimensions/utils.js +3 -0
- package/dist/esm/hooks/useChartOptions/types.d.ts +5 -3
- package/dist/esm/hooks/useChartOptions/x-axis.js +8 -0
- package/dist/esm/hooks/useChartOptions/y-axis.js +8 -0
- package/dist/esm/hooks/useSeries/prepare-waterfall.js +40 -28
- package/dist/esm/hooks/useSeries/types.d.ts +4 -3
- package/dist/esm/hooks/useShapes/HtmlLayer.js +2 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/line/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/pie/index.js +1 -1
- package/dist/esm/hooks/useShapes/pie/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/radar/prepare-data.js +1 -0
- package/dist/esm/hooks/useShapes/treemap/index.js +1 -1
- package/dist/esm/hooks/useShapes/treemap/prepare-data.js +3 -2
- package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +4 -2
- package/dist/esm/i18n/keysets/en.json +3 -1
- package/dist/esm/i18n/keysets/ru.json +3 -1
- package/dist/esm/libs/chart-error/index.d.ts +1 -0
- package/dist/esm/libs/chart-error/index.js +1 -0
- package/dist/esm/types/chart/axis.d.ts +32 -7
- package/dist/esm/types/chart/waterfall.d.ts +9 -0
- package/dist/esm/types/chart-ui.d.ts +1 -0
- package/dist/esm/utils/chart/axis-generators/bottom.d.ts +1 -0
- package/dist/esm/utils/chart/axis-generators/bottom.js +16 -1
- package/dist/esm/utils/chart/axis.d.ts +12 -1
- package/dist/esm/utils/chart/axis.js +35 -0
- package/dist/esm/utils/chart/get-closest-data.js +23 -13
- package/dist/esm/utils/chart/index.d.ts +2 -1
- package/dist/esm/utils/chart/index.js +5 -5
- package/dist/esm/utils/chart/series/waterfall.d.ts +2 -2
- package/dist/esm/utils/chart/series/waterfall.js +1 -7
- package/dist/esm/utils/chart/types.d.ts +1 -0
- package/dist/esm/utils/chart/types.js +1 -0
- package/dist/esm/utils/chart-ui/pie-center-text.d.ts +1 -0
- package/dist/esm/utils/chart-ui/pie-center-text.js +3 -1
- package/dist/esm/validation/index.js +144 -0
- package/package.json +1 -1
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { dateTime } from '@gravity-ui/date-utils';
|
|
3
2
|
import get from 'lodash/get';
|
|
4
|
-
import { formatNumber } from '../../libs';
|
|
5
3
|
import { block, getDataCategoryValue, getWaterfallPointSubtotal } from '../../utils';
|
|
6
4
|
import { getFormattedValue } from '../../utils/chart/format';
|
|
7
5
|
const b = block('tooltip');
|
|
@@ -12,23 +10,14 @@ const getRowData = (fieldName, data, axis) => {
|
|
|
12
10
|
const categories = get(axis, 'categories', []);
|
|
13
11
|
return getDataCategoryValue({ axisDirection: fieldName, categories, data });
|
|
14
12
|
}
|
|
15
|
-
case 'datetime': {
|
|
16
|
-
const value = get(data, fieldName);
|
|
17
|
-
if (!value) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
return dateTime({ input: value }).format(DEFAULT_DATE_FORMAT);
|
|
21
|
-
}
|
|
22
|
-
case 'linear':
|
|
23
13
|
default: {
|
|
24
|
-
|
|
25
|
-
return formatNumber(value);
|
|
14
|
+
return get(data, fieldName);
|
|
26
15
|
}
|
|
27
16
|
}
|
|
28
17
|
};
|
|
29
18
|
const getXRowData = (data, xAxis) => getRowData('x', data, xAxis);
|
|
30
19
|
const getYRowData = (data, yAxis) => getRowData('y', data, yAxis);
|
|
31
|
-
const getMeasureValue = (data, xAxis, yAxis) => {
|
|
20
|
+
const getMeasureValue = ({ data, xAxis, yAxis, valueFormat, }) => {
|
|
32
21
|
var _a, _b, _c, _d;
|
|
33
22
|
if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
|
|
34
23
|
return null;
|
|
@@ -37,12 +26,38 @@ const getMeasureValue = (data, xAxis, yAxis) => {
|
|
|
37
26
|
return (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
|
|
38
27
|
}
|
|
39
28
|
if (data.some((item) => item.series.type === 'bar-y')) {
|
|
40
|
-
|
|
29
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
|
|
30
|
+
return getFormattedValue({
|
|
31
|
+
value: getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis),
|
|
32
|
+
format,
|
|
33
|
+
});
|
|
41
34
|
}
|
|
42
|
-
|
|
35
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: xAxis });
|
|
36
|
+
return getFormattedValue({
|
|
37
|
+
value: getXRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, xAxis),
|
|
38
|
+
format,
|
|
39
|
+
});
|
|
43
40
|
};
|
|
41
|
+
function getDefaultValueFormat({ axis }) {
|
|
42
|
+
switch (axis === null || axis === void 0 ? void 0 : axis.type) {
|
|
43
|
+
case 'linear':
|
|
44
|
+
case 'logarithmic': {
|
|
45
|
+
return {
|
|
46
|
+
type: 'number',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
case 'datetime': {
|
|
50
|
+
return {
|
|
51
|
+
type: 'date',
|
|
52
|
+
format: DEFAULT_DATE_FORMAT,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
44
59
|
export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
45
|
-
const measureValue = getMeasureValue(hovered, xAxis, yAxis);
|
|
60
|
+
const measureValue = getMeasureValue({ data: hovered, xAxis, yAxis });
|
|
46
61
|
return (React.createElement(React.Fragment, null,
|
|
47
62
|
measureValue && React.createElement("div", null, measureValue),
|
|
48
63
|
hovered.map((seriesItem, i) => {
|
|
@@ -55,9 +70,10 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
55
70
|
case 'line':
|
|
56
71
|
case 'area':
|
|
57
72
|
case 'bar-x': {
|
|
73
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
|
|
58
74
|
const formattedValue = getFormattedValue({
|
|
59
75
|
value: getYRowData(data, yAxis),
|
|
60
|
-
format
|
|
76
|
+
format,
|
|
61
77
|
});
|
|
62
78
|
const value = (React.createElement(React.Fragment, null,
|
|
63
79
|
series.name,
|
|
@@ -70,13 +86,14 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
70
86
|
case 'waterfall': {
|
|
71
87
|
const isTotal = get(data, 'total', false);
|
|
72
88
|
const subTotalValue = getWaterfallPointSubtotal(data, series);
|
|
89
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: yAxis });
|
|
73
90
|
const subTotal = getFormattedValue({
|
|
74
91
|
value: subTotalValue,
|
|
75
|
-
format
|
|
92
|
+
format,
|
|
76
93
|
});
|
|
77
94
|
const formattedValue = getFormattedValue({
|
|
78
95
|
value: getYRowData(data, yAxis),
|
|
79
|
-
format
|
|
96
|
+
format,
|
|
80
97
|
});
|
|
81
98
|
return (React.createElement("div", { key: `${id}_${get(data, 'x')}` },
|
|
82
99
|
!isTotal && (React.createElement(React.Fragment, null,
|
|
@@ -93,9 +110,10 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
93
110
|
subTotal)));
|
|
94
111
|
}
|
|
95
112
|
case 'bar-y': {
|
|
113
|
+
const format = valueFormat !== null && valueFormat !== void 0 ? valueFormat : getDefaultValueFormat({ axis: xAxis });
|
|
96
114
|
const formattedValue = getFormattedValue({
|
|
97
115
|
value: getXRowData(data, xAxis),
|
|
98
|
-
format
|
|
116
|
+
format,
|
|
99
117
|
});
|
|
100
118
|
const value = (React.createElement(React.Fragment, null,
|
|
101
119
|
series.name,
|
|
@@ -110,7 +128,7 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
110
128
|
const seriesData = data;
|
|
111
129
|
const formattedValue = getFormattedValue({
|
|
112
130
|
value: seriesData.value,
|
|
113
|
-
format: valueFormat,
|
|
131
|
+
format: valueFormat !== null && valueFormat !== void 0 ? valueFormat : { type: 'number' },
|
|
114
132
|
});
|
|
115
133
|
return (React.createElement("div", { key: id, className: b('content-row') },
|
|
116
134
|
React.createElement("div", { className: b('color'), style: { backgroundColor: color } }),
|
|
@@ -124,7 +142,7 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
124
142
|
const value = (_a = source.links.find((d) => d.name === (target === null || target === void 0 ? void 0 : target.name))) === null || _a === void 0 ? void 0 : _a.value;
|
|
125
143
|
const formattedValue = getFormattedValue({
|
|
126
144
|
value,
|
|
127
|
-
format: valueFormat,
|
|
145
|
+
format: valueFormat !== null && valueFormat !== void 0 ? valueFormat : { type: 'number' },
|
|
128
146
|
});
|
|
129
147
|
return (React.createElement("div", { key: id, className: b('content-row') },
|
|
130
148
|
React.createElement("div", { className: b('color'), style: { backgroundColor: source.color } }),
|
|
@@ -142,7 +160,7 @@ export const DefaultContent = ({ hovered, xAxis, yAxis, valueFormat }) => {
|
|
|
142
160
|
const seriesData = data;
|
|
143
161
|
const formattedValue = getFormattedValue({
|
|
144
162
|
value: seriesData.value,
|
|
145
|
-
format: valueFormat,
|
|
163
|
+
format: valueFormat !== null && valueFormat !== void 0 ? valueFormat : { type: 'number' },
|
|
146
164
|
});
|
|
147
165
|
const value = (React.createElement(React.Fragment, null,
|
|
148
166
|
React.createElement("span", null,
|
|
@@ -8,6 +8,9 @@ const getBottomOffset = (args) => {
|
|
|
8
8
|
if (preparedLegend.enabled) {
|
|
9
9
|
result += preparedLegend.height + preparedLegend.margin;
|
|
10
10
|
}
|
|
11
|
+
if (!preparedXAxis.visible) {
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
11
14
|
if (hasAxisRelatedSeries) {
|
|
12
15
|
if (preparedXAxis.title.text) {
|
|
13
16
|
result += preparedXAxis.title.height + preparedXAxis.title.margin;
|
|
@@ -6,6 +6,9 @@ export const getBoundsWidth = (args) => {
|
|
|
6
6
|
getWidthOccupiedByYAxis({ preparedAxis: preparedYAxis }));
|
|
7
7
|
};
|
|
8
8
|
export function getYAxisWidth(axis) {
|
|
9
|
+
if (!(axis === null || axis === void 0 ? void 0 : axis.visible)) {
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
9
12
|
let result = 0;
|
|
10
13
|
if (axis === null || axis === void 0 ? void 0 : axis.title.text) {
|
|
11
14
|
result += axis.title.height + axis.title.margin;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DashStyle } from 'src/constants';
|
|
2
|
-
import type {
|
|
2
|
+
import type { AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisTitleAlignment, ChartAxisType, ChartData, ChartMargin, PlotLayerPlacement } from '../../types';
|
|
3
3
|
type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation'>> & {
|
|
4
4
|
style: BaseTextStyle;
|
|
5
5
|
rotation: number;
|
|
@@ -11,15 +11,16 @@ type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style'
|
|
|
11
11
|
export type PreparedChart = {
|
|
12
12
|
margin: ChartMargin;
|
|
13
13
|
};
|
|
14
|
+
export type PreparedAxisPlotBand = Required<AxisPlotBand>;
|
|
14
15
|
export type PreparedAxisPlotLine = {
|
|
15
16
|
value: number;
|
|
16
17
|
color: string;
|
|
17
18
|
width: number;
|
|
18
19
|
dashStyle: DashStyle;
|
|
19
20
|
opacity: number;
|
|
20
|
-
layerPlacement:
|
|
21
|
+
layerPlacement: PlotLayerPlacement;
|
|
21
22
|
};
|
|
22
|
-
export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines'> & {
|
|
23
|
+
export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotBands'> & {
|
|
23
24
|
type: ChartAxisType;
|
|
24
25
|
labels: PreparedAxisLabels;
|
|
25
26
|
title: {
|
|
@@ -42,6 +43,7 @@ export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines'> & {
|
|
|
42
43
|
position: 'left' | 'right' | 'top' | 'bottom';
|
|
43
44
|
plotIndex: number;
|
|
44
45
|
plotLines: PreparedAxisPlotLine[];
|
|
46
|
+
plotBands: PreparedAxisPlotBand[];
|
|
45
47
|
};
|
|
46
48
|
export type PreparedTitle = ChartData['title'] & {
|
|
47
49
|
height: number;
|
|
@@ -110,6 +110,14 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
|
|
|
110
110
|
opacity: get(d, 'opacity', 1),
|
|
111
111
|
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
112
112
|
})),
|
|
113
|
+
plotBands: get(xAxis, 'plotBands', []).map((d) => ({
|
|
114
|
+
color: get(d, 'color', 'var(--g-color-base-brand)'),
|
|
115
|
+
opacity: get(d, 'opacity', 1),
|
|
116
|
+
from: get(d, 'from', 0),
|
|
117
|
+
to: get(d, 'to', 0),
|
|
118
|
+
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
119
|
+
})),
|
|
120
|
+
visible: get(xAxis, 'visible', true),
|
|
113
121
|
};
|
|
114
122
|
const { height, rotation } = getLabelSettings({
|
|
115
123
|
axis: preparedXAxis,
|
|
@@ -116,6 +116,14 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
|
|
|
116
116
|
opacity: get(d, 'opacity', 1),
|
|
117
117
|
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
118
118
|
})),
|
|
119
|
+
plotBands: get(axisItem, 'plotBands', []).map((d) => ({
|
|
120
|
+
color: get(d, 'color', 'var(--g-color-base-brand)'),
|
|
121
|
+
opacity: get(d, 'opacity', 1),
|
|
122
|
+
from: get(d, 'from', 0),
|
|
123
|
+
to: get(d, 'to', 0),
|
|
124
|
+
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
125
|
+
})),
|
|
126
|
+
visible: get(axisItem, 'visible', true),
|
|
119
127
|
};
|
|
120
128
|
if (labelsEnabled) {
|
|
121
129
|
preparedAxis.labels.width = getAxisLabelMaxWidth({ axis: preparedAxis, series });
|
|
@@ -4,35 +4,47 @@ import { getUniqId } from '../../utils';
|
|
|
4
4
|
import { DEFAULT_DATALABELS_PADDING, DEFAULT_DATALABELS_STYLE } from './constants';
|
|
5
5
|
import { prepareLegendSymbol } from './utils';
|
|
6
6
|
export function prepareWaterfallSeries(args) {
|
|
7
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
7
8
|
const { colorScale, series: seriesList, legend } = args;
|
|
8
9
|
const [, negativeColor, positiveColor] = DEFAULT_PALETTE;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
dataLabels:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
10
|
+
const series = seriesList[0];
|
|
11
|
+
const common = {
|
|
12
|
+
id: '',
|
|
13
|
+
color: seriesList[0].color || colorScale(seriesList[0].name),
|
|
14
|
+
type: series.type,
|
|
15
|
+
name: series.name,
|
|
16
|
+
visible: get(series, 'visible', true),
|
|
17
|
+
legend: {
|
|
18
|
+
enabled: get(series, 'legend.enabled', legend.enabled),
|
|
19
|
+
symbol: prepareLegendSymbol(series),
|
|
20
|
+
},
|
|
21
|
+
dataLabels: {
|
|
22
|
+
enabled: ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) || true,
|
|
23
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_b = series.dataLabels) === null || _b === void 0 ? void 0 : _b.style),
|
|
24
|
+
allowOverlap: ((_c = series.dataLabels) === null || _c === void 0 ? void 0 : _c.allowOverlap) || false,
|
|
25
|
+
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
26
|
+
html: get(series, 'dataLabels.html', false),
|
|
27
|
+
format: (_d = series.dataLabels) === null || _d === void 0 ? void 0 : _d.format,
|
|
28
|
+
},
|
|
29
|
+
cursor: get(series, 'cursor', null),
|
|
30
|
+
data: [],
|
|
31
|
+
};
|
|
32
|
+
const positive = Object.assign(Object.assign({}, common), { name: (_g = (_f = (_e = series.legend) === null || _e === void 0 ? void 0 : _e.itemText) === null || _f === void 0 ? void 0 : _f.positive) !== null && _g !== void 0 ? _g : `${series.name} ↑`, id: getUniqId(), color: series.positiveColor || positiveColor, data: [] });
|
|
33
|
+
const negative = Object.assign(Object.assign({}, common), { name: (_k = (_j = (_h = series.legend) === null || _h === void 0 ? void 0 : _h.itemText) === null || _j === void 0 ? void 0 : _j.negative) !== null && _k !== void 0 ? _k : `${series.name} ↓`, id: getUniqId(), color: series.negativeColor || negativeColor, data: [] });
|
|
34
|
+
const totals = Object.assign(Object.assign({}, common), { name: (_o = (_m = (_l = series.legend) === null || _l === void 0 ? void 0 : _l.itemText) === null || _m === void 0 ? void 0 : _m.totals) !== null && _o !== void 0 ? _o : series.name, id: getUniqId(), data: [] });
|
|
35
|
+
series.data.forEach((d, index) => {
|
|
36
|
+
var _a;
|
|
37
|
+
const value = (_a = d === null || d === void 0 ? void 0 : d.y) !== null && _a !== void 0 ? _a : 0;
|
|
38
|
+
const dataItem = Object.assign(Object.assign({}, d), { index });
|
|
39
|
+
if (d === null || d === void 0 ? void 0 : d.total) {
|
|
40
|
+
totals.data.push(dataItem);
|
|
41
|
+
}
|
|
42
|
+
else if (value > 0) {
|
|
43
|
+
positive.data.push(dataItem);
|
|
44
|
+
}
|
|
45
|
+
else if (value < 0) {
|
|
46
|
+
negative.data.push(dataItem);
|
|
47
|
+
}
|
|
37
48
|
}, []);
|
|
49
|
+
return [positive, negative, totals];
|
|
38
50
|
}
|
|
@@ -243,9 +243,12 @@ export type PreparedTreemapSeries = {
|
|
|
243
243
|
};
|
|
244
244
|
layoutAlgorithm: `${LayoutAlgorithm}`;
|
|
245
245
|
} & BasePreparedSeries & Omit<TreemapSeries, keyof BasePreparedSeries>;
|
|
246
|
+
export type PreparedWaterfallSeriesData = WaterfallSeriesData & {
|
|
247
|
+
index: number;
|
|
248
|
+
};
|
|
246
249
|
export type PreparedWaterfallSeries = {
|
|
247
250
|
type: WaterfallSeries['type'];
|
|
248
|
-
data:
|
|
251
|
+
data: PreparedWaterfallSeriesData[];
|
|
249
252
|
dataLabels: {
|
|
250
253
|
enabled: boolean;
|
|
251
254
|
style: BaseTextStyle;
|
|
@@ -254,8 +257,6 @@ export type PreparedWaterfallSeries = {
|
|
|
254
257
|
html: boolean;
|
|
255
258
|
format?: ValueFormat;
|
|
256
259
|
};
|
|
257
|
-
positiveColor: string;
|
|
258
|
-
negativeColor: string;
|
|
259
260
|
} & BasePreparedSeries;
|
|
260
261
|
export type PreparedSankeySeries = {
|
|
261
262
|
type: SankeySeries['type'];
|
|
@@ -17,6 +17,7 @@ export const HtmlLayer = (props) => {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
return (React.createElement(Portal, { container: htmlLayout }, items.map((item, index) => {
|
|
20
|
-
|
|
20
|
+
const style = Object.assign(Object.assign({}, item.style), { position: 'absolute', left: item.x, top: item.y });
|
|
21
|
+
return (React.createElement("div", { key: index, dangerouslySetInnerHTML: { __html: item.content }, style: style }));
|
|
21
22
|
})));
|
|
22
23
|
};
|
|
@@ -35,6 +35,7 @@ function getHtmlLabel(point, series, xMax) {
|
|
|
35
35
|
y: Math.max(0, point.y - series.dataLabels.padding - size.maxHeight),
|
|
36
36
|
content,
|
|
37
37
|
size: { width: size.maxWidth, height: size.maxHeight },
|
|
38
|
+
style: series.dataLabels.style,
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
export const prepareLineData = (args) => {
|
|
@@ -94,10 +94,11 @@ export function prepareTreemapData(args) {
|
|
|
94
94
|
let labelData = [];
|
|
95
95
|
const htmlElements = [];
|
|
96
96
|
if ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
97
|
-
const { html } = series.dataLabels;
|
|
97
|
+
const { html, style: dataLabelsStyle } = series.dataLabels;
|
|
98
98
|
const labels = getLabels({ data: leaves, options: series.dataLabels });
|
|
99
99
|
if (html) {
|
|
100
|
-
|
|
100
|
+
const htmlItems = labels.map((l) => (Object.assign({ style: dataLabelsStyle }, l)));
|
|
101
|
+
htmlElements.push(...htmlItems);
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
104
|
labelData = labels;
|
|
@@ -5,10 +5,12 @@ import { getFormattedValue } from '../../../utils/chart/format';
|
|
|
5
5
|
import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '../constants';
|
|
6
6
|
import { getXValue, getYValue } from '../utils';
|
|
7
7
|
function getLabelData(d, plotHeight) {
|
|
8
|
+
var _a, _b;
|
|
8
9
|
if (!d.series.dataLabels.enabled) {
|
|
9
10
|
return undefined;
|
|
10
11
|
}
|
|
11
|
-
const
|
|
12
|
+
const labelValue = (_b = (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.y) !== null && _b !== void 0 ? _b : d.subTotal;
|
|
13
|
+
const text = getFormattedValue(Object.assign({ value: labelValue }, d.series.dataLabels));
|
|
12
14
|
const style = d.series.dataLabels.style;
|
|
13
15
|
const { maxHeight: height, maxWidth: width } = getLabelsSize({ labels: [text], style });
|
|
14
16
|
let y;
|
|
@@ -60,7 +62,7 @@ export const prepareWaterfallData = (args) => {
|
|
|
60
62
|
acc.push(...s.data.map((d) => ({ data: d, series: s })));
|
|
61
63
|
return acc;
|
|
62
64
|
}, []);
|
|
63
|
-
const data = sortBy(flattenData, (d) => d.data.
|
|
65
|
+
const data = sortBy(flattenData, (d) => d.data.index);
|
|
64
66
|
const bandWidth = getBandWidth({
|
|
65
67
|
series,
|
|
66
68
|
xAxis,
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"label_invalid-series-property": "It seems you are trying to use inappropriate value for \"{{key}}\", or defined it incorrectly. Available values: [{{values}}].",
|
|
12
12
|
"label_invalid-treemap-redundant-value": "It seems you are trying to set \"value\" for container node. Check node with this properties: { id: \"{{id}}\", name: \"{{name}}\" }",
|
|
13
13
|
"label_invalid-treemap-missing-value": "It seems you are trying to use node without \"value\". Check node with this properties: { id: \"{{id}}\", name: \"{{name}}\" }",
|
|
14
|
-
"label_invalid-y-axis-index": "It seems you are trying to use inappropriate index for Y axis: \"{{index}}\""
|
|
14
|
+
"label_invalid-y-axis-index": "It seems you are trying to use inappropriate index for Y axis: \"{{index}}\"",
|
|
15
|
+
"label_invalid-axis-plot-band-option": "It seems you are trying to use inappropriate type for \"{{axis}}\" axis plot band option: \"{{option}}\"",
|
|
16
|
+
"label_axis-plot-band-options-not-equal": "It seems you are trying to use different type for \"{{axis}}\" axis plot band options"
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"label_invalid-series-property": "Похоже, что вы пытаетесь использовать недопустимое значение для \"{{key}}\", или указали его неверно. Доступные значения: [{{values}}].",
|
|
12
12
|
"label_invalid-treemap-redundant-value": "Похоже, что вы пытаетесь установить значение \"value\" для узла, используемого в качестве контейнера. Проверьте узел с этими свойствами: { id: \"{{id}}\", name: \"{{name}}\" }",
|
|
13
13
|
"label_invalid-treemap-missing-value": "Похоже, что вы пытаетесь использовать узел без значения \"value\". Проверьте узел с этими свойствами: { id: \"{{id}}\", name: \"{{name}}\" }",
|
|
14
|
-
"label_invalid-y-axis-index": "Похоже, что вы пытаетесь использовать некорректный индекс для оси Y: \"{{index}}\""
|
|
14
|
+
"label_invalid-y-axis-index": "Похоже, что вы пытаетесь использовать некорректный индекс для оси Y: \"{{index}}\"",
|
|
15
|
+
"label_invalid-axis-plot-band-option": "Похоже, что вы пытаетесь использовать некорректный тип для параметра полосы: \"{{option}}\" для оси \"{{axis}}\"",
|
|
16
|
+
"label_axis-plot-band-options-not-equal": "Похоже, что вы пытаетесь использовать разные типы для для параметра полосы для оси \"{{axis}}\""
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -2,6 +2,7 @@ export const CHART_ERROR_CODE = {
|
|
|
2
2
|
NO_DATA: 'ERR.CK.NO_DATA',
|
|
3
3
|
INVALID_DATA: 'ERR.CK.INVALID_DATA',
|
|
4
4
|
UNKNOWN: 'ERR.CK.UNKNOWN_ERROR',
|
|
5
|
+
INVALID_OPTION_TYPE: 'ERR.CK.INVALID_OPTION_TYPE',
|
|
5
6
|
};
|
|
6
7
|
export class ChartError extends Error {
|
|
7
8
|
constructor({ originalError, message, code = CHART_ERROR_CODE.UNKNOWN } = {}) {
|
|
@@ -75,10 +75,27 @@ export interface ChartAxis {
|
|
|
75
75
|
maxPadding?: number;
|
|
76
76
|
/** An array of lines stretching across the plot area, marking a specific value */
|
|
77
77
|
plotLines?: AxisPlotLine[];
|
|
78
|
+
/** An array of colored bands stretching across the plot area marking an interval on the axis. */
|
|
79
|
+
plotBands?: AxisPlotBand[];
|
|
80
|
+
/** Whether axis, including axis title, line, ticks and labels, should be visible. */
|
|
81
|
+
visible?: boolean;
|
|
78
82
|
}
|
|
79
83
|
export interface ChartXAxis extends ChartAxis {
|
|
80
84
|
}
|
|
81
|
-
export
|
|
85
|
+
export type PlotLayerPlacement = 'before' | 'after';
|
|
86
|
+
export interface AxisPlot {
|
|
87
|
+
/** Place the line behind or above the chart. */
|
|
88
|
+
layerPlacement?: PlotLayerPlacement;
|
|
89
|
+
/** The color of the plot line (hex, rgba). */
|
|
90
|
+
color?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Individual opacity for the line.
|
|
93
|
+
*
|
|
94
|
+
* @default 1
|
|
95
|
+
* */
|
|
96
|
+
opacity?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface AxisPlotLine extends AxisPlot {
|
|
82
99
|
/** The position of the line in axis units. */
|
|
83
100
|
value?: number;
|
|
84
101
|
/** The color of the plot line (hex, rgba). */
|
|
@@ -90,14 +107,22 @@ export interface AxisPlotLine {
|
|
|
90
107
|
width?: number;
|
|
91
108
|
/** Option for line stroke style. */
|
|
92
109
|
dashStyle?: `${DashStyle}`;
|
|
110
|
+
}
|
|
111
|
+
export interface AxisPlotBand extends AxisPlot {
|
|
93
112
|
/**
|
|
94
|
-
*
|
|
113
|
+
* The start position of the plot band in axis units.
|
|
95
114
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
* Can be a number, a string (e.g., a category), or a timestamp if representing a date.
|
|
116
|
+
* When representing a date, the value **must be a timestamp** (number of milliseconds since Unix epoch).
|
|
117
|
+
*/
|
|
118
|
+
from: number | string;
|
|
119
|
+
/**
|
|
120
|
+
* The end position of the plot band in axis units.
|
|
121
|
+
*
|
|
122
|
+
* Can be a number, a string (e.g., a category), or a timestamp if representing a date.
|
|
123
|
+
* When representing a date, the value **must be a timestamp** (number of milliseconds since Unix epoch).
|
|
124
|
+
*/
|
|
125
|
+
to: number | string;
|
|
101
126
|
}
|
|
102
127
|
export interface ChartYAxis extends ChartAxis {
|
|
103
128
|
/** Axis location.
|
|
@@ -36,5 +36,14 @@ export interface WaterfallSeries<T = MeaningfulAny> extends BaseSeries {
|
|
|
36
36
|
/** Individual series legend options. Has higher priority than legend options in widget data. */
|
|
37
37
|
legend?: ChartLegend & {
|
|
38
38
|
symbol?: RectLegendSymbolOptions;
|
|
39
|
+
/** The legend item text for positive, negative values and totals. */
|
|
40
|
+
itemText?: {
|
|
41
|
+
/** The legend item text for positive values. */
|
|
42
|
+
positive?: string;
|
|
43
|
+
/** The legend item text for negative values. */
|
|
44
|
+
negative?: string;
|
|
45
|
+
/** The legend item text for totals. */
|
|
46
|
+
totals?: string;
|
|
47
|
+
};
|
|
39
48
|
};
|
|
40
49
|
}
|
|
@@ -16,7 +16,7 @@ function addDomain(selection, options) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
export function axisBottom(args) {
|
|
19
|
-
const { scale, ticks: { labelFormat = (value) => String(value), labelsPaddings = 0, labelsMargin = 0, labelsMaxWidth = Infinity, labelsStyle, labelsLineHeight, items: tickItems, count: ticksCount, maxTickCount, rotation = 0, tickColor, }, domain, } = args;
|
|
19
|
+
const { leftmostLimit = 0, scale, ticks: { labelFormat = (value) => String(value), labelsPaddings = 0, labelsMargin = 0, labelsMaxWidth = Infinity, labelsStyle, labelsLineHeight, items: tickItems, count: ticksCount, maxTickCount, rotation = 0, tickColor, }, domain, } = args;
|
|
20
20
|
const offset = getXAxisOffset();
|
|
21
21
|
const position = getXTickPosition({ scale, offset });
|
|
22
22
|
const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
|
|
@@ -103,6 +103,21 @@ export function axisBottom(args) {
|
|
|
103
103
|
.remove();
|
|
104
104
|
// add an ellipsis to the labels that go beyond the boundaries of the chart
|
|
105
105
|
labels.each(function (_d, i, nodes) {
|
|
106
|
+
if (i === 0) {
|
|
107
|
+
const currentElement = this;
|
|
108
|
+
const text = select(currentElement);
|
|
109
|
+
const currentElementPosition = currentElement.getBoundingClientRect();
|
|
110
|
+
const nextElement = nodes[i + 1];
|
|
111
|
+
const nextElementPosition = nextElement === null || nextElement === void 0 ? void 0 : nextElement.getBoundingClientRect();
|
|
112
|
+
if (currentElementPosition.left < leftmostLimit) {
|
|
113
|
+
const remainSpace = nextElementPosition.left -
|
|
114
|
+
currentElementPosition.right +
|
|
115
|
+
x -
|
|
116
|
+
labelsMargin;
|
|
117
|
+
text.attr('text-anchor', 'start');
|
|
118
|
+
setEllipsisForOverflowText(text, remainSpace);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
106
121
|
if (i === nodes.length - 1) {
|
|
107
122
|
const currentElement = this;
|
|
108
123
|
const prevElement = nodes[i - 1];
|