@gravity-ui/charts 1.26.0 → 1.27.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/AxisX/AxisX.d.ts +5 -20
- package/dist/cjs/components/AxisX/AxisX.js +167 -212
- package/dist/cjs/components/AxisX/prepare-axis-data.d.ts +10 -0
- package/dist/cjs/components/AxisX/prepare-axis-data.js +267 -0
- package/dist/cjs/components/AxisX/styles.css +7 -10
- package/dist/cjs/components/AxisX/types.d.ts +85 -0
- package/dist/cjs/components/AxisX/types.js +1 -0
- package/dist/cjs/components/AxisY/AxisY.js +9 -3
- package/dist/cjs/components/AxisY/prepare-axis-data.d.ts +1 -1
- package/dist/cjs/components/AxisY/prepare-axis-data.js +17 -81
- package/dist/cjs/components/AxisY/prepare-axis-title.d.ts +16 -0
- package/dist/cjs/components/AxisY/prepare-axis-title.js +149 -0
- package/dist/cjs/components/AxisY/types.d.ts +16 -4
- package/dist/cjs/components/AxisY/utils.js +1 -8
- package/dist/cjs/components/ChartInner/index.js +62 -50
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +7 -7
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +15 -20
- package/dist/cjs/components/ChartInner/useChartInnerState.d.ts +3 -2
- package/dist/cjs/components/ChartInner/useChartInnerState.js +23 -4
- package/dist/cjs/components/Legend/index.js +21 -14
- package/dist/cjs/components/RangeSlider/index.d.ts +5 -3
- package/dist/cjs/components/RangeSlider/index.js +36 -4
- package/dist/cjs/components/Title/index.js +2 -2
- package/dist/cjs/components/utils.d.ts +9 -0
- package/dist/cjs/components/utils.js +34 -0
- package/dist/cjs/constants/defaults/axis.js +1 -1
- package/dist/cjs/hooks/index.d.ts +0 -1
- package/dist/cjs/hooks/index.js +0 -1
- package/dist/cjs/hooks/useAxis/index.js +10 -0
- package/dist/cjs/hooks/useAxis/types.d.ts +3 -0
- package/dist/cjs/hooks/useAxis/x-axis.d.ts +2 -1
- package/dist/cjs/hooks/useAxis/x-axis.js +36 -28
- package/dist/cjs/hooks/useAxis/y-axis.js +38 -11
- package/dist/cjs/hooks/useAxisScales/index.d.ts +4 -1
- package/dist/cjs/hooks/useAxisScales/index.js +8 -7
- package/dist/cjs/hooks/useAxisScales/utils.d.ts +6 -0
- package/dist/cjs/hooks/useAxisScales/utils.js +17 -0
- package/dist/cjs/hooks/useChartDimensions/utils.js +7 -1
- package/dist/cjs/hooks/useNormalizedOriginalData/index.d.ts +1 -7
- package/dist/cjs/hooks/useRangeSlider/index.js +1 -2
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +1 -3
- package/dist/cjs/hooks/useZoom/index.d.ts +1 -0
- package/dist/cjs/hooks/useZoom/index.js +12 -2
- package/dist/cjs/types/chart/axis.d.ts +45 -17
- package/dist/cjs/types/chart/title.d.ts +3 -0
- package/dist/{esm/utils/chart/axis.d.ts → cjs/utils/chart/axis/common.d.ts} +4 -16
- package/dist/{esm/utils/chart/axis.js → cjs/utils/chart/axis/common.js} +7 -40
- package/dist/cjs/utils/chart/axis/x-axis.d.ts +12 -0
- package/dist/cjs/utils/chart/axis/x-axis.js +78 -0
- package/dist/cjs/utils/chart/axis-generators/bottom.js +1 -1
- package/dist/cjs/utils/chart/index.d.ts +1 -1
- package/dist/cjs/utils/chart/index.js +1 -1
- package/dist/cjs/utils/chart/text.d.ts +0 -6
- package/dist/cjs/utils/chart/text.js +7 -19
- package/dist/esm/components/AxisX/AxisX.d.ts +5 -20
- package/dist/esm/components/AxisX/AxisX.js +167 -212
- package/dist/esm/components/AxisX/prepare-axis-data.d.ts +10 -0
- package/dist/esm/components/AxisX/prepare-axis-data.js +267 -0
- package/dist/esm/components/AxisX/styles.css +7 -10
- package/dist/esm/components/AxisX/types.d.ts +85 -0
- package/dist/esm/components/AxisX/types.js +1 -0
- package/dist/esm/components/AxisY/AxisY.js +9 -3
- package/dist/esm/components/AxisY/prepare-axis-data.d.ts +1 -1
- package/dist/esm/components/AxisY/prepare-axis-data.js +17 -81
- package/dist/esm/components/AxisY/prepare-axis-title.d.ts +16 -0
- package/dist/esm/components/AxisY/prepare-axis-title.js +149 -0
- package/dist/esm/components/AxisY/types.d.ts +16 -4
- package/dist/esm/components/AxisY/utils.js +1 -8
- package/dist/esm/components/ChartInner/index.js +62 -50
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +7 -7
- package/dist/esm/components/ChartInner/useChartInnerProps.js +15 -20
- package/dist/esm/components/ChartInner/useChartInnerState.d.ts +3 -2
- package/dist/esm/components/ChartInner/useChartInnerState.js +23 -4
- package/dist/esm/components/Legend/index.js +21 -14
- package/dist/esm/components/RangeSlider/index.d.ts +5 -3
- package/dist/esm/components/RangeSlider/index.js +36 -4
- package/dist/esm/components/Title/index.js +2 -2
- package/dist/esm/components/utils.d.ts +9 -0
- package/dist/esm/components/utils.js +34 -0
- package/dist/esm/constants/defaults/axis.js +1 -1
- package/dist/esm/hooks/index.d.ts +0 -1
- package/dist/esm/hooks/index.js +0 -1
- package/dist/esm/hooks/useAxis/index.js +10 -0
- package/dist/esm/hooks/useAxis/types.d.ts +3 -0
- package/dist/esm/hooks/useAxis/x-axis.d.ts +2 -1
- package/dist/esm/hooks/useAxis/x-axis.js +36 -28
- package/dist/esm/hooks/useAxis/y-axis.js +38 -11
- package/dist/esm/hooks/useAxisScales/index.d.ts +4 -1
- package/dist/esm/hooks/useAxisScales/index.js +8 -7
- package/dist/esm/hooks/useAxisScales/utils.d.ts +6 -0
- package/dist/esm/hooks/useAxisScales/utils.js +17 -0
- package/dist/esm/hooks/useChartDimensions/utils.js +7 -1
- package/dist/esm/hooks/useNormalizedOriginalData/index.d.ts +1 -7
- package/dist/esm/hooks/useRangeSlider/index.js +1 -2
- package/dist/esm/hooks/useRangeSlider/types.d.ts +1 -3
- package/dist/esm/hooks/useZoom/index.d.ts +1 -0
- package/dist/esm/hooks/useZoom/index.js +12 -2
- package/dist/esm/types/chart/axis.d.ts +45 -17
- package/dist/esm/types/chart/title.d.ts +3 -0
- package/dist/{cjs/utils/chart/axis.d.ts → esm/utils/chart/axis/common.d.ts} +4 -16
- package/dist/{cjs/utils/chart/axis.js → esm/utils/chart/axis/common.js} +7 -40
- package/dist/esm/utils/chart/axis/x-axis.d.ts +12 -0
- package/dist/esm/utils/chart/axis/x-axis.js +78 -0
- package/dist/esm/utils/chart/axis-generators/bottom.js +1 -1
- package/dist/esm/utils/chart/index.d.ts +1 -1
- package/dist/esm/utils/chart/index.js +1 -1
- package/dist/esm/utils/chart/text.d.ts +0 -6
- package/dist/esm/utils/chart/text.js +7 -19
- package/package.json +1 -1
- package/dist/cjs/hooks/useChartOptions/index.d.ts +0 -16
- package/dist/cjs/hooks/useChartOptions/index.js +0 -21
- package/dist/esm/hooks/useChartOptions/index.d.ts +0 -16
- package/dist/esm/hooks/useChartOptions/index.js +0 -21
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { getUniqId } from '@gravity-ui/uikit';
|
|
2
|
+
import { calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, wrapText, } from '../../utils';
|
|
3
|
+
import { getXAxisTickValues } from '../../utils/chart/axis/x-axis';
|
|
4
|
+
async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxWidth, axisWidth, boundsOffsetLeft, boundsOffsetRight, }) {
|
|
5
|
+
var _a;
|
|
6
|
+
const rotation = axis.labels.rotation;
|
|
7
|
+
const content = [];
|
|
8
|
+
let rowText = text;
|
|
9
|
+
let textSize = await getTextSize(text);
|
|
10
|
+
const a = (360 + rotation) % 90;
|
|
11
|
+
const textMaxWidth = a === 0
|
|
12
|
+
? Math.min(labelMaxWidth,
|
|
13
|
+
// rightmost label
|
|
14
|
+
labelMaxWidth / 2 + axisWidth + boundsOffsetRight - left)
|
|
15
|
+
: Math.min(axis.labels.height / calculateSin(a) - textSize.height * calculateSin(90 - a),
|
|
16
|
+
// leftmostLabel
|
|
17
|
+
(boundsOffsetLeft + left) / calculateSin(a));
|
|
18
|
+
if (textSize.width > textMaxWidth) {
|
|
19
|
+
rowText = await getTextWithElipsis({
|
|
20
|
+
text: rowText,
|
|
21
|
+
getTextWidth: async (str) => (await getTextSize(str)).width,
|
|
22
|
+
maxWidth: textMaxWidth,
|
|
23
|
+
});
|
|
24
|
+
textSize = await getTextSize(rowText);
|
|
25
|
+
}
|
|
26
|
+
const actualTextWidth = a
|
|
27
|
+
? textSize.width * calculateSin(90 - a) + textSize.height * calculateSin(a)
|
|
28
|
+
: textSize.width;
|
|
29
|
+
const xOffset = a ? (textSize.width * calculateSin(90 - a)) / 2 : 0;
|
|
30
|
+
const yOffset = textSize.width * calculateSin(a);
|
|
31
|
+
content.push({
|
|
32
|
+
text: rowText,
|
|
33
|
+
x: 0,
|
|
34
|
+
y: 0,
|
|
35
|
+
size: textSize,
|
|
36
|
+
});
|
|
37
|
+
const x = Math.max(-boundsOffsetLeft, Math.min(left - actualTextWidth / 2 - xOffset, axisWidth - actualTextWidth));
|
|
38
|
+
const y = top + yOffset + axis.labels.margin;
|
|
39
|
+
const svgLabel = {
|
|
40
|
+
title: ((_a = content[0]) === null || _a === void 0 ? void 0 : _a.text) === text ? undefined : text,
|
|
41
|
+
content,
|
|
42
|
+
style: axis.labels.style,
|
|
43
|
+
size: textSize,
|
|
44
|
+
x,
|
|
45
|
+
y,
|
|
46
|
+
angle: rotation,
|
|
47
|
+
};
|
|
48
|
+
return svgLabel;
|
|
49
|
+
}
|
|
50
|
+
// eslint-disable-next-line complexity
|
|
51
|
+
export async function prepareXAxisData({ axis, scale, boundsWidth, boundsOffsetLeft, boundsOffsetRight, height, }) {
|
|
52
|
+
var _a, _b, _c, _d;
|
|
53
|
+
const axisHeight = height;
|
|
54
|
+
const axisWidth = boundsWidth;
|
|
55
|
+
let domain = null;
|
|
56
|
+
if (axis.visible) {
|
|
57
|
+
domain = {
|
|
58
|
+
start: [0, height],
|
|
59
|
+
end: [axisWidth, height],
|
|
60
|
+
lineColor: (_a = axis.lineColor) !== null && _a !== void 0 ? _a : '',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const ticks = [];
|
|
64
|
+
const getTextSize = getTextSizeFn({ style: axis.labels.style });
|
|
65
|
+
const labelLineHeight = (await getTextSize('Tmp')).height;
|
|
66
|
+
const values = getXAxisTickValues({ scale, axis, labelLineHeight });
|
|
67
|
+
const tickStep = getMinSpaceBetween(values, (d) => Number(d.value));
|
|
68
|
+
const labelMaxWidth = values.length > 1
|
|
69
|
+
? Math.abs(values[0].x - values[1].x) - axis.labels.padding * 2
|
|
70
|
+
: axisWidth;
|
|
71
|
+
for (let i = 0; i < values.length; i++) {
|
|
72
|
+
const tickValue = values[i];
|
|
73
|
+
let svgLabel = null;
|
|
74
|
+
let htmlLabel = null;
|
|
75
|
+
if (axis.labels.enabled) {
|
|
76
|
+
if (axis.labels.html) {
|
|
77
|
+
const content = String(tickValue.value);
|
|
78
|
+
const labelSize = await getLabelsSize({
|
|
79
|
+
labels: [content],
|
|
80
|
+
html: true,
|
|
81
|
+
style: axis.labels.style,
|
|
82
|
+
});
|
|
83
|
+
const size = { width: labelSize.maxWidth, height: labelSize.maxHeight };
|
|
84
|
+
htmlLabel = {
|
|
85
|
+
content,
|
|
86
|
+
x: tickValue.x - size.width / 2,
|
|
87
|
+
y: height + axis.labels.margin,
|
|
88
|
+
size,
|
|
89
|
+
style: axis.labels.style,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const text = formatAxisTickLabel({ value: tickValue.value, axis, step: tickStep });
|
|
94
|
+
svgLabel = await getSvgAxisLabel({
|
|
95
|
+
getTextSize,
|
|
96
|
+
text,
|
|
97
|
+
axis,
|
|
98
|
+
top: height,
|
|
99
|
+
left: tickValue.x,
|
|
100
|
+
labelMaxWidth,
|
|
101
|
+
axisWidth,
|
|
102
|
+
boundsOffsetLeft,
|
|
103
|
+
boundsOffsetRight,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const tickLine = axis.grid.enabled
|
|
108
|
+
? {
|
|
109
|
+
points: [
|
|
110
|
+
[tickValue.x, 0],
|
|
111
|
+
[tickValue.x, height],
|
|
112
|
+
],
|
|
113
|
+
}
|
|
114
|
+
: null;
|
|
115
|
+
ticks.push({
|
|
116
|
+
line: tickLine,
|
|
117
|
+
svgLabel,
|
|
118
|
+
htmlLabel,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
let title = null;
|
|
122
|
+
if (axis.title.text) {
|
|
123
|
+
const getTitleTextSize = getTextSizeFn({ style: axis.title.style });
|
|
124
|
+
const titleContent = [];
|
|
125
|
+
const titleMaxWidth = axisWidth;
|
|
126
|
+
if (axis.title.maxRowCount > 1) {
|
|
127
|
+
const titleTextRows = await wrapText({
|
|
128
|
+
text: axis.title.text,
|
|
129
|
+
style: axis.title.style,
|
|
130
|
+
width: titleMaxWidth,
|
|
131
|
+
getTextSize: getTitleTextSize,
|
|
132
|
+
});
|
|
133
|
+
for (let i = 0; i < axis.title.maxRowCount && i < titleTextRows.length; i++) {
|
|
134
|
+
const textRow = titleTextRows[i];
|
|
135
|
+
const textRowContent = textRow.text.trim();
|
|
136
|
+
const textRowSize = await getTitleTextSize(textRowContent);
|
|
137
|
+
titleContent.push({
|
|
138
|
+
text: textRowContent,
|
|
139
|
+
x: 0,
|
|
140
|
+
y: textRow.y,
|
|
141
|
+
size: textRowSize,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const text = await getTextWithElipsis({
|
|
147
|
+
text: axis.title.text,
|
|
148
|
+
maxWidth: titleMaxWidth,
|
|
149
|
+
getTextWidth: async (s) => (await getTitleTextSize(s)).width,
|
|
150
|
+
});
|
|
151
|
+
titleContent.push({
|
|
152
|
+
text,
|
|
153
|
+
x: 0,
|
|
154
|
+
y: 0,
|
|
155
|
+
size: await getTitleTextSize(text),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const titleTextSize = titleContent.reduce((acc, item) => {
|
|
159
|
+
acc.width = Math.max(acc.width, item.size.width);
|
|
160
|
+
acc.height += item.size.height;
|
|
161
|
+
return acc;
|
|
162
|
+
}, { width: 0, height: 0 });
|
|
163
|
+
let x = 0;
|
|
164
|
+
switch (axis.title.align) {
|
|
165
|
+
case 'left': {
|
|
166
|
+
x = 0;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
case 'center': {
|
|
170
|
+
x = Math.max(axisWidth / 2 - titleTextSize.width / 2);
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case 'right': {
|
|
174
|
+
x = Math.max(0, axisWidth - titleTextSize.width);
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
title = {
|
|
179
|
+
content: titleContent,
|
|
180
|
+
style: axis.title.style,
|
|
181
|
+
size: titleTextSize,
|
|
182
|
+
x,
|
|
183
|
+
y: height +
|
|
184
|
+
axis.labels.margin +
|
|
185
|
+
axis.labels.height +
|
|
186
|
+
axis.title.margin +
|
|
187
|
+
titleTextSize.height,
|
|
188
|
+
rotate: 0,
|
|
189
|
+
offset: 0,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const plotBands = [];
|
|
193
|
+
for (let i = 0; i < axis.plotBands.length; i++) {
|
|
194
|
+
const plotBand = axis.plotBands[i];
|
|
195
|
+
const axisScale = scale;
|
|
196
|
+
const { from, to } = getBandsPosition({
|
|
197
|
+
band: plotBand,
|
|
198
|
+
axisScale,
|
|
199
|
+
axis: 'x',
|
|
200
|
+
});
|
|
201
|
+
const halfBandwidth = ((_c = (_b = axisScale.bandwidth) === null || _b === void 0 ? void 0 : _b.call(axisScale)) !== null && _c !== void 0 ? _c : 0) / 2;
|
|
202
|
+
const startPos = halfBandwidth + Math.min(from, to);
|
|
203
|
+
const endPos = Math.min(Math.abs(to - from), axisWidth - Math.min(from, to));
|
|
204
|
+
const getPlotLabelSize = getTextSizeFn({ style: plotBand.label.style });
|
|
205
|
+
const labelSize = plotBand.label.text ? await getPlotLabelSize(plotBand.label.text) : null;
|
|
206
|
+
plotBands.push({
|
|
207
|
+
layerPlacement: plotBand.layerPlacement,
|
|
208
|
+
x: Math.max(0, startPos),
|
|
209
|
+
y: 0,
|
|
210
|
+
width: Math.min(endPos, axisWidth),
|
|
211
|
+
height: axisHeight,
|
|
212
|
+
color: plotBand.color,
|
|
213
|
+
opacity: plotBand.opacity,
|
|
214
|
+
label: plotBand.label.text
|
|
215
|
+
? {
|
|
216
|
+
text: plotBand.label.text,
|
|
217
|
+
style: plotBand.label.style,
|
|
218
|
+
x: plotBand.label.padding,
|
|
219
|
+
y: plotBand.label.padding + ((_d = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _d !== void 0 ? _d : 0),
|
|
220
|
+
rotate: -90,
|
|
221
|
+
}
|
|
222
|
+
: null,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
const plotLines = [];
|
|
226
|
+
for (let i = 0; i < axis.plotLines.length; i++) {
|
|
227
|
+
const plotLine = axis.plotLines[i];
|
|
228
|
+
const axisScale = scale;
|
|
229
|
+
const plotLineValue = Number(axisScale(plotLine.value));
|
|
230
|
+
const points = [
|
|
231
|
+
[plotLineValue, 0],
|
|
232
|
+
[plotLineValue, axisHeight],
|
|
233
|
+
];
|
|
234
|
+
let label = null;
|
|
235
|
+
if (plotLine.label.text) {
|
|
236
|
+
const getTitleTextSize = getTextSizeFn({ style: plotLine.label.style });
|
|
237
|
+
const size = await getTitleTextSize(plotLine.label.text);
|
|
238
|
+
label = {
|
|
239
|
+
text: plotLine.label.text,
|
|
240
|
+
style: plotLine.label.style,
|
|
241
|
+
x: plotLineValue - plotLine.label.padding - size.height,
|
|
242
|
+
y: plotLine.label.padding + size.width,
|
|
243
|
+
rotate: -90,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
plotLines.push({
|
|
247
|
+
layerPlacement: plotLine.layerPlacement,
|
|
248
|
+
x: 0,
|
|
249
|
+
y: 0,
|
|
250
|
+
width: axisWidth,
|
|
251
|
+
color: plotLine.color,
|
|
252
|
+
opacity: plotLine.opacity,
|
|
253
|
+
label,
|
|
254
|
+
points,
|
|
255
|
+
lineWidth: plotLine.width,
|
|
256
|
+
dashStyle: plotLine.dashStyle,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
id: getUniqId(),
|
|
261
|
+
title,
|
|
262
|
+
ticks,
|
|
263
|
+
domain,
|
|
264
|
+
plotBands,
|
|
265
|
+
plotLines,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
.gcharts-
|
|
1
|
+
.gcharts-x-axis__domain {
|
|
2
2
|
stroke: var(--g-color-line-generic-active);
|
|
3
3
|
}
|
|
4
|
-
.gcharts-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
.gcharts-x-axis__label {
|
|
5
|
+
fill: var(--g-color-text-secondary);
|
|
6
|
+
stroke: none;
|
|
7
7
|
}
|
|
8
|
-
.gcharts-
|
|
8
|
+
.gcharts-x-axis__tick {
|
|
9
9
|
stroke: var(--g-color-line-generic);
|
|
10
10
|
}
|
|
11
|
-
.gcharts-axis__title {
|
|
12
|
-
dominant-baseline: text-
|
|
11
|
+
.gcharts-x-axis__title {
|
|
12
|
+
dominant-baseline: text-before-edge;
|
|
13
13
|
fill: var(--g-color-text-secondary);
|
|
14
|
-
}
|
|
15
|
-
.gcharts-axis__title tspan {
|
|
16
|
-
dominant-baseline: text-after-edge;
|
|
17
14
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { DashStyle } from 'src/constants';
|
|
2
|
+
import type { BaseTextStyle, HtmlItem, PlotLayerPlacement, PointPosition } from '../../types';
|
|
3
|
+
export type TextRowData = {
|
|
4
|
+
text: string;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
size: {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type AxisSvgLabelData = {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
angle: number;
|
|
16
|
+
content: TextRowData[];
|
|
17
|
+
title?: string;
|
|
18
|
+
style: BaseTextStyle;
|
|
19
|
+
size: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type AxisTickLine = {
|
|
25
|
+
points: PointPosition[];
|
|
26
|
+
};
|
|
27
|
+
export type AxisTickData = {
|
|
28
|
+
line: AxisTickLine | null;
|
|
29
|
+
svgLabel: AxisSvgLabelData | null;
|
|
30
|
+
htmlLabel: HtmlItem | null;
|
|
31
|
+
};
|
|
32
|
+
export type AxisTitleData = {
|
|
33
|
+
content: TextRowData[];
|
|
34
|
+
style: BaseTextStyle;
|
|
35
|
+
size: {
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
};
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
rotate: number;
|
|
42
|
+
offset: number;
|
|
43
|
+
};
|
|
44
|
+
export type AxisPlotLineLabel = {
|
|
45
|
+
text: string;
|
|
46
|
+
rotate: number;
|
|
47
|
+
style: BaseTextStyle;
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
};
|
|
51
|
+
export type AxisPlotLineData = {
|
|
52
|
+
layerPlacement: PlotLayerPlacement;
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
width: number;
|
|
56
|
+
points: [number, number][];
|
|
57
|
+
color: string;
|
|
58
|
+
lineWidth: number;
|
|
59
|
+
opacity: number;
|
|
60
|
+
label: AxisPlotLineLabel | null;
|
|
61
|
+
dashStyle: DashStyle;
|
|
62
|
+
};
|
|
63
|
+
export type AxisPlotBandData = {
|
|
64
|
+
layerPlacement: PlotLayerPlacement;
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
color: string;
|
|
70
|
+
opacity: number;
|
|
71
|
+
label: AxisPlotLineLabel | null;
|
|
72
|
+
};
|
|
73
|
+
export type AxisDomainData = {
|
|
74
|
+
start: [number, number];
|
|
75
|
+
end: [number, number];
|
|
76
|
+
lineColor: string;
|
|
77
|
+
};
|
|
78
|
+
export type AxisXData = {
|
|
79
|
+
id: string;
|
|
80
|
+
title: AxisTitleData | null;
|
|
81
|
+
domain: AxisDomainData | null;
|
|
82
|
+
ticks: AxisTickData[];
|
|
83
|
+
plotLines: AxisPlotLineData[];
|
|
84
|
+
plotBands: AxisPlotBandData[];
|
|
85
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,11 +5,17 @@ import { block, getLineDashArray } from '../../utils';
|
|
|
5
5
|
import './styles.css';
|
|
6
6
|
const b = block('y-axis');
|
|
7
7
|
export const AxisY = (props) => {
|
|
8
|
+
var _a;
|
|
8
9
|
const { htmlLayout, plotBeforeRef, plotAfterRef, preparedAxisData } = props;
|
|
9
10
|
const ref = React.useRef(null);
|
|
10
11
|
const lineGenerator = line();
|
|
11
|
-
const
|
|
12
|
+
const htmlElements = [];
|
|
13
|
+
htmlElements.push(...preparedAxisData.ticks.map((d) => d.htmlLabel).filter(Boolean));
|
|
14
|
+
if ((_a = preparedAxisData.title) === null || _a === void 0 ? void 0 : _a.html) {
|
|
15
|
+
htmlElements.push(preparedAxisData.title);
|
|
16
|
+
}
|
|
12
17
|
React.useEffect(() => {
|
|
18
|
+
var _a;
|
|
13
19
|
if (!ref.current) {
|
|
14
20
|
return;
|
|
15
21
|
}
|
|
@@ -26,7 +32,7 @@ export const AxisY = (props) => {
|
|
|
26
32
|
plotAfterContainer = select(plotAfterRef.current);
|
|
27
33
|
plotAfterContainer.selectAll(`[${plotDataAttr}]`).remove();
|
|
28
34
|
}
|
|
29
|
-
if (preparedAxisData.title) {
|
|
35
|
+
if (((_a = preparedAxisData.title) === null || _a === void 0 ? void 0 : _a.html) === false) {
|
|
30
36
|
svgElement
|
|
31
37
|
.append('g')
|
|
32
38
|
.attr('class', b('title'))
|
|
@@ -177,6 +183,6 @@ export const AxisY = (props) => {
|
|
|
177
183
|
}
|
|
178
184
|
}, [lineGenerator, plotAfterRef, plotBeforeRef, preparedAxisData]);
|
|
179
185
|
return (React.createElement(React.Fragment, null,
|
|
180
|
-
React.createElement(HtmlLayer, { preparedData: { htmlElements
|
|
186
|
+
React.createElement(HtmlLayer, { preparedData: { htmlElements }, htmlLayout: htmlLayout }),
|
|
181
187
|
React.createElement("g", { ref: ref, className: b() })));
|
|
182
188
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChartScale, PreparedAxis, PreparedSeries, PreparedSplit } from '../../hooks';
|
|
2
2
|
import type { AxisYData } from './types';
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function prepareYAxisData({ axis, split, scale, top: topOffset, width, height, series, }: {
|
|
4
4
|
axis: PreparedAxis;
|
|
5
5
|
split: PreparedSplit;
|
|
6
6
|
scale: ChartScale;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getUniqId } from '@gravity-ui/uikit';
|
|
2
2
|
import { calculateCos, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, wrapText, } from '../../utils';
|
|
3
|
+
import { prepareHtmlYAxisTitle, prepareSvgYAxisTitle } from './prepare-axis-title';
|
|
3
4
|
import { getTickValues } from './utils';
|
|
4
5
|
async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxHeight, topOffset, }) {
|
|
5
6
|
var _a;
|
|
@@ -107,8 +108,7 @@ async function getSvgAxisLabel({ getTextSize, text, axis, top, left, labelMaxHei
|
|
|
107
108
|
};
|
|
108
109
|
return svgLabel;
|
|
109
110
|
}
|
|
110
|
-
|
|
111
|
-
export async function prepareAxisData({ axis, split, scale, top: topOffset, width, height, series, }) {
|
|
111
|
+
export async function prepareYAxisData({ axis, split, scale, top: topOffset, width, height, series, }) {
|
|
112
112
|
var _a, _b, _c;
|
|
113
113
|
const axisPlotTopPosition = ((_a = split.plots[axis.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
|
|
114
114
|
const axisHeight = ((_b = split.plots[axis.plotIndex]) === null || _b === void 0 ? void 0 : _b.height) || height;
|
|
@@ -183,85 +183,21 @@ export async function prepareAxisData({ axis, split, scale, top: topOffset, widt
|
|
|
183
183
|
}
|
|
184
184
|
let labelsWidth = ticks.reduce((acc, item) => { var _a, _b, _c, _d; return Math.max(acc, (_d = (_b = (_a = item.svgLabel) === null || _a === void 0 ? void 0 : _a.size.width) !== null && _b !== void 0 ? _b : (_c = item.htmlLabel) === null || _c === void 0 ? void 0 : _c.size.width) !== null && _d !== void 0 ? _d : 0); }, 0);
|
|
185
185
|
labelsWidth = Math.min(axis.labels.width, labelsWidth);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
for (let i = 0; i < axis.title.maxRowCount && i < titleTextRows.length; i++) {
|
|
202
|
-
const textRow = titleTextRows[i];
|
|
203
|
-
const textRowContent = textRow.text.trim();
|
|
204
|
-
const textRowSize = await getTitleTextSize(textRowContent);
|
|
205
|
-
titleContent.push({
|
|
206
|
-
text: textRowContent,
|
|
207
|
-
x: 0,
|
|
208
|
-
y: textRow.y,
|
|
209
|
-
size: textRowSize,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
const text = await getTextWithElipsis({
|
|
215
|
-
text: axis.title.text,
|
|
216
|
-
maxWidth: titleMaxWidth,
|
|
217
|
-
getTextWidth: async (s) => (await getTitleTextSize(s)).width,
|
|
218
|
-
});
|
|
219
|
-
titleContent.push({
|
|
220
|
-
text,
|
|
221
|
-
x: 0,
|
|
222
|
-
y: 0,
|
|
223
|
-
size: await getTitleTextSize(text),
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
const originalTextSize = titleContent.reduce((acc, item) => {
|
|
227
|
-
acc.width = Math.max(acc.width, item.size.width);
|
|
228
|
-
acc.height += item.size.height;
|
|
229
|
-
return acc;
|
|
230
|
-
}, { width: 0, height: 0 });
|
|
231
|
-
const rotatedTitleSize = {
|
|
232
|
-
width: sin * originalTextSize.height + cos * originalTextSize.width,
|
|
233
|
-
height: sin * originalTextSize.width + cos * originalTextSize.height,
|
|
234
|
-
};
|
|
235
|
-
const bottom = Math.max(0, calculateSin(rotateAngle) * originalTextSize.width);
|
|
236
|
-
let y = 0;
|
|
237
|
-
switch (axis.title.align) {
|
|
238
|
-
case 'left': {
|
|
239
|
-
y = -bottom + axisHeight;
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
case 'center': {
|
|
243
|
-
y = -bottom + axisHeight / 2 + rotatedTitleSize.height / 2;
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
case 'right': {
|
|
247
|
-
y = -bottom + rotatedTitleSize.height;
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
const left = Math.min(0, calculateCos(rotateAngle) * originalTextSize.width);
|
|
252
|
-
const x = axis.position === 'left'
|
|
253
|
-
? -left - labelsWidth - axis.labels.margin - axis.title.margin
|
|
254
|
-
: -left + width + labelsWidth + axis.labels.margin + axis.title.margin;
|
|
255
|
-
title = {
|
|
256
|
-
content: titleContent,
|
|
257
|
-
style: axis.title.style,
|
|
258
|
-
size: rotatedTitleSize,
|
|
259
|
-
x,
|
|
260
|
-
y: axisPlotTopPosition + y,
|
|
261
|
-
rotate: rotateAngle,
|
|
262
|
-
offset: -(originalTextSize.height / titleContent.length) * (titleContent.length - 1),
|
|
263
|
-
};
|
|
264
|
-
}
|
|
186
|
+
const title = axis.title.html
|
|
187
|
+
? await prepareHtmlYAxisTitle({
|
|
188
|
+
axis,
|
|
189
|
+
axisTop: axisPlotTopPosition,
|
|
190
|
+
axisWidth: width,
|
|
191
|
+
axisHeight,
|
|
192
|
+
axisLabelsWidth: labelsWidth,
|
|
193
|
+
})
|
|
194
|
+
: await prepareSvgYAxisTitle({
|
|
195
|
+
axis,
|
|
196
|
+
axisTop: axisPlotTopPosition,
|
|
197
|
+
axisWidth: width,
|
|
198
|
+
axisHeight,
|
|
199
|
+
axisLabelsWidth: labelsWidth,
|
|
200
|
+
});
|
|
265
201
|
const plotBands = [];
|
|
266
202
|
axis.plotBands.forEach((plotBand) => {
|
|
267
203
|
var _a, _b;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PreparedAxis } from 'src/hooks';
|
|
2
|
+
import type { HtmlAxisTitleData, SvgAxisTitleData } from './types';
|
|
3
|
+
export declare function prepareSvgYAxisTitle({ axis, axisTop, axisHeight, axisWidth, axisLabelsWidth, }: {
|
|
4
|
+
axis: PreparedAxis;
|
|
5
|
+
axisTop: number;
|
|
6
|
+
axisHeight: number;
|
|
7
|
+
axisWidth: number;
|
|
8
|
+
axisLabelsWidth: number;
|
|
9
|
+
}): Promise<SvgAxisTitleData | null>;
|
|
10
|
+
export declare function prepareHtmlYAxisTitle({ axis, axisTop, axisHeight, axisWidth, axisLabelsWidth, }: {
|
|
11
|
+
axis: PreparedAxis;
|
|
12
|
+
axisTop: number;
|
|
13
|
+
axisHeight: number;
|
|
14
|
+
axisWidth: number;
|
|
15
|
+
axisLabelsWidth: number;
|
|
16
|
+
}): Promise<HtmlAxisTitleData | null>;
|