@gravity-ui/charts 1.1.0 → 1.3.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.js +42 -5
- package/dist/cjs/components/Axis/AxisY.d.ts +1 -1
- package/dist/cjs/components/Axis/AxisY.js +48 -5
- package/dist/cjs/components/ChartInner/index.js +1 -1
- package/dist/cjs/components/ChartInner/styles.css +2 -0
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +3 -3
- package/dist/cjs/components/Legend/index.js +22 -10
- package/dist/cjs/components/Title/index.js +1 -1
- package/dist/cjs/constants/defaults/legend.d.ts +1 -0
- package/dist/cjs/constants/defaults/legend.js +1 -0
- package/dist/cjs/hooks/useChartOptions/types.d.ts +5 -3
- package/dist/cjs/hooks/useChartOptions/x-axis.js +7 -0
- package/dist/cjs/hooks/useChartOptions/y-axis.js +12 -1
- package/dist/cjs/hooks/useSeries/prepare-legend.js +1 -0
- 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 +11 -6
- 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 +14 -8
- 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 +30 -7
- package/dist/cjs/types/chart/legend.d.ts +6 -0
- package/dist/cjs/types/chart-ui.d.ts +1 -0
- package/dist/cjs/utils/chart/axis.d.ts +12 -1
- package/dist/cjs/utils/chart/axis.js +35 -0
- package/dist/cjs/utils/chart/index.d.ts +2 -1
- package/dist/cjs/utils/chart/types.d.ts +1 -0
- package/dist/cjs/utils/chart/types.js +1 -0
- package/dist/cjs/validation/index.js +144 -0
- package/dist/esm/components/Axis/AxisX.js +42 -5
- package/dist/esm/components/Axis/AxisY.d.ts +1 -1
- package/dist/esm/components/Axis/AxisY.js +48 -5
- package/dist/esm/components/ChartInner/index.js +1 -1
- package/dist/esm/components/ChartInner/styles.css +2 -0
- package/dist/esm/components/ChartInner/useChartInnerProps.js +3 -3
- package/dist/esm/components/Legend/index.js +22 -10
- package/dist/esm/components/Title/index.js +1 -1
- package/dist/esm/constants/defaults/legend.d.ts +1 -0
- package/dist/esm/constants/defaults/legend.js +1 -0
- package/dist/esm/hooks/useChartOptions/types.d.ts +5 -3
- package/dist/esm/hooks/useChartOptions/x-axis.js +7 -0
- package/dist/esm/hooks/useChartOptions/y-axis.js +12 -1
- package/dist/esm/hooks/useSeries/prepare-legend.js +1 -0
- 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 +11 -6
- 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 +14 -8
- 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 +30 -7
- package/dist/esm/types/chart/legend.d.ts +6 -0
- package/dist/esm/types/chart-ui.d.ts +1 -0
- package/dist/esm/utils/chart/axis.d.ts +12 -1
- package/dist/esm/utils/chart/axis.js +35 -0
- package/dist/esm/utils/chart/index.d.ts +2 -1
- package/dist/esm/utils/chart/types.d.ts +1 -0
- package/dist/esm/utils/chart/types.js +1 -0
- package/dist/esm/validation/index.js +144 -0
- package/package.json +1 -1
|
@@ -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,13 @@ 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
|
+
})),
|
|
113
120
|
visible: get(xAxis, 'visible', true),
|
|
114
121
|
};
|
|
115
122
|
const { height, rotation } = getLabelSettings({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, DashStyle, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
|
|
3
|
-
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, getWaterfallPointSubtotal, wrapText, } from '../../utils';
|
|
3
|
+
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, getWaterfallPointSubtotal, isAxisRelatedSeries, wrapText, } from '../../utils';
|
|
4
4
|
import { createYScale } from '../useAxisScales';
|
|
5
5
|
const getAxisLabelMaxWidth = (args) => {
|
|
6
6
|
const { axis, series } = args;
|
|
@@ -45,6 +45,10 @@ function getAxisMin(axis, series) {
|
|
|
45
45
|
export const getPreparedYAxis = ({ series, yAxis, height, }) => {
|
|
46
46
|
const axisByPlot = [];
|
|
47
47
|
const axisItems = yAxis || [{}];
|
|
48
|
+
const hasAxisRelatedSeries = series.some(isAxisRelatedSeries);
|
|
49
|
+
if (!hasAxisRelatedSeries) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
48
52
|
return axisItems.map((axisItem) => {
|
|
49
53
|
const plotIndex = get(axisItem, 'plotIndex', 0);
|
|
50
54
|
const firstPlotAxis = !axisByPlot[plotIndex];
|
|
@@ -116,6 +120,13 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
|
|
|
116
120
|
opacity: get(d, 'opacity', 1),
|
|
117
121
|
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
118
122
|
})),
|
|
123
|
+
plotBands: get(axisItem, 'plotBands', []).map((d) => ({
|
|
124
|
+
color: get(d, 'color', 'var(--g-color-base-brand)'),
|
|
125
|
+
opacity: get(d, 'opacity', 1),
|
|
126
|
+
from: get(d, 'from', 0),
|
|
127
|
+
to: get(d, 'to', 0),
|
|
128
|
+
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
129
|
+
})),
|
|
119
130
|
visible: get(axisItem, 'visible', true),
|
|
120
131
|
};
|
|
121
132
|
if (labelsEnabled) {
|
|
@@ -50,6 +50,7 @@ export const getPreparedLegend = (args) => {
|
|
|
50
50
|
const legendWidth = get(legend, 'width', CONTINUOUS_LEGEND_SIZE.width);
|
|
51
51
|
return {
|
|
52
52
|
align: get(legend, 'align', legendDefaults.align),
|
|
53
|
+
justifyContent: get(legend, 'justifyContent', legendDefaults.justifyContent),
|
|
53
54
|
enabled,
|
|
54
55
|
height,
|
|
55
56
|
itemDistance: get(legend, 'itemDistance', legendDefaults.itemDistance),
|
|
@@ -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) => {
|
|
@@ -17,7 +17,10 @@ const getCenter = (boundsWidth, boundsHeight, center) => {
|
|
|
17
17
|
};
|
|
18
18
|
export function preparePieData(args) {
|
|
19
19
|
const { series: preparedSeries, boundsWidth, boundsHeight } = args;
|
|
20
|
-
const
|
|
20
|
+
const haloSize = preparedSeries[0].states.hover.halo.enabled
|
|
21
|
+
? preparedSeries[0].states.hover.halo.size
|
|
22
|
+
: 0;
|
|
23
|
+
const maxRadius = Math.min(boundsWidth, boundsHeight) / 2 - haloSize;
|
|
21
24
|
const groupedPieSeries = group(preparedSeries, (pieSeries) => pieSeries.stackId);
|
|
22
25
|
const prepareItem = (stackId, items) => {
|
|
23
26
|
var _a;
|
|
@@ -184,6 +187,7 @@ export function preparePieData(args) {
|
|
|
184
187
|
y: Math.max(0, data.center[1] + label.y),
|
|
185
188
|
content: label.text,
|
|
186
189
|
size: label.size,
|
|
190
|
+
style: label.style,
|
|
187
191
|
});
|
|
188
192
|
}
|
|
189
193
|
else {
|
|
@@ -209,19 +213,20 @@ export function preparePieData(args) {
|
|
|
209
213
|
series: items,
|
|
210
214
|
});
|
|
211
215
|
const segmentMaxRadius = Math.max(...data.segments.map((s) => s.data.radius));
|
|
212
|
-
const
|
|
216
|
+
const topAdjustment = Math.min(data.center[1] - segmentMaxRadius, ...preparedLabels.labels.map((l) => l.y + data.center[1]), ...preparedLabels.htmlLabels.map((l) => l.y));
|
|
213
217
|
const bottom = Math.max(data.center[1] + segmentMaxRadius, ...preparedLabels.labels.map((l) => l.y + data.center[1] + l.size.height), ...preparedLabels.htmlLabels.map((l) => l.y + l.size.height));
|
|
214
|
-
const topAdjustment = Math.floor(top - data.halo.size);
|
|
215
218
|
if (topAdjustment > 0) {
|
|
216
219
|
data.segments.forEach((s) => {
|
|
217
|
-
s.data.radius
|
|
220
|
+
const nextPossibleRadius = s.data.radius + topAdjustment / 2;
|
|
221
|
+
s.data.radius = Math.min(nextPossibleRadius, maxRadius);
|
|
218
222
|
});
|
|
219
223
|
data.center[1] -= topAdjustment / 2;
|
|
220
224
|
}
|
|
221
|
-
const bottomAdjustment = Math.floor(boundsHeight - bottom
|
|
225
|
+
const bottomAdjustment = Math.floor(boundsHeight - bottom);
|
|
222
226
|
if (bottomAdjustment > 0) {
|
|
223
227
|
data.segments.forEach((s) => {
|
|
224
|
-
s.data.radius
|
|
228
|
+
const nextPossibleRadius = s.data.radius + bottomAdjustment / 2;
|
|
229
|
+
s.data.radius = Math.min(nextPossibleRadius, maxRadius);
|
|
225
230
|
});
|
|
226
231
|
data.center[1] += bottomAdjustment / 2;
|
|
227
232
|
}
|
|
@@ -10,23 +10,28 @@ function getLabels(args) {
|
|
|
10
10
|
texts.forEach((text, index) => {
|
|
11
11
|
var _a;
|
|
12
12
|
const label = getFormattedValue(Object.assign({ value: text }, args.options));
|
|
13
|
-
const { maxHeight: lineHeight, maxWidth:
|
|
13
|
+
const { maxHeight: lineHeight, maxWidth: labelMaxWidth } = (_a = getLabelsSize({ labels: [label], html })) !== null && _a !== void 0 ? _a : {};
|
|
14
14
|
const left = d.x0 + padding;
|
|
15
15
|
const right = d.x1 - padding;
|
|
16
|
-
const
|
|
16
|
+
const spaceWidth = Math.max(0, right - left);
|
|
17
|
+
const spaceHeight = Math.max(0, d.y1 - d.y0 - padding);
|
|
17
18
|
let x = left;
|
|
18
19
|
const y = index * lineHeight + d.y0 + padding;
|
|
20
|
+
const labelWidth = Math.min(labelMaxWidth, spaceWidth);
|
|
21
|
+
if (!labelWidth || lineHeight > spaceHeight) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
19
24
|
switch (align) {
|
|
20
25
|
case 'left': {
|
|
21
26
|
x = left;
|
|
22
27
|
break;
|
|
23
28
|
}
|
|
24
29
|
case 'center': {
|
|
25
|
-
x = Math.max(left, left + (
|
|
30
|
+
x = Math.max(left, left + (spaceWidth - labelMaxWidth) / 2);
|
|
26
31
|
break;
|
|
27
32
|
}
|
|
28
33
|
case 'right': {
|
|
29
|
-
x = Math.max(left, right -
|
|
34
|
+
x = Math.max(left, right - labelMaxWidth);
|
|
30
35
|
break;
|
|
31
36
|
}
|
|
32
37
|
}
|
|
@@ -35,13 +40,13 @@ function getLabels(args) {
|
|
|
35
40
|
content: label,
|
|
36
41
|
x,
|
|
37
42
|
y,
|
|
38
|
-
size: { width, height: lineHeight },
|
|
43
|
+
size: { width: labelWidth, height: lineHeight },
|
|
39
44
|
}
|
|
40
45
|
: {
|
|
41
46
|
text: label,
|
|
42
47
|
x,
|
|
43
48
|
y,
|
|
44
|
-
width,
|
|
49
|
+
width: labelWidth,
|
|
45
50
|
nodeData: d.data,
|
|
46
51
|
};
|
|
47
52
|
acc.push(item);
|
|
@@ -94,10 +99,11 @@ export function prepareTreemapData(args) {
|
|
|
94
99
|
let labelData = [];
|
|
95
100
|
const htmlElements = [];
|
|
96
101
|
if ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) {
|
|
97
|
-
const { html } = series.dataLabels;
|
|
102
|
+
const { html, style: dataLabelsStyle } = series.dataLabels;
|
|
98
103
|
const labels = getLabels({ data: leaves, options: series.dataLabels });
|
|
99
104
|
if (html) {
|
|
100
|
-
|
|
105
|
+
const htmlItems = labels.map((l) => (Object.assign({ style: dataLabelsStyle }, l)));
|
|
106
|
+
htmlElements.push(...htmlItems);
|
|
101
107
|
}
|
|
102
108
|
else {
|
|
103
109
|
labelData = labels;
|
|
@@ -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,12 +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[];
|
|
78
80
|
/** Whether axis, including axis title, line, ticks and labels, should be visible. */
|
|
79
81
|
visible?: boolean;
|
|
80
82
|
}
|
|
81
83
|
export interface ChartXAxis extends ChartAxis {
|
|
82
84
|
}
|
|
83
|
-
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 {
|
|
84
99
|
/** The position of the line in axis units. */
|
|
85
100
|
value?: number;
|
|
86
101
|
/** The color of the plot line (hex, rgba). */
|
|
@@ -92,14 +107,22 @@ export interface AxisPlotLine {
|
|
|
92
107
|
width?: number;
|
|
93
108
|
/** Option for line stroke style. */
|
|
94
109
|
dashStyle?: `${DashStyle}`;
|
|
110
|
+
}
|
|
111
|
+
export interface AxisPlotBand extends AxisPlot {
|
|
95
112
|
/**
|
|
96
|
-
*
|
|
113
|
+
* The start position of the plot band in axis units.
|
|
97
114
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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;
|
|
103
126
|
}
|
|
104
127
|
export interface ChartYAxis extends ChartAxis {
|
|
105
128
|
/** Axis location.
|
|
@@ -15,6 +15,12 @@ export interface ChartLegend {
|
|
|
15
15
|
* @default center
|
|
16
16
|
* */
|
|
17
17
|
align?: 'left' | 'center' | 'right';
|
|
18
|
+
/**
|
|
19
|
+
* Defines how items should be positioned in the legend when overflowing (moving to the next line).
|
|
20
|
+
*
|
|
21
|
+
* @default center
|
|
22
|
+
* */
|
|
23
|
+
justifyContent?: 'start' | 'center';
|
|
18
24
|
/**
|
|
19
25
|
* Defines the pixel distance between each legend item
|
|
20
26
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AxisDomain, AxisScale, ScaleBand } from 'd3';
|
|
2
|
-
import type { PreparedAxis, PreparedSplit } from '../../hooks';
|
|
2
|
+
import type { PreparedAxis, PreparedAxisPlotBand, PreparedSplit } from '../../hooks';
|
|
3
3
|
import type { TextRow } from './text';
|
|
4
|
+
import type { AxisDirection } from './types';
|
|
4
5
|
export declare function getTicksCount({ axis, range }: {
|
|
5
6
|
axis: PreparedAxis;
|
|
6
7
|
range: number;
|
|
@@ -29,3 +30,13 @@ export declare function getAxisTitleRows(args: {
|
|
|
29
30
|
axis: PreparedAxis;
|
|
30
31
|
textMaxWidth: number;
|
|
31
32
|
}): TextRow[];
|
|
33
|
+
interface GetBandsPositionArgs {
|
|
34
|
+
band: PreparedAxisPlotBand;
|
|
35
|
+
axisScale: AxisScale<AxisDomain>;
|
|
36
|
+
axis: AxisDirection;
|
|
37
|
+
}
|
|
38
|
+
export declare function getBandsPosition(args: GetBandsPositionArgs): {
|
|
39
|
+
from: number;
|
|
40
|
+
to: number;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import clamp from 'lodash/clamp';
|
|
1
2
|
import { wrapText } from './text';
|
|
2
3
|
export function getTicksCount({ axis, range }) {
|
|
3
4
|
let ticksCount;
|
|
@@ -69,3 +70,37 @@ export function getAxisTitleRows(args) {
|
|
|
69
70
|
return acc;
|
|
70
71
|
}, []);
|
|
71
72
|
}
|
|
73
|
+
export function getBandsPosition(args) {
|
|
74
|
+
var _a, _b, _c;
|
|
75
|
+
const { band, axisScale } = args;
|
|
76
|
+
const scalePosTo = axisScale(band.to);
|
|
77
|
+
const scalePosFrom = axisScale(band.from);
|
|
78
|
+
const isX = args.axis === 'x';
|
|
79
|
+
if (scalePosTo !== undefined && scalePosFrom !== undefined) {
|
|
80
|
+
return {
|
|
81
|
+
from: Math.max(scalePosFrom, 0),
|
|
82
|
+
to: Math.max(scalePosTo, 0),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (typeof band.from !== 'number' || typeof band.to !== 'number') {
|
|
86
|
+
throw new Error('Filed to create plot band');
|
|
87
|
+
}
|
|
88
|
+
const category = axisScale.domain();
|
|
89
|
+
const bandwidth = (_b = (_a = axisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(axisScale)) !== null && _b !== void 0 ? _b : 1;
|
|
90
|
+
const halfBandwidth = bandwidth / 2;
|
|
91
|
+
const calcPosition = (value) => {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
if (value >= category.length) {
|
|
94
|
+
return ((_a = axisScale(category[category.length - 1])) !== null && _a !== void 0 ? _a : 0) + halfBandwidth * (isX ? 1 : -1);
|
|
95
|
+
}
|
|
96
|
+
return (((_b = axisScale(category[clamp(Math.floor(value), 0, category.length - 1)])) !== null && _b !== void 0 ? _b : 0) +
|
|
97
|
+
bandwidth * (value - Math.floor(Math.abs(value))) * (isX ? 1 : -1));
|
|
98
|
+
};
|
|
99
|
+
const to = calcPosition(band.to);
|
|
100
|
+
const from = calcPosition(band.from);
|
|
101
|
+
const maxPos = ((_c = axisScale(category[isX ? category.length - 1 : 0])) !== null && _c !== void 0 ? _c : 0) + halfBandwidth;
|
|
102
|
+
return {
|
|
103
|
+
from: clamp(from, -halfBandwidth, maxPos),
|
|
104
|
+
to: clamp(to, -halfBandwidth, maxPos),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AxisDomain } from 'd3';
|
|
2
2
|
import type { PreparedAxis } from '../../hooks';
|
|
3
3
|
import type { BaseTextStyle, ChartSeries, ChartSeriesData } from '../../types';
|
|
4
|
+
import type { AxisDirection } from './types';
|
|
4
5
|
export * from './math';
|
|
5
6
|
export * from './text';
|
|
6
7
|
export * from './time';
|
|
@@ -12,7 +13,6 @@ export * from './series';
|
|
|
12
13
|
export * from './color';
|
|
13
14
|
export declare const CHART_SERIES_WITH_VOLUME_ON_Y_AXIS: ChartSeries['type'][];
|
|
14
15
|
export declare const CHART_SERIES_WITH_VOLUME_ON_X_AXIS: ChartSeries['type'][];
|
|
15
|
-
export type AxisDirection = 'x' | 'y';
|
|
16
16
|
type UnknownSeries = {
|
|
17
17
|
type: ChartSeries['type'];
|
|
18
18
|
data: unknown;
|
|
@@ -76,3 +76,4 @@ export declare const getDataCategoryValue: (args: {
|
|
|
76
76
|
data: ChartSeriesData;
|
|
77
77
|
}) => string;
|
|
78
78
|
export declare function getClosestPointsRange(axis: PreparedAxis, points: AxisDomain[]): number | undefined;
|
|
79
|
+
export { AxisDirection };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type AxisDirection = 'x' | 'y';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|