@gravity-ui/charts 1.13.0 → 1.13.1
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/constants/defaults/series-options.d.ts +3 -1
- package/dist/cjs/constants/defaults/series-options.js +2 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +9 -3
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +24 -17
- package/dist/cjs/types/chart/series.d.ts +10 -0
- package/dist/esm/constants/defaults/series-options.d.ts +3 -1
- package/dist/esm/constants/defaults/series-options.js +2 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +9 -3
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +24 -17
- package/dist/esm/types/chart/series.d.ts +10 -0
- package/package.json +1 -1
|
@@ -4,13 +4,15 @@ type DefaultBarXSeriesOptions = Partial<ChartSeriesOptions['bar-x']> & {
|
|
|
4
4
|
barMaxWidth: number;
|
|
5
5
|
barPadding: number;
|
|
6
6
|
groupPadding: number;
|
|
7
|
+
stackGap: number;
|
|
7
8
|
};
|
|
8
9
|
};
|
|
9
|
-
type DefaultBarYSeriesOptions = Partial<ChartSeriesOptions['bar-
|
|
10
|
+
type DefaultBarYSeriesOptions = Partial<ChartSeriesOptions['bar-y']> & {
|
|
10
11
|
'bar-y': {
|
|
11
12
|
barMaxWidth: number;
|
|
12
13
|
barPadding: number;
|
|
13
14
|
groupPadding: number;
|
|
15
|
+
stackGap: number;
|
|
14
16
|
};
|
|
15
17
|
};
|
|
16
18
|
type DefaultWaterfallSeriesOptions = Partial<ChartSeriesOptions['waterfall']> & {
|
|
@@ -3,6 +3,7 @@ export const seriesOptionsDefaults = {
|
|
|
3
3
|
barMaxWidth: 50,
|
|
4
4
|
barPadding: 0.1,
|
|
5
5
|
groupPadding: 0.2,
|
|
6
|
+
stackGap: 1,
|
|
6
7
|
states: {
|
|
7
8
|
hover: {
|
|
8
9
|
enabled: true,
|
|
@@ -18,6 +19,7 @@ export const seriesOptionsDefaults = {
|
|
|
18
19
|
barMaxWidth: 50,
|
|
19
20
|
barPadding: 0.1,
|
|
20
21
|
groupPadding: 0.2,
|
|
22
|
+
stackGap: 1,
|
|
21
23
|
states: {
|
|
22
24
|
hover: {
|
|
23
25
|
enabled: true,
|
|
@@ -32,6 +32,7 @@ async function getLabelData(d) {
|
|
|
32
32
|
}
|
|
33
33
|
export const prepareBarXData = async (args) => {
|
|
34
34
|
const { series, seriesOptions, xAxis, xScale, yScale, boundsHeight: plotHeight } = args;
|
|
35
|
+
const stackGap = seriesOptions['bar-x'].stackGap;
|
|
35
36
|
const categories = get(xAxis, 'categories', []);
|
|
36
37
|
const barMaxWidth = get(seriesOptions, 'bar-x.barMaxWidth');
|
|
37
38
|
const barPadding = get(seriesOptions, 'bar-x.barPadding');
|
|
@@ -124,7 +125,12 @@ export const prepareBarXData = async (args) => {
|
|
|
124
125
|
const yDataValue = yValue.data.y;
|
|
125
126
|
const y = seriesYScale(yDataValue);
|
|
126
127
|
const base = seriesYScale(0);
|
|
128
|
+
const isLastStackItem = yValueIndex === sortedData.length - 1;
|
|
127
129
|
const height = yDataValue > 0 ? base - y : y - base;
|
|
130
|
+
let shapeHeight = height - (stackItems.length ? stackGap : 0);
|
|
131
|
+
if (shapeHeight < 0) {
|
|
132
|
+
shapeHeight = height;
|
|
133
|
+
}
|
|
128
134
|
if (height <= 0) {
|
|
129
135
|
continue;
|
|
130
136
|
}
|
|
@@ -132,12 +138,12 @@ export const prepareBarXData = async (args) => {
|
|
|
132
138
|
x,
|
|
133
139
|
y: yDataValue > 0 ? y - stackHeight : seriesYScale(0),
|
|
134
140
|
width: rectWidth,
|
|
135
|
-
height,
|
|
141
|
+
height: shapeHeight,
|
|
136
142
|
opacity: get(yValue.data, 'opacity', null),
|
|
137
143
|
data: yValue.data,
|
|
138
144
|
series: yValue.series,
|
|
139
145
|
htmlElements: [],
|
|
140
|
-
isLastStackItem
|
|
146
|
+
isLastStackItem,
|
|
141
147
|
};
|
|
142
148
|
const label = await getLabelData(barData);
|
|
143
149
|
if (yValue.series.dataLabels.html && label) {
|
|
@@ -153,7 +159,7 @@ export const prepareBarXData = async (args) => {
|
|
|
153
159
|
barData.label = await getLabelData(barData);
|
|
154
160
|
}
|
|
155
161
|
stackItems.push(barData);
|
|
156
|
-
stackHeight += height
|
|
162
|
+
stackHeight += height;
|
|
157
163
|
}
|
|
158
164
|
if (series.some((s) => s.stacking === 'percent')) {
|
|
159
165
|
let acc = 0;
|
|
@@ -7,10 +7,10 @@ const DEFAULT_LABEL_PADDING = 7;
|
|
|
7
7
|
export const prepareBarYData = async (args) => {
|
|
8
8
|
var _a;
|
|
9
9
|
const { series, seriesOptions, yAxis, xScale, yScale: [yScale], } = args;
|
|
10
|
+
const stackGap = seriesOptions['bar-y'].stackGap;
|
|
10
11
|
const xLinearScale = xScale;
|
|
11
12
|
const yLinearScale = yScale;
|
|
12
13
|
const plotHeight = yLinearScale(yLinearScale.domain()[0]);
|
|
13
|
-
const plotWidth = xLinearScale(xLinearScale.domain()[1]);
|
|
14
14
|
const sortingOptions = get(seriesOptions, 'bar-y.dataSorting');
|
|
15
15
|
const comparator = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.direction) === 'desc' ? descending : ascending;
|
|
16
16
|
const sortKey = (() => {
|
|
@@ -46,6 +46,16 @@ export const prepareBarYData = async (args) => {
|
|
|
46
46
|
const sortedData = sortKey
|
|
47
47
|
? sort(measureValues, (a, b) => comparator(get(a, sortKey), get(b, sortKey)))
|
|
48
48
|
: measureValues;
|
|
49
|
+
let ratio = 1;
|
|
50
|
+
if (series.some((s) => s.stacking === 'percent')) {
|
|
51
|
+
const sum = sortedData.reduce((acc, item) => {
|
|
52
|
+
if (item.data.x) {
|
|
53
|
+
return acc + xLinearScale(Number(item.data.x));
|
|
54
|
+
}
|
|
55
|
+
return acc;
|
|
56
|
+
}, 0);
|
|
57
|
+
ratio = xLinearScale.range()[1] / sum;
|
|
58
|
+
}
|
|
49
59
|
sortedData.forEach(({ data, series: s }, xValueIndex) => {
|
|
50
60
|
let center;
|
|
51
61
|
if (yAxis[0].type === 'category') {
|
|
@@ -58,14 +68,20 @@ export const prepareBarYData = async (args) => {
|
|
|
58
68
|
}
|
|
59
69
|
const y = center - currentBarHeight / 2 + (barSize + barGap) * groupItemIndex;
|
|
60
70
|
const xValue = Number(data.x);
|
|
61
|
-
const
|
|
62
|
-
|
|
71
|
+
const isLastStackItem = xValueIndex === sortedData.length - 1;
|
|
72
|
+
const width = Math.abs(xLinearScale(xValue) * ratio - base);
|
|
73
|
+
let shapeWidth = width - (stackItems.length ? stackGap : 0);
|
|
74
|
+
if (shapeWidth < 0) {
|
|
75
|
+
shapeWidth = width;
|
|
76
|
+
}
|
|
77
|
+
if (shapeWidth <= 0) {
|
|
63
78
|
return;
|
|
64
79
|
}
|
|
80
|
+
const itemStackGap = width - shapeWidth;
|
|
65
81
|
const item = {
|
|
66
|
-
x: xValue > baseRangeValue ? stackSum : stackSum - width,
|
|
67
|
-
y,
|
|
68
|
-
width,
|
|
82
|
+
x: (xValue > baseRangeValue ? stackSum : stackSum - width) + itemStackGap,
|
|
83
|
+
y: y,
|
|
84
|
+
width: shapeWidth,
|
|
69
85
|
height: barSize,
|
|
70
86
|
color: data.color || s.color,
|
|
71
87
|
borderColor: s.borderColor,
|
|
@@ -73,20 +89,11 @@ export const prepareBarYData = async (args) => {
|
|
|
73
89
|
opacity: get(data, 'opacity', null),
|
|
74
90
|
data,
|
|
75
91
|
series: s,
|
|
76
|
-
isLastStackItem
|
|
92
|
+
isLastStackItem,
|
|
77
93
|
};
|
|
78
94
|
stackItems.push(item);
|
|
79
|
-
stackSum += width
|
|
95
|
+
stackSum += width;
|
|
80
96
|
});
|
|
81
|
-
if (series.some((s) => s.stacking === 'percent')) {
|
|
82
|
-
let acc = 0;
|
|
83
|
-
const ratio = plotWidth / (stackSum - stackItems.length);
|
|
84
|
-
stackItems.forEach((item) => {
|
|
85
|
-
item.width = item.width * ratio;
|
|
86
|
-
item.x = acc;
|
|
87
|
-
acc += item.width;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
97
|
result.push(...stackItems);
|
|
91
98
|
});
|
|
92
99
|
});
|
|
@@ -79,6 +79,11 @@ export interface ChartSeriesOptions {
|
|
|
79
79
|
* @default 0
|
|
80
80
|
*/
|
|
81
81
|
borderRadius?: number;
|
|
82
|
+
/**
|
|
83
|
+
* The distance between the shapes of the stacked values, in pixels.
|
|
84
|
+
* @default 1
|
|
85
|
+
*/
|
|
86
|
+
stackGap?: number;
|
|
82
87
|
dataSorting?: {
|
|
83
88
|
/** Determines what data value should be used to sort by.
|
|
84
89
|
* Possible values are undefined to disable, "name" to sort by series name or "y"
|
|
@@ -130,6 +135,11 @@ export interface ChartSeriesOptions {
|
|
|
130
135
|
* @default 0
|
|
131
136
|
*/
|
|
132
137
|
borderRadius?: number;
|
|
138
|
+
/**
|
|
139
|
+
* The distance between the shapes of the stacked values, in pixels.
|
|
140
|
+
* @default 1
|
|
141
|
+
*/
|
|
142
|
+
stackGap?: number;
|
|
133
143
|
dataSorting?: {
|
|
134
144
|
/** Determines what data value should be used to sort by.
|
|
135
145
|
* Possible values are undefined to disable, "name" to sort by series name or "x"
|
|
@@ -4,13 +4,15 @@ type DefaultBarXSeriesOptions = Partial<ChartSeriesOptions['bar-x']> & {
|
|
|
4
4
|
barMaxWidth: number;
|
|
5
5
|
barPadding: number;
|
|
6
6
|
groupPadding: number;
|
|
7
|
+
stackGap: number;
|
|
7
8
|
};
|
|
8
9
|
};
|
|
9
|
-
type DefaultBarYSeriesOptions = Partial<ChartSeriesOptions['bar-
|
|
10
|
+
type DefaultBarYSeriesOptions = Partial<ChartSeriesOptions['bar-y']> & {
|
|
10
11
|
'bar-y': {
|
|
11
12
|
barMaxWidth: number;
|
|
12
13
|
barPadding: number;
|
|
13
14
|
groupPadding: number;
|
|
15
|
+
stackGap: number;
|
|
14
16
|
};
|
|
15
17
|
};
|
|
16
18
|
type DefaultWaterfallSeriesOptions = Partial<ChartSeriesOptions['waterfall']> & {
|
|
@@ -3,6 +3,7 @@ export const seriesOptionsDefaults = {
|
|
|
3
3
|
barMaxWidth: 50,
|
|
4
4
|
barPadding: 0.1,
|
|
5
5
|
groupPadding: 0.2,
|
|
6
|
+
stackGap: 1,
|
|
6
7
|
states: {
|
|
7
8
|
hover: {
|
|
8
9
|
enabled: true,
|
|
@@ -18,6 +19,7 @@ export const seriesOptionsDefaults = {
|
|
|
18
19
|
barMaxWidth: 50,
|
|
19
20
|
barPadding: 0.1,
|
|
20
21
|
groupPadding: 0.2,
|
|
22
|
+
stackGap: 1,
|
|
21
23
|
states: {
|
|
22
24
|
hover: {
|
|
23
25
|
enabled: true,
|
|
@@ -32,6 +32,7 @@ async function getLabelData(d) {
|
|
|
32
32
|
}
|
|
33
33
|
export const prepareBarXData = async (args) => {
|
|
34
34
|
const { series, seriesOptions, xAxis, xScale, yScale, boundsHeight: plotHeight } = args;
|
|
35
|
+
const stackGap = seriesOptions['bar-x'].stackGap;
|
|
35
36
|
const categories = get(xAxis, 'categories', []);
|
|
36
37
|
const barMaxWidth = get(seriesOptions, 'bar-x.barMaxWidth');
|
|
37
38
|
const barPadding = get(seriesOptions, 'bar-x.barPadding');
|
|
@@ -124,7 +125,12 @@ export const prepareBarXData = async (args) => {
|
|
|
124
125
|
const yDataValue = yValue.data.y;
|
|
125
126
|
const y = seriesYScale(yDataValue);
|
|
126
127
|
const base = seriesYScale(0);
|
|
128
|
+
const isLastStackItem = yValueIndex === sortedData.length - 1;
|
|
127
129
|
const height = yDataValue > 0 ? base - y : y - base;
|
|
130
|
+
let shapeHeight = height - (stackItems.length ? stackGap : 0);
|
|
131
|
+
if (shapeHeight < 0) {
|
|
132
|
+
shapeHeight = height;
|
|
133
|
+
}
|
|
128
134
|
if (height <= 0) {
|
|
129
135
|
continue;
|
|
130
136
|
}
|
|
@@ -132,12 +138,12 @@ export const prepareBarXData = async (args) => {
|
|
|
132
138
|
x,
|
|
133
139
|
y: yDataValue > 0 ? y - stackHeight : seriesYScale(0),
|
|
134
140
|
width: rectWidth,
|
|
135
|
-
height,
|
|
141
|
+
height: shapeHeight,
|
|
136
142
|
opacity: get(yValue.data, 'opacity', null),
|
|
137
143
|
data: yValue.data,
|
|
138
144
|
series: yValue.series,
|
|
139
145
|
htmlElements: [],
|
|
140
|
-
isLastStackItem
|
|
146
|
+
isLastStackItem,
|
|
141
147
|
};
|
|
142
148
|
const label = await getLabelData(barData);
|
|
143
149
|
if (yValue.series.dataLabels.html && label) {
|
|
@@ -153,7 +159,7 @@ export const prepareBarXData = async (args) => {
|
|
|
153
159
|
barData.label = await getLabelData(barData);
|
|
154
160
|
}
|
|
155
161
|
stackItems.push(barData);
|
|
156
|
-
stackHeight += height
|
|
162
|
+
stackHeight += height;
|
|
157
163
|
}
|
|
158
164
|
if (series.some((s) => s.stacking === 'percent')) {
|
|
159
165
|
let acc = 0;
|
|
@@ -7,10 +7,10 @@ const DEFAULT_LABEL_PADDING = 7;
|
|
|
7
7
|
export const prepareBarYData = async (args) => {
|
|
8
8
|
var _a;
|
|
9
9
|
const { series, seriesOptions, yAxis, xScale, yScale: [yScale], } = args;
|
|
10
|
+
const stackGap = seriesOptions['bar-y'].stackGap;
|
|
10
11
|
const xLinearScale = xScale;
|
|
11
12
|
const yLinearScale = yScale;
|
|
12
13
|
const plotHeight = yLinearScale(yLinearScale.domain()[0]);
|
|
13
|
-
const plotWidth = xLinearScale(xLinearScale.domain()[1]);
|
|
14
14
|
const sortingOptions = get(seriesOptions, 'bar-y.dataSorting');
|
|
15
15
|
const comparator = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.direction) === 'desc' ? descending : ascending;
|
|
16
16
|
const sortKey = (() => {
|
|
@@ -46,6 +46,16 @@ export const prepareBarYData = async (args) => {
|
|
|
46
46
|
const sortedData = sortKey
|
|
47
47
|
? sort(measureValues, (a, b) => comparator(get(a, sortKey), get(b, sortKey)))
|
|
48
48
|
: measureValues;
|
|
49
|
+
let ratio = 1;
|
|
50
|
+
if (series.some((s) => s.stacking === 'percent')) {
|
|
51
|
+
const sum = sortedData.reduce((acc, item) => {
|
|
52
|
+
if (item.data.x) {
|
|
53
|
+
return acc + xLinearScale(Number(item.data.x));
|
|
54
|
+
}
|
|
55
|
+
return acc;
|
|
56
|
+
}, 0);
|
|
57
|
+
ratio = xLinearScale.range()[1] / sum;
|
|
58
|
+
}
|
|
49
59
|
sortedData.forEach(({ data, series: s }, xValueIndex) => {
|
|
50
60
|
let center;
|
|
51
61
|
if (yAxis[0].type === 'category') {
|
|
@@ -58,14 +68,20 @@ export const prepareBarYData = async (args) => {
|
|
|
58
68
|
}
|
|
59
69
|
const y = center - currentBarHeight / 2 + (barSize + barGap) * groupItemIndex;
|
|
60
70
|
const xValue = Number(data.x);
|
|
61
|
-
const
|
|
62
|
-
|
|
71
|
+
const isLastStackItem = xValueIndex === sortedData.length - 1;
|
|
72
|
+
const width = Math.abs(xLinearScale(xValue) * ratio - base);
|
|
73
|
+
let shapeWidth = width - (stackItems.length ? stackGap : 0);
|
|
74
|
+
if (shapeWidth < 0) {
|
|
75
|
+
shapeWidth = width;
|
|
76
|
+
}
|
|
77
|
+
if (shapeWidth <= 0) {
|
|
63
78
|
return;
|
|
64
79
|
}
|
|
80
|
+
const itemStackGap = width - shapeWidth;
|
|
65
81
|
const item = {
|
|
66
|
-
x: xValue > baseRangeValue ? stackSum : stackSum - width,
|
|
67
|
-
y,
|
|
68
|
-
width,
|
|
82
|
+
x: (xValue > baseRangeValue ? stackSum : stackSum - width) + itemStackGap,
|
|
83
|
+
y: y,
|
|
84
|
+
width: shapeWidth,
|
|
69
85
|
height: barSize,
|
|
70
86
|
color: data.color || s.color,
|
|
71
87
|
borderColor: s.borderColor,
|
|
@@ -73,20 +89,11 @@ export const prepareBarYData = async (args) => {
|
|
|
73
89
|
opacity: get(data, 'opacity', null),
|
|
74
90
|
data,
|
|
75
91
|
series: s,
|
|
76
|
-
isLastStackItem
|
|
92
|
+
isLastStackItem,
|
|
77
93
|
};
|
|
78
94
|
stackItems.push(item);
|
|
79
|
-
stackSum += width
|
|
95
|
+
stackSum += width;
|
|
80
96
|
});
|
|
81
|
-
if (series.some((s) => s.stacking === 'percent')) {
|
|
82
|
-
let acc = 0;
|
|
83
|
-
const ratio = plotWidth / (stackSum - stackItems.length);
|
|
84
|
-
stackItems.forEach((item) => {
|
|
85
|
-
item.width = item.width * ratio;
|
|
86
|
-
item.x = acc;
|
|
87
|
-
acc += item.width;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
97
|
result.push(...stackItems);
|
|
91
98
|
});
|
|
92
99
|
});
|
|
@@ -79,6 +79,11 @@ export interface ChartSeriesOptions {
|
|
|
79
79
|
* @default 0
|
|
80
80
|
*/
|
|
81
81
|
borderRadius?: number;
|
|
82
|
+
/**
|
|
83
|
+
* The distance between the shapes of the stacked values, in pixels.
|
|
84
|
+
* @default 1
|
|
85
|
+
*/
|
|
86
|
+
stackGap?: number;
|
|
82
87
|
dataSorting?: {
|
|
83
88
|
/** Determines what data value should be used to sort by.
|
|
84
89
|
* Possible values are undefined to disable, "name" to sort by series name or "y"
|
|
@@ -130,6 +135,11 @@ export interface ChartSeriesOptions {
|
|
|
130
135
|
* @default 0
|
|
131
136
|
*/
|
|
132
137
|
borderRadius?: number;
|
|
138
|
+
/**
|
|
139
|
+
* The distance between the shapes of the stacked values, in pixels.
|
|
140
|
+
* @default 1
|
|
141
|
+
*/
|
|
142
|
+
stackGap?: number;
|
|
133
143
|
dataSorting?: {
|
|
134
144
|
/** Determines what data value should be used to sort by.
|
|
135
145
|
* Possible values are undefined to disable, "name" to sort by series name or "x"
|