@gravity-ui/charts 1.24.0 → 1.24.2
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 +2 -1
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +1 -2
- package/dist/cjs/hooks/useAxisScales/index.d.ts +4 -4
- package/dist/cjs/hooks/useAxisScales/index.js +95 -39
- package/dist/cjs/hooks/useAxisScales/utils.d.ts +19 -0
- package/dist/cjs/hooks/useAxisScales/utils.js +34 -0
- package/dist/cjs/hooks/useRangeSlider/index.js +2 -1
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +159 -158
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +87 -72
- package/dist/cjs/hooks/useShapes/index.js +2 -0
- package/dist/cjs/hooks/useShapes/line/prepare-data.js +1 -1
- package/dist/cjs/hooks/useShapes/styles.css +5 -13
- package/dist/cjs/utils/chart/index.js +1 -1
- package/dist/esm/components/ChartInner/index.js +2 -1
- package/dist/esm/components/ChartInner/useChartInnerProps.js +1 -2
- package/dist/esm/hooks/useAxisScales/index.d.ts +4 -4
- package/dist/esm/hooks/useAxisScales/index.js +95 -39
- package/dist/esm/hooks/useAxisScales/utils.d.ts +19 -0
- package/dist/esm/hooks/useAxisScales/utils.js +34 -0
- package/dist/esm/hooks/useRangeSlider/index.js +2 -1
- package/dist/esm/hooks/useRangeSlider/types.d.ts +2 -0
- package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +2 -0
- package/dist/esm/hooks/useShapes/area/prepare-data.js +159 -158
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.d.ts +2 -0
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +87 -72
- package/dist/esm/hooks/useShapes/index.js +2 -0
- package/dist/esm/hooks/useShapes/line/prepare-data.js +1 -1
- package/dist/esm/hooks/useShapes/styles.css +5 -13
- package/dist/esm/utils/chart/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,33 +1,7 @@
|
|
|
1
1
|
import { group } from 'd3';
|
|
2
|
-
import { getDataCategoryValue, getLabelsSize,
|
|
2
|
+
import { getDataCategoryValue, getLabelsSize, getTextSizeFn } from '../../../utils';
|
|
3
3
|
import { getFormattedValue } from '../../../utils/chart/format';
|
|
4
4
|
import { getXValue, getYValue } from '../utils';
|
|
5
|
-
async function getLabelData(point, series, xMax) {
|
|
6
|
-
const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, series.dataLabels));
|
|
7
|
-
const style = series.dataLabels.style;
|
|
8
|
-
const size = await getLabelsSize({ labels: [text], style, html: series.dataLabels.html });
|
|
9
|
-
const labelData = {
|
|
10
|
-
text,
|
|
11
|
-
x: point.x,
|
|
12
|
-
y: point.y - series.dataLabels.padding,
|
|
13
|
-
style,
|
|
14
|
-
size: { width: size.maxWidth, height: size.maxHeight },
|
|
15
|
-
textAnchor: 'middle',
|
|
16
|
-
series: series,
|
|
17
|
-
active: true,
|
|
18
|
-
};
|
|
19
|
-
const left = getLeftPosition(labelData);
|
|
20
|
-
if (left < 0) {
|
|
21
|
-
labelData.x = labelData.x + Math.abs(left);
|
|
22
|
-
}
|
|
23
|
-
else {
|
|
24
|
-
const right = left + labelData.size.width;
|
|
25
|
-
if (right > xMax) {
|
|
26
|
-
labelData.x = labelData.x - (right - xMax);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return labelData;
|
|
30
|
-
}
|
|
31
5
|
function getXValues(series, xAxis, xScale) {
|
|
32
6
|
const categories = xAxis.categories || [];
|
|
33
7
|
const xValues = series.reduce((acc, s) => {
|
|
@@ -53,148 +27,175 @@ function getXValues(series, xAxis, xScale) {
|
|
|
53
27
|
}
|
|
54
28
|
return Array.from(xValues);
|
|
55
29
|
}
|
|
30
|
+
async function prepareDataLabels({ series, points, xMax, yAxisTop, }) {
|
|
31
|
+
const svgLabels = [];
|
|
32
|
+
const htmlLabels = [];
|
|
33
|
+
const getTextSize = getTextSizeFn({ style: series.dataLabels.style });
|
|
34
|
+
for (let pointsIndex = 0; pointsIndex < points.length; pointsIndex++) {
|
|
35
|
+
const point = points[pointsIndex];
|
|
36
|
+
if (point.y === null) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const text = getFormattedValue(Object.assign({ value: point.data.label || point.data.y }, series.dataLabels));
|
|
40
|
+
if (series.dataLabels.html) {
|
|
41
|
+
const size = await getLabelsSize({
|
|
42
|
+
labels: [text],
|
|
43
|
+
style: series.dataLabels.style,
|
|
44
|
+
html: series.dataLabels.html,
|
|
45
|
+
});
|
|
46
|
+
const labelSize = { width: size.maxWidth, height: size.maxHeight };
|
|
47
|
+
const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
|
|
48
|
+
const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height);
|
|
49
|
+
htmlLabels.push({
|
|
50
|
+
x,
|
|
51
|
+
y,
|
|
52
|
+
content: text,
|
|
53
|
+
size: labelSize,
|
|
54
|
+
style: series.dataLabels.style,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
const labelSize = await getTextSize(text);
|
|
59
|
+
const x = Math.min(xMax - labelSize.width, Math.max(0, point.x - labelSize.width / 2));
|
|
60
|
+
const y = Math.max(yAxisTop, point.y - series.dataLabels.padding - labelSize.height);
|
|
61
|
+
svgLabels.push({
|
|
62
|
+
text,
|
|
63
|
+
x,
|
|
64
|
+
y,
|
|
65
|
+
style: series.dataLabels.style,
|
|
66
|
+
size: labelSize,
|
|
67
|
+
textAnchor: 'start',
|
|
68
|
+
series,
|
|
69
|
+
active: true,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return { svgLabels, htmlLabels };
|
|
74
|
+
}
|
|
56
75
|
export const prepareAreaData = async (args) => {
|
|
57
|
-
var _a;
|
|
58
|
-
const { series, xAxis, xScale, yAxis, yScale, boundsHeight: plotHeight, isOutsideBounds } = args;
|
|
76
|
+
var _a, _b;
|
|
77
|
+
const { series, xAxis, xScale, yAxis, yScale, boundsHeight: plotHeight, split, isOutsideBounds, } = args;
|
|
59
78
|
const [_xMin, xRangeMax] = xScale.range();
|
|
60
|
-
const xMax = xRangeMax
|
|
79
|
+
const xMax = xRangeMax;
|
|
61
80
|
const result = [];
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
yAxis
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
? getDataCategoryValue({
|
|
88
|
-
axisDirection: 'x',
|
|
89
|
-
categories: xAxis.categories || [],
|
|
90
|
-
data: d,
|
|
91
|
-
})
|
|
92
|
-
: d.x);
|
|
93
|
-
return m.set(key, d);
|
|
94
|
-
}, new Map());
|
|
95
|
-
const points = xValues.reduce((pointsAcc, [x, xValue]) => {
|
|
96
|
-
var _a;
|
|
97
|
-
const accumulatedYValue = accumulatedYValues.get(x) || 0;
|
|
98
|
-
const d = (_a = seriesData.get(x)) !== null && _a !== void 0 ? _a : {
|
|
99
|
-
x,
|
|
100
|
-
y: 0,
|
|
101
|
-
};
|
|
102
|
-
const yValue = getYValue({ point: d, yAxis: seriesYAxis, yScale: seriesYScale });
|
|
103
|
-
const yPointValue = yValue === null ? null : yValue - accumulatedYValue;
|
|
104
|
-
if (yPointValue !== null) {
|
|
105
|
-
accumulatedYValues.set(x, yMin - yPointValue);
|
|
81
|
+
const dataByPlots = Array.from(group(series, (s) => {
|
|
82
|
+
const yAxisIndex = s.yAxis;
|
|
83
|
+
const seriesYAxis = yAxis[yAxisIndex];
|
|
84
|
+
const plotIndex = seriesYAxis.plotIndex;
|
|
85
|
+
return plotIndex;
|
|
86
|
+
}, (s) => s.stackId));
|
|
87
|
+
const plotIndexes = Object.keys(dataByPlots);
|
|
88
|
+
for (let plotDataIndex = 0; plotDataIndex < plotIndexes.length; plotDataIndex++) {
|
|
89
|
+
const [plotIndex, stackItems] = dataByPlots[plotDataIndex];
|
|
90
|
+
const list = Array.from(stackItems);
|
|
91
|
+
for (let i = 0; i < list.length; i++) {
|
|
92
|
+
const [_stackId, seriesStack] = list[i];
|
|
93
|
+
const xValues = getXValues(seriesStack, xAxis, xScale);
|
|
94
|
+
const accumulatedYValues = new Map();
|
|
95
|
+
xValues.forEach(([key]) => {
|
|
96
|
+
accumulatedYValues.set(key, 0);
|
|
97
|
+
});
|
|
98
|
+
const seriesStackData = [];
|
|
99
|
+
for (let j = 0; j < seriesStack.length; j++) {
|
|
100
|
+
const s = seriesStack[j];
|
|
101
|
+
const yAxisIndex = s.yAxis;
|
|
102
|
+
const seriesYAxis = yAxis[yAxisIndex];
|
|
103
|
+
const seriesYScale = yScale[yAxisIndex];
|
|
104
|
+
if (!seriesYScale) {
|
|
105
|
+
continue;
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
107
|
+
const yAxisTop = ((_a = split.plots[plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
|
|
108
|
+
const yMin = (_b = getYValue({
|
|
109
|
+
point: { y: 0 },
|
|
110
|
+
points: s.data,
|
|
111
|
+
yAxis: seriesYAxis,
|
|
112
|
+
yScale: seriesYScale,
|
|
113
|
+
})) !== null && _b !== void 0 ? _b : 0;
|
|
114
|
+
const seriesData = s.data.reduce((m, d) => {
|
|
115
|
+
const key = String(xAxis.type === 'category'
|
|
116
|
+
? getDataCategoryValue({
|
|
117
|
+
axisDirection: 'x',
|
|
118
|
+
categories: xAxis.categories || [],
|
|
119
|
+
data: d,
|
|
120
|
+
})
|
|
121
|
+
: d.x);
|
|
122
|
+
return m.set(key, d);
|
|
123
|
+
}, new Map());
|
|
124
|
+
const points = xValues.reduce((pointsAcc, [x, xValue]) => {
|
|
125
|
+
var _a;
|
|
126
|
+
const accumulatedYValue = accumulatedYValues.get(x) || 0;
|
|
127
|
+
const d = (_a = seriesData.get(x)) !== null && _a !== void 0 ? _a : {
|
|
128
|
+
x,
|
|
129
|
+
y: 0,
|
|
130
|
+
};
|
|
131
|
+
const yValue = getYValue({ point: d, yAxis: seriesYAxis, yScale: seriesYScale });
|
|
132
|
+
const yPointValue = yValue === null ? null : yValue - accumulatedYValue;
|
|
133
|
+
if (yPointValue !== null) {
|
|
134
|
+
accumulatedYValues.set(x, yMin - yPointValue);
|
|
122
135
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
content: l.text,
|
|
139
|
-
size: {
|
|
140
|
-
width: labelSize.maxWidth,
|
|
141
|
-
height: labelSize.maxHeight,
|
|
142
|
-
},
|
|
143
|
-
style,
|
|
144
|
-
};
|
|
145
|
-
}));
|
|
146
|
-
htmlElements.push(...htmlLabels);
|
|
136
|
+
pointsAcc.push({
|
|
137
|
+
y0: yAxisTop + yMin - accumulatedYValue,
|
|
138
|
+
x: xValue,
|
|
139
|
+
y: yPointValue === null ? null : yAxisTop + (yPointValue !== null && yPointValue !== void 0 ? yPointValue : 0),
|
|
140
|
+
data: d,
|
|
141
|
+
series: s,
|
|
142
|
+
});
|
|
143
|
+
return pointsAcc;
|
|
144
|
+
}, []);
|
|
145
|
+
const labels = [];
|
|
146
|
+
const htmlElements = [];
|
|
147
|
+
if (s.dataLabels.enabled) {
|
|
148
|
+
const labelsData = await prepareDataLabels({ series: s, points, xMax, yAxisTop });
|
|
149
|
+
labels.push(...labelsData.svgLabels);
|
|
150
|
+
htmlElements.push(...labelsData.htmlLabels);
|
|
147
151
|
}
|
|
148
|
-
|
|
149
|
-
|
|
152
|
+
let markers = [];
|
|
153
|
+
if (s.marker.states.normal.enabled || s.marker.states.hover.enabled) {
|
|
154
|
+
markers = points.reduce((markersAcc, p) => {
|
|
155
|
+
if (p.y === null) {
|
|
156
|
+
return markersAcc;
|
|
157
|
+
}
|
|
158
|
+
markersAcc.push({
|
|
159
|
+
point: p,
|
|
160
|
+
active: true,
|
|
161
|
+
hovered: false,
|
|
162
|
+
clipped: isOutsideBounds(p.x, p.y),
|
|
163
|
+
});
|
|
164
|
+
return markersAcc;
|
|
165
|
+
}, []);
|
|
150
166
|
}
|
|
167
|
+
seriesStackData.push({
|
|
168
|
+
points,
|
|
169
|
+
markers,
|
|
170
|
+
labels,
|
|
171
|
+
color: s.color,
|
|
172
|
+
opacity: s.opacity,
|
|
173
|
+
width: s.lineWidth,
|
|
174
|
+
series: s,
|
|
175
|
+
hovered: false,
|
|
176
|
+
active: true,
|
|
177
|
+
id: s.id,
|
|
178
|
+
htmlElements,
|
|
179
|
+
});
|
|
151
180
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
point
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
181
|
+
if (series.some((s) => s.stacking === 'percent')) {
|
|
182
|
+
xValues.forEach(([x], index) => {
|
|
183
|
+
const stackHeight = accumulatedYValues.get(x) || 0;
|
|
184
|
+
let acc = 0;
|
|
185
|
+
const ratio = plotHeight / stackHeight;
|
|
186
|
+
seriesStackData.forEach((item) => {
|
|
187
|
+
const point = item.points[index];
|
|
188
|
+
if (point.y !== null && point.y !== undefined) {
|
|
189
|
+
const height = (point.y0 - point.y) * ratio;
|
|
190
|
+
point.y0 = plotHeight - height - acc;
|
|
191
|
+
point.y = point.y0 + height;
|
|
192
|
+
acc += height;
|
|
193
|
+
}
|
|
163
194
|
});
|
|
164
|
-
return markersAcc;
|
|
165
|
-
}, []);
|
|
166
|
-
}
|
|
167
|
-
seriesStackData.push({
|
|
168
|
-
points,
|
|
169
|
-
markers,
|
|
170
|
-
labels,
|
|
171
|
-
color: s.color,
|
|
172
|
-
opacity: s.opacity,
|
|
173
|
-
width: s.lineWidth,
|
|
174
|
-
series: s,
|
|
175
|
-
hovered: false,
|
|
176
|
-
active: true,
|
|
177
|
-
id: s.id,
|
|
178
|
-
htmlElements,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
if (series.some((s) => s.stacking === 'percent')) {
|
|
182
|
-
xValues.forEach(([x], index) => {
|
|
183
|
-
const stackHeight = accumulatedYValues.get(x) || 0;
|
|
184
|
-
let acc = 0;
|
|
185
|
-
const ratio = plotHeight / stackHeight;
|
|
186
|
-
seriesStackData.forEach((item) => {
|
|
187
|
-
const point = item.points[index];
|
|
188
|
-
if (point.y !== null && point.y !== undefined) {
|
|
189
|
-
const height = (point.y0 - point.y) * ratio;
|
|
190
|
-
point.y0 = plotHeight - height - acc;
|
|
191
|
-
point.y = point.y0 + height;
|
|
192
|
-
acc += height;
|
|
193
|
-
}
|
|
194
195
|
});
|
|
195
|
-
}
|
|
196
|
+
}
|
|
197
|
+
result.push(...seriesStackData);
|
|
196
198
|
}
|
|
197
|
-
result.push(...seriesStackData);
|
|
198
199
|
}
|
|
199
200
|
return result;
|
|
200
201
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
2
2
|
import type { ChartScale } from '../../useAxisScales';
|
|
3
3
|
import type { PreparedBarXSeries, PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
|
+
import type { PreparedSplit } from '../../useSplit/types';
|
|
4
5
|
import type { PreparedBarXData } from './types';
|
|
5
6
|
export declare const prepareBarXData: (args: {
|
|
6
7
|
series: PreparedBarXSeries[];
|
|
@@ -10,4 +11,5 @@ export declare const prepareBarXData: (args: {
|
|
|
10
11
|
yAxis: PreparedYAxis[];
|
|
11
12
|
yScale: (ChartScale | undefined)[];
|
|
12
13
|
boundsHeight: number;
|
|
14
|
+
split: PreparedSplit;
|
|
13
15
|
}) => Promise<PreparedBarXData[]>;
|
|
@@ -33,8 +33,8 @@ async function getLabelData(d) {
|
|
|
33
33
|
}
|
|
34
34
|
// eslint-disable-next-line complexity
|
|
35
35
|
export const prepareBarXData = async (args) => {
|
|
36
|
-
var _a;
|
|
37
|
-
const { series, seriesOptions, xAxis, xScale, yScale, boundsHeight: plotHeight } = args;
|
|
36
|
+
var _a, _b, _c;
|
|
37
|
+
const { series, seriesOptions, xAxis, xScale, yAxis, yScale, boundsHeight: plotHeight, split, } = args;
|
|
38
38
|
const stackGap = seriesOptions['bar-x'].stackGap;
|
|
39
39
|
const categories = get(xAxis, 'categories', []);
|
|
40
40
|
const barMaxWidth = get(seriesOptions, 'bar-x.barMaxWidth');
|
|
@@ -55,8 +55,17 @@ export const prepareBarXData = async (args) => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
})();
|
|
58
|
-
|
|
58
|
+
// series grouped by plotIndex > xValue > data[];
|
|
59
|
+
const dataByPlots = new Map();
|
|
59
60
|
series.forEach((s) => {
|
|
61
|
+
var _a;
|
|
62
|
+
const yAxisIndex = s.yAxis;
|
|
63
|
+
const seriesYAxis = yAxis[yAxisIndex];
|
|
64
|
+
const plotIndex = seriesYAxis.plotIndex;
|
|
65
|
+
if (!dataByPlots.has(plotIndex)) {
|
|
66
|
+
dataByPlots.set(plotIndex, {});
|
|
67
|
+
}
|
|
68
|
+
const data = (_a = dataByPlots.get(plotIndex)) !== null && _a !== void 0 ? _a : {};
|
|
60
69
|
s.data.forEach((d) => {
|
|
61
70
|
if (!isSeriesDataValid(d)) {
|
|
62
71
|
return;
|
|
@@ -96,81 +105,87 @@ export const prepareBarXData = async (args) => {
|
|
|
96
105
|
}
|
|
97
106
|
});
|
|
98
107
|
}
|
|
99
|
-
const maxGroupSize = max(Object.values(data), (d) => Object.values(d).length) || 1;
|
|
100
|
-
const groupGap = Math.max(bandWidth * groupPadding, MIN_BAR_GROUP_GAP);
|
|
101
|
-
const groupWidth = bandWidth - groupGap;
|
|
102
|
-
const rectGap = Math.max(bandWidth * barPadding, MIN_BAR_GAP);
|
|
103
|
-
const rectWidth = Math.max(MIN_BAR_WIDTH, Math.min(groupWidth / maxGroupSize - rectGap, barMaxWidth));
|
|
104
108
|
const result = [];
|
|
105
|
-
const
|
|
106
|
-
for (let
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
const
|
|
128
|
-
|
|
109
|
+
const plotIndexes = Array.from(dataByPlots.keys());
|
|
110
|
+
for (let plotDataIndex = 0; plotDataIndex < plotIndexes.length; plotDataIndex++) {
|
|
111
|
+
const data = (_a = dataByPlots.get(plotIndexes[plotDataIndex])) !== null && _a !== void 0 ? _a : {};
|
|
112
|
+
const maxGroupSize = max(Object.values(data), (d) => Object.values(d).length) || 1;
|
|
113
|
+
const groupGap = Math.max(bandWidth * groupPadding, MIN_BAR_GROUP_GAP);
|
|
114
|
+
const groupWidth = bandWidth - groupGap;
|
|
115
|
+
const rectGap = Math.max(bandWidth * barPadding, MIN_BAR_GAP);
|
|
116
|
+
const rectWidth = Math.max(MIN_BAR_WIDTH, Math.min(groupWidth / maxGroupSize - rectGap, barMaxWidth));
|
|
117
|
+
const groupedData = Object.entries(data);
|
|
118
|
+
for (let groupedDataIndex = 0; groupedDataIndex < groupedData.length; groupedDataIndex++) {
|
|
119
|
+
const [xValue, val] = groupedData[groupedDataIndex];
|
|
120
|
+
const stacks = Object.values(val);
|
|
121
|
+
const currentGroupWidth = rectWidth * stacks.length + rectGap * (stacks.length - 1);
|
|
122
|
+
for (let groupItemIndex = 0; groupItemIndex < stacks.length; groupItemIndex++) {
|
|
123
|
+
const yValues = stacks[groupItemIndex];
|
|
124
|
+
let stackHeight = 0;
|
|
125
|
+
const stackItems = [];
|
|
126
|
+
const sortedData = sortKey
|
|
127
|
+
? sort(yValues, (a, b) => comparator(get(a, sortKey), get(b, sortKey)))
|
|
128
|
+
: yValues;
|
|
129
|
+
for (let yValueIndex = 0; yValueIndex < sortedData.length; yValueIndex++) {
|
|
130
|
+
const yValue = sortedData[yValueIndex];
|
|
131
|
+
const yAxisIndex = yValue.series.yAxis;
|
|
132
|
+
const seriesYScale = yScale[yAxisIndex];
|
|
133
|
+
if (!seriesYScale) {
|
|
129
134
|
continue;
|
|
130
135
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
136
|
+
const seriesYAxis = yAxis[yAxisIndex];
|
|
137
|
+
const yAxisTop = ((_b = split.plots[seriesYAxis.plotIndex]) === null || _b === void 0 ? void 0 : _b.top) || 0;
|
|
138
|
+
let xCenter;
|
|
139
|
+
if (xAxis.type === 'category') {
|
|
140
|
+
const xBandScale = xScale;
|
|
141
|
+
const xBandScaleDomain = xBandScale.domain();
|
|
142
|
+
if (xBandScaleDomain.indexOf(xValue) === -1) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
xCenter = (xBandScale(xValue) || 0) + xBandScale.bandwidth() / 2;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
const xLinearScale = xScale;
|
|
149
|
+
xCenter = xLinearScale(Number(xValue));
|
|
150
|
+
}
|
|
151
|
+
const x = xCenter - currentGroupWidth / 2 + (rectWidth + rectGap) * groupItemIndex;
|
|
152
|
+
const yDataValue = ((_c = yValue.data.y) !== null && _c !== void 0 ? _c : 0);
|
|
153
|
+
const y = seriesYScale(yDataValue);
|
|
154
|
+
const base = seriesYScale(0);
|
|
155
|
+
const isLastStackItem = yValueIndex === sortedData.length - 1;
|
|
156
|
+
const height = Math.abs(base - y);
|
|
157
|
+
let shapeHeight = height - (stackItems.length ? stackGap : 0);
|
|
158
|
+
if (shapeHeight < 0) {
|
|
159
|
+
shapeHeight = height;
|
|
160
|
+
}
|
|
161
|
+
if (shapeHeight < 0) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const barData = {
|
|
165
|
+
x,
|
|
166
|
+
y: yAxisTop + (yDataValue > 0 ? y - stackHeight : base),
|
|
167
|
+
width: rectWidth,
|
|
168
|
+
height: shapeHeight,
|
|
169
|
+
opacity: get(yValue.data, 'opacity', null),
|
|
170
|
+
data: yValue.data,
|
|
171
|
+
series: yValue.series,
|
|
172
|
+
htmlElements: [],
|
|
173
|
+
isLastStackItem,
|
|
174
|
+
};
|
|
175
|
+
stackItems.push(barData);
|
|
176
|
+
stackHeight += height;
|
|
146
177
|
}
|
|
147
|
-
if (
|
|
148
|
-
|
|
178
|
+
if (series.some((s) => s.stacking === 'percent')) {
|
|
179
|
+
let acc = 0;
|
|
180
|
+
const ratio = plotHeight / (stackHeight - stackItems.length);
|
|
181
|
+
stackItems.forEach((item) => {
|
|
182
|
+
item.height = item.height * ratio;
|
|
183
|
+
item.y = plotHeight - item.height - acc;
|
|
184
|
+
acc += item.height + 1;
|
|
185
|
+
});
|
|
149
186
|
}
|
|
150
|
-
|
|
151
|
-
x,
|
|
152
|
-
y: yDataValue > 0 ? y - stackHeight : seriesYScale(0),
|
|
153
|
-
width: rectWidth,
|
|
154
|
-
height: shapeHeight,
|
|
155
|
-
opacity: get(yValue.data, 'opacity', null),
|
|
156
|
-
data: yValue.data,
|
|
157
|
-
series: yValue.series,
|
|
158
|
-
htmlElements: [],
|
|
159
|
-
isLastStackItem,
|
|
160
|
-
};
|
|
161
|
-
stackItems.push(barData);
|
|
162
|
-
stackHeight += height;
|
|
163
|
-
}
|
|
164
|
-
if (series.some((s) => s.stacking === 'percent')) {
|
|
165
|
-
let acc = 0;
|
|
166
|
-
const ratio = plotHeight / (stackHeight - stackItems.length);
|
|
167
|
-
stackItems.forEach((item) => {
|
|
168
|
-
item.height = item.height * ratio;
|
|
169
|
-
item.y = plotHeight - item.height - acc;
|
|
170
|
-
acc += item.height + 1;
|
|
171
|
-
});
|
|
187
|
+
result.push(...stackItems);
|
|
172
188
|
}
|
|
173
|
-
result.push(...stackItems);
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
191
|
for (let i = 0; i < result.length; i++) {
|
|
@@ -57,6 +57,7 @@ export const useShapes = (args) => {
|
|
|
57
57
|
yAxis,
|
|
58
58
|
yScale,
|
|
59
59
|
boundsHeight,
|
|
60
|
+
split,
|
|
60
61
|
});
|
|
61
62
|
shapes.push(React.createElement(BarXSeriesShapes, { key: SERIES_TYPE.BarX, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
62
63
|
shapesData.push(...preparedData);
|
|
@@ -120,6 +121,7 @@ export const useShapes = (args) => {
|
|
|
120
121
|
yAxis,
|
|
121
122
|
yScale,
|
|
122
123
|
boundsHeight,
|
|
124
|
+
split,
|
|
123
125
|
isOutsideBounds,
|
|
124
126
|
});
|
|
125
127
|
shapes.push(React.createElement(AreaSeriesShapes, { key: SERIES_TYPE.Area, dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData, htmlLayout: htmlLayout, clipPathId: clipPathId }));
|
|
@@ -16,7 +16,7 @@ export const prepareLineData = async (args) => {
|
|
|
16
16
|
var _a;
|
|
17
17
|
const { series, xAxis, yAxis, xScale, yScale, split, isOutsideBounds } = args;
|
|
18
18
|
const [_xMin, xRangeMax] = xScale.range();
|
|
19
|
-
const xMax = xRangeMax
|
|
19
|
+
const xMax = xRangeMax;
|
|
20
20
|
const acc = [];
|
|
21
21
|
for (let i = 0; i < series.length; i++) {
|
|
22
22
|
const s = series[i];
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
.gcharts-line__label
|
|
1
|
+
.gcharts-line__label,
|
|
2
|
+
.gcharts-area__label,
|
|
3
|
+
.gcharts-radar__label,
|
|
4
|
+
.gcharts-heatmap__label,
|
|
5
|
+
.gcharts-funnel__label {
|
|
2
6
|
dominant-baseline: text-before-edge;
|
|
3
7
|
}
|
|
4
8
|
|
|
@@ -16,10 +20,6 @@
|
|
|
16
20
|
dominant-baseline: text-before-edge;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
.gcharts-radar__label {
|
|
20
|
-
dominant-baseline: text-before-edge;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
23
|
.gcharts-bar-x__label {
|
|
24
24
|
user-select: none;
|
|
25
25
|
fill: var(--g-color-text-complementary);
|
|
@@ -40,12 +40,4 @@
|
|
|
40
40
|
|
|
41
41
|
.gcharts-waterfall__connector {
|
|
42
42
|
stroke: var(--g-color-line-generic-active);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.gcharts-heatmap__label {
|
|
46
|
-
dominant-baseline: text-before-edge;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.gcharts-funnel__label {
|
|
50
|
-
dominant-baseline: text-before-edge;
|
|
51
43
|
}
|
|
@@ -129,7 +129,7 @@ export const getDomainDataYBySeries = (series) => {
|
|
|
129
129
|
switch (type) {
|
|
130
130
|
case 'area':
|
|
131
131
|
case 'bar-x': {
|
|
132
|
-
acc.push(...getDomainDataForStackedSeries(seriesList));
|
|
132
|
+
acc.push(0, ...getDomainDataForStackedSeries(seriesList));
|
|
133
133
|
break;
|
|
134
134
|
}
|
|
135
135
|
case 'waterfall': {
|
|
@@ -177,6 +177,7 @@ export const ChartInner = (props) => {
|
|
|
177
177
|
}, [
|
|
178
178
|
initialized,
|
|
179
179
|
preparedRangeSlider.defaultRange,
|
|
180
|
+
preparedSeries,
|
|
180
181
|
setInitialized,
|
|
181
182
|
updateRangeSliderState,
|
|
182
183
|
xScale,
|
|
@@ -201,7 +202,7 @@ export const ChartInner = (props) => {
|
|
|
201
202
|
React.createElement("g", { ref: plotBeforeRef }),
|
|
202
203
|
shapes,
|
|
203
204
|
React.createElement("g", { ref: plotAfterRef })),
|
|
204
|
-
((_e = xAxis === null || xAxis === void 0 ? void 0 : xAxis.rangeSlider) === null || _e === void 0 ? void 0 : _e.enabled) && (React.createElement(RangeSlider, { boundsOffsetLeft: debouncedOffsetLeft, boundsWidth: debouncedBoundsWidth, height: height, htmlLayout: htmlLayout, onUpdate: updateRangeSliderState, preparedChart: preparedChart, preparedLegend: preparedLegend, preparedSeries: debouncedAllPreparedSeries, preparedSeriesOptions: preparedSeriesOptions, preparedRangeSlider: xAxis.rangeSlider, rangeSliderState: rangeSliderState, width: width, xAxis: data.xAxis, yAxis: data.yAxis })),
|
|
205
|
+
((_e = xAxis === null || xAxis === void 0 ? void 0 : xAxis.rangeSlider) === null || _e === void 0 ? void 0 : _e.enabled) && (React.createElement(RangeSlider, { boundsOffsetLeft: debouncedOffsetLeft, boundsWidth: debouncedBoundsWidth, height: height, htmlLayout: htmlLayout, onUpdate: updateRangeSliderState, preparedChart: preparedChart, preparedLegend: preparedLegend, preparedSeries: debouncedAllPreparedSeries, preparedSeriesOptions: preparedSeriesOptions, preparedRangeSlider: xAxis.rangeSlider, rangeSliderState: rangeSliderState, width: width, xAxis: data.xAxis, yAxis: data.yAxis, zoomState: zoomState })),
|
|
205
206
|
(preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && legendConfig && (React.createElement(Legend, { chartSeries: preparedSeries, legend: preparedLegend, items: legendItems, config: legendConfig, onItemClick: handleLegendItemClick, onUpdate: unpinTooltip, htmlLayout: htmlLayout }))));
|
|
206
207
|
return (React.createElement("div", { className: b() },
|
|
207
208
|
React.createElement("svg", { ref: svgRef, width: width, height: height,
|
|
@@ -79,14 +79,13 @@ export function useChartInnerProps(props) {
|
|
|
79
79
|
const { xScale, yScale } = useAxisScales({
|
|
80
80
|
boundsWidth,
|
|
81
81
|
boundsHeight,
|
|
82
|
-
hasZoomX: Boolean(zoomState.x),
|
|
83
|
-
hasZoomY: Boolean(zoomState.y),
|
|
84
82
|
rangeSliderState,
|
|
85
83
|
series: preparedSeries,
|
|
86
84
|
seriesOptions: preparedSeriesOptions,
|
|
87
85
|
split: preparedSplit,
|
|
88
86
|
xAxis,
|
|
89
87
|
yAxis,
|
|
88
|
+
zoomState,
|
|
90
89
|
});
|
|
91
90
|
const isOutsideBounds = React.useCallback((x, y) => {
|
|
92
91
|
return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
|