@gravity-ui/charts 1.43.1 → 1.45.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/ChartInner/utils/zoom.js +3 -1
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +31 -6
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +4 -5
- package/dist/cjs/core/constants/chart-types.d.ts +1 -0
- package/dist/cjs/core/constants/chart-types.js +1 -0
- package/dist/cjs/core/constants/defaults/annotation.d.ts +12 -0
- package/dist/cjs/core/constants/defaults/annotation.js +12 -0
- package/dist/cjs/core/constants/defaults/index.d.ts +1 -0
- package/dist/cjs/core/constants/defaults/index.js +1 -0
- package/dist/cjs/core/constants/defaults/series-options.d.ts +5 -1
- package/dist/cjs/core/constants/defaults/series-options.js +13 -0
- package/dist/cjs/core/i18n/keysets/en.json +2 -1
- package/dist/cjs/core/i18n/keysets/ru.json +2 -1
- package/dist/cjs/core/series/constants.d.ts +1 -1
- package/dist/cjs/core/series/constants.js +1 -1
- package/dist/cjs/core/series/prepare-annotation.d.ts +12 -0
- package/dist/cjs/core/series/prepare-annotation.js +31 -0
- package/dist/cjs/core/series/prepare-legend.js +2 -2
- package/dist/cjs/core/series/prepare-x-range.d.ts +11 -0
- package/dist/cjs/core/series/prepare-x-range.js +41 -0
- package/dist/cjs/core/series/prepareSeries.js +9 -0
- package/dist/cjs/core/series/types.d.ts +34 -2
- package/dist/cjs/core/types/chart/annotation.d.ts +45 -0
- package/dist/cjs/core/types/chart/annotation.js +1 -0
- package/dist/cjs/core/types/chart/area.d.ts +10 -1
- package/dist/cjs/core/types/chart/bar-x.d.ts +6 -0
- package/dist/cjs/core/types/chart/line.d.ts +8 -0
- package/dist/cjs/core/types/chart/marker.d.ts +6 -4
- package/dist/cjs/core/types/chart/series.d.ts +36 -2
- package/dist/cjs/core/types/chart/tooltip.d.ts +7 -1
- package/dist/cjs/core/types/chart/x-range.d.ts +59 -0
- package/dist/cjs/core/types/chart/x-range.js +1 -0
- package/dist/cjs/core/types/chart/zoom.d.ts +1 -1
- package/dist/cjs/core/types/index.d.ts +2 -0
- package/dist/cjs/core/types/index.js +2 -0
- package/dist/cjs/core/utils/axis/x-axis.js +9 -1
- package/dist/cjs/core/utils/color.js +6 -0
- package/dist/cjs/core/utils/common.js +10 -0
- package/dist/cjs/core/utils/get-closest-data.js +19 -0
- package/dist/cjs/core/utils/text.d.ts +8 -0
- package/dist/cjs/core/utils/text.js +9 -1
- package/dist/cjs/core/validation/index.js +13 -0
- package/dist/cjs/core/zoom/zoom.js +24 -7
- package/dist/cjs/hooks/useShapes/annotation/index.d.ts +14 -0
- package/dist/cjs/hooks/useShapes/annotation/index.js +200 -0
- package/dist/cjs/hooks/useShapes/area/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/area/index.js +21 -2
- package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +45 -26
- package/dist/cjs/hooks/useShapes/area/types.d.ts +4 -0
- package/dist/cjs/hooks/useShapes/bar-x/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/bar-x/index.js +30 -2
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +32 -11
- package/dist/cjs/hooks/useShapes/bar-x/types.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/index.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/index.js +22 -3
- package/dist/cjs/hooks/useShapes/line/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/line/index.js +21 -7
- package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/line/prepare-data.js +28 -10
- package/dist/cjs/hooks/useShapes/line/types.d.ts +4 -0
- package/dist/cjs/hooks/useShapes/x-range/index.d.ts +14 -0
- package/dist/cjs/hooks/useShapes/x-range/index.js +115 -0
- package/dist/cjs/hooks/useShapes/x-range/prepare-data.d.ts +15 -0
- package/dist/cjs/hooks/useShapes/x-range/prepare-data.js +147 -0
- package/dist/cjs/hooks/useShapes/x-range/types.d.ts +12 -0
- package/dist/cjs/hooks/useShapes/x-range/types.js +1 -0
- package/dist/esm/components/ChartInner/utils/zoom.js +3 -1
- package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +31 -6
- package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +4 -5
- package/dist/esm/core/constants/chart-types.d.ts +1 -0
- package/dist/esm/core/constants/chart-types.js +1 -0
- package/dist/esm/core/constants/defaults/annotation.d.ts +12 -0
- package/dist/esm/core/constants/defaults/annotation.js +12 -0
- package/dist/esm/core/constants/defaults/index.d.ts +1 -0
- package/dist/esm/core/constants/defaults/index.js +1 -0
- package/dist/esm/core/constants/defaults/series-options.d.ts +5 -1
- package/dist/esm/core/constants/defaults/series-options.js +13 -0
- package/dist/esm/core/i18n/keysets/en.json +2 -1
- package/dist/esm/core/i18n/keysets/ru.json +2 -1
- package/dist/esm/core/series/constants.d.ts +1 -1
- package/dist/esm/core/series/constants.js +1 -1
- package/dist/esm/core/series/prepare-annotation.d.ts +12 -0
- package/dist/esm/core/series/prepare-annotation.js +31 -0
- package/dist/esm/core/series/prepare-legend.js +2 -2
- package/dist/esm/core/series/prepare-x-range.d.ts +11 -0
- package/dist/esm/core/series/prepare-x-range.js +41 -0
- package/dist/esm/core/series/prepareSeries.js +9 -0
- package/dist/esm/core/series/types.d.ts +34 -2
- package/dist/esm/core/types/chart/annotation.d.ts +45 -0
- package/dist/esm/core/types/chart/annotation.js +1 -0
- package/dist/esm/core/types/chart/area.d.ts +10 -1
- package/dist/esm/core/types/chart/bar-x.d.ts +6 -0
- package/dist/esm/core/types/chart/line.d.ts +8 -0
- package/dist/esm/core/types/chart/marker.d.ts +6 -4
- package/dist/esm/core/types/chart/series.d.ts +36 -2
- package/dist/esm/core/types/chart/tooltip.d.ts +7 -1
- package/dist/esm/core/types/chart/x-range.d.ts +59 -0
- package/dist/esm/core/types/chart/x-range.js +1 -0
- package/dist/esm/core/types/chart/zoom.d.ts +1 -1
- package/dist/esm/core/types/index.d.ts +2 -0
- package/dist/esm/core/types/index.js +2 -0
- package/dist/esm/core/utils/axis/x-axis.js +9 -1
- package/dist/esm/core/utils/color.js +6 -0
- package/dist/esm/core/utils/common.js +10 -0
- package/dist/esm/core/utils/get-closest-data.js +19 -0
- package/dist/esm/core/utils/text.d.ts +8 -0
- package/dist/esm/core/utils/text.js +9 -1
- package/dist/esm/core/validation/index.js +13 -0
- package/dist/esm/core/zoom/zoom.js +24 -7
- package/dist/esm/hooks/useShapes/annotation/index.d.ts +14 -0
- package/dist/esm/hooks/useShapes/annotation/index.js +200 -0
- package/dist/esm/hooks/useShapes/area/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/area/index.js +21 -2
- package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +2 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +45 -26
- package/dist/esm/hooks/useShapes/area/types.d.ts +4 -0
- package/dist/esm/hooks/useShapes/bar-x/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/bar-x/index.js +30 -2
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +32 -11
- package/dist/esm/hooks/useShapes/bar-x/types.d.ts +2 -0
- package/dist/esm/hooks/useShapes/index.d.ts +2 -1
- package/dist/esm/hooks/useShapes/index.js +22 -3
- package/dist/esm/hooks/useShapes/line/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/line/index.js +21 -7
- package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +2 -1
- package/dist/esm/hooks/useShapes/line/prepare-data.js +28 -10
- package/dist/esm/hooks/useShapes/line/types.d.ts +4 -0
- package/dist/esm/hooks/useShapes/x-range/index.d.ts +14 -0
- package/dist/esm/hooks/useShapes/x-range/index.js +115 -0
- package/dist/esm/hooks/useShapes/x-range/prepare-data.d.ts +15 -0
- package/dist/esm/hooks/useShapes/x-range/prepare-data.js +147 -0
- package/dist/esm/hooks/useShapes/x-range/types.d.ts +12 -0
- package/dist/esm/hooks/useShapes/x-range/types.js +1 -0
- package/package.json +2 -2
|
@@ -2,10 +2,11 @@ import type { PreparedSplit } from '../../../core/layout/split-types';
|
|
|
2
2
|
import type { ChartScale } from '../../../core/scales/types';
|
|
3
3
|
import type { ShapeDataWithLabels } from '../../../types';
|
|
4
4
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
5
|
-
import type { PreparedLineSeries } from '../../useSeries/types';
|
|
5
|
+
import type { PreparedLineSeries, PreparedSeriesOptions } from '../../useSeries/types';
|
|
6
6
|
import type { PreparedLineData } from './types';
|
|
7
7
|
export declare const prepareLineData: (args: {
|
|
8
8
|
series: PreparedLineSeries[];
|
|
9
|
+
seriesOptions?: PreparedSeriesOptions;
|
|
9
10
|
xAxis: PreparedXAxis;
|
|
10
11
|
xScale: ChartScale;
|
|
11
12
|
yAxis: PreparedYAxis[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { prepareAnnotation } from '../../../core/series/prepare-annotation';
|
|
1
2
|
import { filterOverlappingLabels, getLabelsSize, getTextSizeFn } from '../../../core/utils';
|
|
2
3
|
import { getFormattedValue } from '../../../core/utils/format';
|
|
3
4
|
import { getXValue, getYValue } from '../utils';
|
|
@@ -15,8 +16,8 @@ async function getHtmlLabel(point, series, xMax) {
|
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
export const prepareLineData = async (args) => {
|
|
18
|
-
var _a, _b, _c, _d;
|
|
19
|
-
const { series, xAxis, yAxis, xScale, yScale, split, isOutsideBounds, isRangeSlider, otherLayers, } = args;
|
|
19
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
20
|
+
const { series, seriesOptions, xAxis, yAxis, xScale, yScale, split, isOutsideBounds, isRangeSlider, otherLayers, } = args;
|
|
20
21
|
const [_xMin, xRangeMax] = xScale.range();
|
|
21
22
|
const xMax = xRangeMax;
|
|
22
23
|
const acc = [];
|
|
@@ -29,21 +30,31 @@ export const prepareLineData = async (args) => {
|
|
|
29
30
|
if (!seriesYScale) {
|
|
30
31
|
continue;
|
|
31
32
|
}
|
|
32
|
-
const
|
|
33
|
+
const annotationOpts = (_b = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions.line) === null || _b === void 0 ? void 0 : _b.annotation;
|
|
34
|
+
const points = [];
|
|
35
|
+
for (let j = 0; j < s.data.length; j++) {
|
|
36
|
+
const d = s.data[j];
|
|
33
37
|
const yValue = getYValue({
|
|
34
38
|
point: d,
|
|
35
39
|
points: s.data,
|
|
36
40
|
yAxis: seriesYAxis,
|
|
37
41
|
yScale: seriesYScale,
|
|
38
42
|
});
|
|
39
|
-
|
|
43
|
+
points.push({
|
|
40
44
|
x: getXValue({ point: d, points: s.data, xAxis, xScale }),
|
|
41
45
|
y: yValue === null ? null : yAxisTop + yValue,
|
|
42
|
-
|
|
46
|
+
color: (_d = (_c = d.marker) === null || _c === void 0 ? void 0 : _c.color) !== null && _d !== void 0 ? _d : d.color,
|
|
43
47
|
data: d,
|
|
44
48
|
series: s,
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
annotation: d.annotation && !isRangeSlider
|
|
50
|
+
? await prepareAnnotation({
|
|
51
|
+
annotation: d.annotation,
|
|
52
|
+
optionsLabel: annotationOpts === null || annotationOpts === void 0 ? void 0 : annotationOpts.label,
|
|
53
|
+
optionsPopup: annotationOpts === null || annotationOpts === void 0 ? void 0 : annotationOpts.popup,
|
|
54
|
+
})
|
|
55
|
+
: undefined,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
47
58
|
let htmlElements = [];
|
|
48
59
|
let svgLabels = [];
|
|
49
60
|
if (s.dataLabels.enabled && !isRangeSlider) {
|
|
@@ -64,7 +75,7 @@ export const prepareLineData = async (args) => {
|
|
|
64
75
|
if (point.y !== null &&
|
|
65
76
|
point.x !== null &&
|
|
66
77
|
!isOutsideBounds(point.x, point.y)) {
|
|
67
|
-
const labelValue = (
|
|
78
|
+
const labelValue = (_e = point.data.label) !== null && _e !== void 0 ? _e : point.data.y;
|
|
68
79
|
const text = getFormattedValue(Object.assign({ value: labelValue }, s.dataLabels));
|
|
69
80
|
const labelSize = await getTextSize(text);
|
|
70
81
|
const style = s.dataLabels.style;
|
|
@@ -112,7 +123,14 @@ export const prepareLineData = async (args) => {
|
|
|
112
123
|
return result;
|
|
113
124
|
}, []);
|
|
114
125
|
}
|
|
126
|
+
const annotations = points.reduce((result, p) => {
|
|
127
|
+
if (p.annotation && p.x !== null && p.y !== null) {
|
|
128
|
+
result.push({ annotation: p.annotation, x: p.x, y: p.y });
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}, []);
|
|
115
132
|
const result = {
|
|
133
|
+
annotations,
|
|
116
134
|
points,
|
|
117
135
|
markers,
|
|
118
136
|
svgLabels: svgLabels,
|
|
@@ -122,11 +140,11 @@ export const prepareLineData = async (args) => {
|
|
|
122
140
|
id: s.id,
|
|
123
141
|
htmlLabels: htmlElements,
|
|
124
142
|
color: s.color,
|
|
125
|
-
lineWidth: (
|
|
143
|
+
lineWidth: (_f = (isRangeSlider ? s.rangeSlider.lineWidth : undefined)) !== null && _f !== void 0 ? _f : s.lineWidth,
|
|
126
144
|
dashStyle: s.dashStyle,
|
|
127
145
|
linecap: s.linecap,
|
|
128
146
|
linejoin: s.linejoin,
|
|
129
|
-
opacity: (
|
|
147
|
+
opacity: (_g = (isRangeSlider ? s.rangeSlider.opacity : undefined)) !== null && _g !== void 0 ? _g : s.opacity,
|
|
130
148
|
};
|
|
131
149
|
acc.push(result);
|
|
132
150
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { DashStyle, LineCap, LineJoin } from '../../../core/constants';
|
|
2
|
+
import type { PreparedAnnotation } from '../../../core/series/types';
|
|
2
3
|
import type { HtmlItem, LabelData, LineSeriesData, LineSeriesLineBaseStyle } from '../../../types';
|
|
3
4
|
import type { PreparedLineSeries } from '../../useSeries/types';
|
|
5
|
+
import type { AnnotationAnchor } from '../annotation';
|
|
4
6
|
export type PointData = {
|
|
5
7
|
x: number | null;
|
|
6
8
|
y: number | null;
|
|
7
9
|
data: LineSeriesData;
|
|
8
10
|
series: PreparedLineSeries;
|
|
11
|
+
annotation?: PreparedAnnotation;
|
|
9
12
|
color?: string;
|
|
10
13
|
};
|
|
11
14
|
export type MarkerPointData = PointData & {
|
|
@@ -19,6 +22,7 @@ export type MarkerData = {
|
|
|
19
22
|
clipped: boolean;
|
|
20
23
|
};
|
|
21
24
|
export type PreparedLineData = {
|
|
25
|
+
annotations: AnnotationAnchor[];
|
|
22
26
|
id: string;
|
|
23
27
|
points: PointData[];
|
|
24
28
|
markers: MarkerData[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Dispatch } from 'd3-dispatch';
|
|
3
|
+
import type { PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
|
+
export { prepareXRangeData } from './prepare-data';
|
|
5
|
+
export type { PreparedXRangeData } from './types';
|
|
6
|
+
import type { PreparedXRangeData } from './types';
|
|
7
|
+
type Args = {
|
|
8
|
+
clipPathId: string;
|
|
9
|
+
htmlLayout: HTMLElement | null;
|
|
10
|
+
preparedData: PreparedXRangeData[];
|
|
11
|
+
seriesOptions: PreparedSeriesOptions;
|
|
12
|
+
dispatcher?: Dispatch<object>;
|
|
13
|
+
};
|
|
14
|
+
export declare function XRangeSeriesShapes(args: Args): React.JSX.Element;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { color } from 'd3-color';
|
|
3
|
+
import { select } from 'd3-selection';
|
|
4
|
+
import get from 'lodash/get';
|
|
5
|
+
import { getLineDashArray } from '../../../core/utils';
|
|
6
|
+
import { block } from '../../../utils';
|
|
7
|
+
import { HtmlLayer } from '../HtmlLayer';
|
|
8
|
+
import { getRectPath } from '../utils';
|
|
9
|
+
export { prepareXRangeData } from './prepare-data';
|
|
10
|
+
const b = block('x-range');
|
|
11
|
+
export function XRangeSeriesShapes(args) {
|
|
12
|
+
const { dispatcher, preparedData, seriesOptions, htmlLayout, clipPathId } = args;
|
|
13
|
+
const hoveredDataRef = React.useRef(null);
|
|
14
|
+
const ref = React.useRef(null);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
var _a;
|
|
17
|
+
if (!ref.current) {
|
|
18
|
+
return () => { };
|
|
19
|
+
}
|
|
20
|
+
const svgElement = select(ref.current);
|
|
21
|
+
svgElement.selectAll('*').remove();
|
|
22
|
+
const segmentSelection = svgElement
|
|
23
|
+
.selectAll(`path.${b('segment')}`)
|
|
24
|
+
.data(preparedData)
|
|
25
|
+
.join('path')
|
|
26
|
+
.attr('d', (d) => {
|
|
27
|
+
const borderRadius = Math.min(d.height / 2, d.width / 2, d.series.borderRadius);
|
|
28
|
+
return getRectPath({
|
|
29
|
+
x: d.x,
|
|
30
|
+
y: d.y,
|
|
31
|
+
width: d.width,
|
|
32
|
+
height: d.height,
|
|
33
|
+
borderRadius,
|
|
34
|
+
}).toString();
|
|
35
|
+
})
|
|
36
|
+
.attr('class', b('segment'))
|
|
37
|
+
.attr('fill', (d) => d.color)
|
|
38
|
+
.attr('opacity', (d) => { var _a; return (_a = d.data.opacity) !== null && _a !== void 0 ? _a : d.series.opacity; })
|
|
39
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
40
|
+
svgElement
|
|
41
|
+
.selectAll(`path.${b('segment-border')}`)
|
|
42
|
+
.data(preparedData.filter((d) => d.series.borderWidth > 0))
|
|
43
|
+
.join('path')
|
|
44
|
+
.attr('d', (d) => {
|
|
45
|
+
const borderRadius = Math.min(d.height / 2, d.width / 2, d.series.borderRadius);
|
|
46
|
+
return getRectPath({
|
|
47
|
+
x: d.x,
|
|
48
|
+
y: d.y,
|
|
49
|
+
width: d.width,
|
|
50
|
+
height: d.height,
|
|
51
|
+
borderRadius,
|
|
52
|
+
}).toString();
|
|
53
|
+
})
|
|
54
|
+
.attr('class', b('segment-border'))
|
|
55
|
+
.attr('fill', 'none')
|
|
56
|
+
.attr('stroke', (d) => d.series.borderColor)
|
|
57
|
+
.attr('stroke-width', (d) => d.series.borderWidth)
|
|
58
|
+
.attr('stroke-dasharray', (d) => getLineDashArray(d.series.borderDashStyle, d.series.borderWidth))
|
|
59
|
+
.attr('opacity', (d) => { var _a; return (_a = d.data.opacity) !== null && _a !== void 0 ? _a : d.series.opacity; })
|
|
60
|
+
.attr('pointer-events', 'none');
|
|
61
|
+
const svgLabels = preparedData.flatMap((d) => d.svgLabels);
|
|
62
|
+
svgElement
|
|
63
|
+
.selectAll(`text.${b('label')}`)
|
|
64
|
+
.data(svgLabels)
|
|
65
|
+
.join('text')
|
|
66
|
+
.attr('class', b('label'))
|
|
67
|
+
.attr('x', (d) => d.x)
|
|
68
|
+
.attr('y', (d) => d.y)
|
|
69
|
+
.attr('text-anchor', (d) => d.textAnchor)
|
|
70
|
+
.attr('dominant-baseline', 'central')
|
|
71
|
+
.attr('pointer-events', 'none')
|
|
72
|
+
.style('font-size', (d) => d.style.fontSize)
|
|
73
|
+
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
74
|
+
.style('fill', (d) => d.style.fontColor || null)
|
|
75
|
+
.html((d) => d.text);
|
|
76
|
+
const hoverOptions = get(seriesOptions, 'x-range.states.hover');
|
|
77
|
+
const inactiveOptions = get(seriesOptions, 'x-range.states.inactive');
|
|
78
|
+
function handleShapeHover(data) {
|
|
79
|
+
hoveredDataRef.current = data;
|
|
80
|
+
if (hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled) {
|
|
81
|
+
const hoveredSet = new Set(data === null || data === void 0 ? void 0 : data.map((d) => d.data));
|
|
82
|
+
segmentSelection.attr('fill', (d) => {
|
|
83
|
+
var _a;
|
|
84
|
+
const fillColor = d.color;
|
|
85
|
+
if (hoveredSet.has(d.data)) {
|
|
86
|
+
return (((_a = color(fillColor)) === null || _a === void 0 ? void 0 : _a.brighter(hoverOptions.brightness).toString()) ||
|
|
87
|
+
fillColor);
|
|
88
|
+
}
|
|
89
|
+
return fillColor;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled) {
|
|
93
|
+
const hoveredSeries = data === null || data === void 0 ? void 0 : data.map((d) => d.series.id);
|
|
94
|
+
segmentSelection.attr('opacity', (d) => {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
if ((hoveredSeries === null || hoveredSeries === void 0 ? void 0 : hoveredSeries.length) && !hoveredSeries.includes(d.series.id)) {
|
|
97
|
+
return inactiveOptions.opacity || null;
|
|
98
|
+
}
|
|
99
|
+
return (_b = (_a = d.data.opacity) !== null && _a !== void 0 ? _a : d.series.opacity) !== null && _b !== void 0 ? _b : null;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (hoveredDataRef.current !== null) {
|
|
104
|
+
handleShapeHover((_a = hoveredDataRef.current) !== null && _a !== void 0 ? _a : undefined);
|
|
105
|
+
}
|
|
106
|
+
dispatcher === null || dispatcher === void 0 ? void 0 : dispatcher.on('hover-shape.x-range', handleShapeHover);
|
|
107
|
+
return () => {
|
|
108
|
+
dispatcher === null || dispatcher === void 0 ? void 0 : dispatcher.on('hover-shape.x-range', null);
|
|
109
|
+
};
|
|
110
|
+
}, [dispatcher, preparedData, seriesOptions]);
|
|
111
|
+
const htmlLayerData = React.useMemo(() => ({ htmlElements: preparedData.flatMap((d) => d.htmlLabels) }), [preparedData]);
|
|
112
|
+
return (React.createElement(React.Fragment, null,
|
|
113
|
+
React.createElement("g", { ref: ref, className: b(), clipPath: `url(#${clipPathId})` }),
|
|
114
|
+
React.createElement(HtmlLayer, { preparedData: htmlLayerData, htmlLayout: htmlLayout })));
|
|
115
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChartScale } from '../../../core/scales/types';
|
|
2
|
+
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
3
|
+
import type { PreparedXRangeSeries } from '../../useSeries/types';
|
|
4
|
+
import type { PreparedXRangeData } from './types';
|
|
5
|
+
type PrepareXRangeDataArgs = {
|
|
6
|
+
series: PreparedXRangeSeries[];
|
|
7
|
+
xAxis: PreparedXAxis;
|
|
8
|
+
xScale: ChartScale;
|
|
9
|
+
yAxis: PreparedYAxis[];
|
|
10
|
+
yScale: (ChartScale | undefined)[];
|
|
11
|
+
boundsWidth?: number;
|
|
12
|
+
isRangeSlider?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export declare function prepareXRangeData(args: PrepareXRangeDataArgs): Promise<PreparedXRangeData[]>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { getDataCategoryValue, getLabelsSize, getTextSizeFn, getTextWithElipsis } from '../../../core/utils';
|
|
3
|
+
import { getFormattedValue } from '../../../core/utils/format';
|
|
4
|
+
import { MIN_BAR_WIDTH } from '../../constants';
|
|
5
|
+
import { getBandSize } from '../../utils/get-band-size';
|
|
6
|
+
const DEFAULT_BAR_PADDING = 0.2;
|
|
7
|
+
export async function prepareXRangeData(args) {
|
|
8
|
+
var _a;
|
|
9
|
+
const { series, xAxis, xScale, yAxis, yScale: [yScale], boundsWidth, isRangeSlider, } = args;
|
|
10
|
+
if (!yScale) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
// Collect unique y-domain values
|
|
14
|
+
const domain = [];
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
const categories = get(yAxis[0], 'categories', []);
|
|
17
|
+
series.forEach((s) => {
|
|
18
|
+
s.data.forEach((d) => {
|
|
19
|
+
const key = yAxis[0].type === 'category'
|
|
20
|
+
? getDataCategoryValue({ axisDirection: 'y', categories, data: d })
|
|
21
|
+
: d.y;
|
|
22
|
+
if (key !== undefined && !seen.has(key)) {
|
|
23
|
+
seen.add(key);
|
|
24
|
+
domain.push(key);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
const bandSize = getBandSize({ domain, scale: yScale });
|
|
29
|
+
const barSize = Math.max(MIN_BAR_WIDTH, bandSize * (1 - DEFAULT_BAR_PADDING));
|
|
30
|
+
const result = [];
|
|
31
|
+
series.forEach((s) => {
|
|
32
|
+
s.data.forEach((d) => {
|
|
33
|
+
let center;
|
|
34
|
+
if (yAxis[0].type === 'category') {
|
|
35
|
+
const bandScale = yScale;
|
|
36
|
+
const yCategory = getDataCategoryValue({ axisDirection: 'y', categories, data: d });
|
|
37
|
+
if (!bandScale.domain().includes(yCategory)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
center = (bandScale(yCategory) || 0) + bandSize / 2;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const linearScale = yScale;
|
|
44
|
+
if (d.y === undefined) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
center = linearScale(Number(d.y));
|
|
48
|
+
}
|
|
49
|
+
let xStart;
|
|
50
|
+
let xEnd;
|
|
51
|
+
if (xAxis.type === 'category') {
|
|
52
|
+
// x-range on a category x-axis is unusual but supported
|
|
53
|
+
const xBandScale = xScale;
|
|
54
|
+
const xCategories = get(xAxis, 'categories', []);
|
|
55
|
+
const startCategory = getDataCategoryValue({
|
|
56
|
+
axisDirection: 'x',
|
|
57
|
+
categories: xCategories,
|
|
58
|
+
data: { x: d.x0 },
|
|
59
|
+
});
|
|
60
|
+
const endCategory = getDataCategoryValue({
|
|
61
|
+
axisDirection: 'x',
|
|
62
|
+
categories: xCategories,
|
|
63
|
+
data: { x: d.x1 },
|
|
64
|
+
});
|
|
65
|
+
xStart = xBandScale(startCategory) || 0;
|
|
66
|
+
xEnd = (xBandScale(endCategory) || 0) + xBandScale.bandwidth();
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const linearScale = xScale;
|
|
70
|
+
xStart = linearScale(Number(d.x0));
|
|
71
|
+
xEnd = linearScale(Number(d.x1));
|
|
72
|
+
}
|
|
73
|
+
const width = xEnd - xStart;
|
|
74
|
+
if (width <= 0) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
result.push({
|
|
78
|
+
x: xStart,
|
|
79
|
+
y: center - barSize / 2,
|
|
80
|
+
width,
|
|
81
|
+
height: barSize,
|
|
82
|
+
color: d.color || s.color,
|
|
83
|
+
data: d,
|
|
84
|
+
series: s,
|
|
85
|
+
htmlLabels: [],
|
|
86
|
+
svgLabels: [],
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
const textSizeFnCache = new Map();
|
|
91
|
+
for (let i = 0; i < result.length; i++) {
|
|
92
|
+
const item = result[i];
|
|
93
|
+
const { dataLabels } = item.series;
|
|
94
|
+
if (!dataLabels.enabled || item.data.label === null || isRangeSlider) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const content = getFormattedValue(Object.assign({ value: item.data.label }, dataLabels));
|
|
98
|
+
const visibleStart = Math.max(0, item.x);
|
|
99
|
+
const visibleEnd = boundsWidth === undefined
|
|
100
|
+
? item.x + item.width
|
|
101
|
+
: Math.min(boundsWidth, item.x + item.width);
|
|
102
|
+
const visibleWidth = visibleEnd - visibleStart;
|
|
103
|
+
const visibleCenterX = visibleStart + visibleWidth / 2;
|
|
104
|
+
if (dataLabels.html) {
|
|
105
|
+
const { maxHeight: height, maxWidth: width } = await getLabelsSize({
|
|
106
|
+
labels: [content],
|
|
107
|
+
style: dataLabels.style,
|
|
108
|
+
html: true,
|
|
109
|
+
});
|
|
110
|
+
const htmlItem = {
|
|
111
|
+
content,
|
|
112
|
+
size: { width, height },
|
|
113
|
+
style: dataLabels.style,
|
|
114
|
+
x: visibleCenterX - width / 2,
|
|
115
|
+
y: item.y + item.height / 2 - height / 2,
|
|
116
|
+
};
|
|
117
|
+
item.htmlLabels.push(htmlItem);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
if (!textSizeFnCache.has(dataLabels.style)) {
|
|
121
|
+
textSizeFnCache.set(dataLabels.style, getTextSizeFn({ style: dataLabels.style }));
|
|
122
|
+
}
|
|
123
|
+
const getTextSize = (_a = textSizeFnCache.get(dataLabels.style)) !== null && _a !== void 0 ? _a : getTextSizeFn({ style: dataLabels.style });
|
|
124
|
+
const availableWidth = Math.max(0, visibleWidth - 2 * dataLabels.padding);
|
|
125
|
+
const text = await getTextWithElipsis({
|
|
126
|
+
text: content,
|
|
127
|
+
getTextWidth: (s) => getTextSize(s).then((r) => r.width),
|
|
128
|
+
maxWidth: availableWidth,
|
|
129
|
+
});
|
|
130
|
+
if (!text) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const { width, height, hangingOffset } = await getTextSize(text);
|
|
134
|
+
const svgItem = {
|
|
135
|
+
text,
|
|
136
|
+
size: { width, height, hangingOffset },
|
|
137
|
+
style: dataLabels.style,
|
|
138
|
+
textAnchor: 'middle',
|
|
139
|
+
x: visibleCenterX,
|
|
140
|
+
y: item.y + item.height / 2,
|
|
141
|
+
series: item.series,
|
|
142
|
+
};
|
|
143
|
+
item.svgLabels.push(svgItem);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HtmlItem, LabelData, TooltipDataChunkXRange } from '../../../types';
|
|
2
|
+
import type { PreparedXRangeSeries } from '../../useSeries/types';
|
|
3
|
+
export type PreparedXRangeData = Omit<TooltipDataChunkXRange, 'series'> & {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
color: string;
|
|
9
|
+
series: PreparedXRangeSeries;
|
|
10
|
+
svgLabels: LabelData[];
|
|
11
|
+
htmlLabels: HtmlItem[];
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,7 +6,8 @@ function mapSeriesTypeToZoomType(seriesType) {
|
|
|
6
6
|
case SERIES_TYPE.Area: {
|
|
7
7
|
return [ZOOM_TYPE.X, ZOOM_TYPE.XY, ZOOM_TYPE.Y];
|
|
8
8
|
}
|
|
9
|
-
case SERIES_TYPE.BarX:
|
|
9
|
+
case SERIES_TYPE.BarX:
|
|
10
|
+
case SERIES_TYPE.XRange: {
|
|
10
11
|
return [ZOOM_TYPE.X];
|
|
11
12
|
}
|
|
12
13
|
case SERIES_TYPE.BarY: {
|
|
@@ -36,6 +37,7 @@ function getDefaultZoomType(seriesType) {
|
|
|
36
37
|
}
|
|
37
38
|
case SERIES_TYPE.Area:
|
|
38
39
|
case SERIES_TYPE.BarX:
|
|
40
|
+
case SERIES_TYPE.XRange:
|
|
39
41
|
case SERIES_TYPE.Line:
|
|
40
42
|
case SERIES_TYPE.Waterfall: {
|
|
41
43
|
return ZOOM_TYPE.X;
|
|
@@ -43,12 +43,15 @@ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, va
|
|
|
43
43
|
const colorSymbol = getTooltipRowColorSymbol({ series, color });
|
|
44
44
|
return (React.createElement(Row, { key: id, active: active, color: color, colorSymbol: colorSymbol ? (React.createElement("div", { dangerouslySetInnerHTML: { __html: colorSymbol.outerHTML } })) : undefined, label: React.createElement("span", { dangerouslySetInnerHTML: { __html: name } }), striped: striped, value: formattedValue }));
|
|
45
45
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
let formattedHeadValue;
|
|
47
|
+
if (measureValue) {
|
|
48
|
+
formattedHeadValue = headerFormat
|
|
49
|
+
? getFormattedValue({
|
|
50
|
+
value: measureValue.value,
|
|
51
|
+
format: headerFormat,
|
|
52
|
+
})
|
|
53
|
+
: measureValue.formattedValue;
|
|
54
|
+
}
|
|
52
55
|
React.useEffect(() => {
|
|
53
56
|
if (!contentRowsRef.current) {
|
|
54
57
|
return;
|
|
@@ -186,6 +189,28 @@ export const DefaultTooltipContent = ({ hovered, pinned, rowRenderer, totals, va
|
|
|
186
189
|
formattedValue,
|
|
187
190
|
});
|
|
188
191
|
}
|
|
192
|
+
case 'x-range': {
|
|
193
|
+
const xRangeData = data;
|
|
194
|
+
const format = rowValueFormat || getDefaultValueFormat({ axis: xAxis });
|
|
195
|
+
const x0Formatted = getFormattedValue({
|
|
196
|
+
value: xRangeData.x0,
|
|
197
|
+
format,
|
|
198
|
+
});
|
|
199
|
+
const x1Formatted = getFormattedValue({
|
|
200
|
+
value: xRangeData.x1,
|
|
201
|
+
format,
|
|
202
|
+
});
|
|
203
|
+
return renderRow({
|
|
204
|
+
id,
|
|
205
|
+
active,
|
|
206
|
+
color,
|
|
207
|
+
name: series.name,
|
|
208
|
+
striped,
|
|
209
|
+
value: hoveredValues[i],
|
|
210
|
+
formattedValue: `${x0Formatted} — ${x1Formatted}`,
|
|
211
|
+
series,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
189
214
|
default: {
|
|
190
215
|
return null;
|
|
191
216
|
}
|
|
@@ -48,7 +48,7 @@ export const getMeasureValue = ({ data, xAxis, yAxis, headerFormat, }) => {
|
|
|
48
48
|
const value = (_b = (_a = data[0].category) === null || _a === void 0 ? void 0 : _a.key) !== null && _b !== void 0 ? _b : null;
|
|
49
49
|
return { value };
|
|
50
50
|
}
|
|
51
|
-
if (data.some((item) => item.series.type
|
|
51
|
+
if (data.some((item) => ['bar-y', 'x-range'].includes(item.series.type))) {
|
|
52
52
|
const value = getYRowData((_c = data[0]) === null || _c === void 0 ? void 0 : _c.data, yAxis);
|
|
53
53
|
const formattedValue = getFormattedValue({
|
|
54
54
|
value: getYRowData((_d = data[0]) === null || _d === void 0 ? void 0 : _d.data, yAxis),
|
|
@@ -72,7 +72,9 @@ export function getHoveredValues(args) {
|
|
|
72
72
|
case 'area':
|
|
73
73
|
case 'line':
|
|
74
74
|
case 'bar-x':
|
|
75
|
-
case '
|
|
75
|
+
case 'waterfall':
|
|
76
|
+
case 'scatter':
|
|
77
|
+
case 'x-range': {
|
|
76
78
|
return getYRowData(data, yAxis);
|
|
77
79
|
}
|
|
78
80
|
case 'bar-y': {
|
|
@@ -90,9 +92,6 @@ export function getHoveredValues(args) {
|
|
|
90
92
|
const { target, data: source } = seriesItem;
|
|
91
93
|
return (_a = source.links.find((d) => d.name === (target === null || target === void 0 ? void 0 : target.name))) === null || _a === void 0 ? void 0 : _a.value;
|
|
92
94
|
}
|
|
93
|
-
case 'waterfall': {
|
|
94
|
-
return getYRowData(data, yAxis);
|
|
95
|
-
}
|
|
96
95
|
default: {
|
|
97
96
|
return undefined;
|
|
98
97
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const annotationLabelDefaults: {
|
|
2
|
+
style: {
|
|
3
|
+
fontSize: string;
|
|
4
|
+
fontColor: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export declare const annotationPopupDefaults: {
|
|
8
|
+
backgroundColor: string;
|
|
9
|
+
borderRadius: number;
|
|
10
|
+
offset: number;
|
|
11
|
+
padding: [number, number];
|
|
12
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const annotationLabelDefaults = {
|
|
2
|
+
style: {
|
|
3
|
+
fontSize: '13px',
|
|
4
|
+
fontColor: 'var(--g-color-text-light-primary)',
|
|
5
|
+
},
|
|
6
|
+
};
|
|
7
|
+
export const annotationPopupDefaults = {
|
|
8
|
+
backgroundColor: 'var(--g-color-base-float-heavy)',
|
|
9
|
+
borderRadius: 4,
|
|
10
|
+
offset: 5,
|
|
11
|
+
padding: [4, 8],
|
|
12
|
+
};
|
|
@@ -21,7 +21,11 @@ type DefaultWaterfallSeriesOptions = Partial<ChartSeriesOptions['waterfall']> &
|
|
|
21
21
|
barPadding: number;
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
|
-
export type SeriesOptionsDefaults = Partial<ChartSeriesOptions> & DefaultBarXSeriesOptions & DefaultBarYSeriesOptions & DefaultWaterfallSeriesOptions
|
|
24
|
+
export type SeriesOptionsDefaults = Partial<ChartSeriesOptions> & DefaultBarXSeriesOptions & DefaultBarYSeriesOptions & DefaultWaterfallSeriesOptions & {
|
|
25
|
+
'x-range': {
|
|
26
|
+
borderRadius: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
25
29
|
export declare const seriesOptionsDefaults: SeriesOptionsDefaults;
|
|
26
30
|
export declare const seriesRangeSliderOptionsDefaults: Required<ChartSeriesRangeSliderOptions>;
|
|
27
31
|
export {};
|
|
@@ -133,6 +133,19 @@ export const seriesOptionsDefaults = {
|
|
|
133
133
|
},
|
|
134
134
|
},
|
|
135
135
|
},
|
|
136
|
+
'x-range': {
|
|
137
|
+
borderRadius: 0,
|
|
138
|
+
states: {
|
|
139
|
+
hover: {
|
|
140
|
+
enabled: true,
|
|
141
|
+
brightness: 0.3,
|
|
142
|
+
},
|
|
143
|
+
inactive: {
|
|
144
|
+
enabled: false,
|
|
145
|
+
opacity: 0.5,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
136
149
|
};
|
|
137
150
|
export const seriesRangeSliderOptionsDefaults = {
|
|
138
151
|
visible: true,
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"label_invalid-axis-labels-html-not-supported-axis-type": "It seems you are trying to use \"labels.html\" property for an axis with an unsupported type. This property is supported only for \"category\" axis.",
|
|
22
22
|
"label_duplicate-axis-categories": "It seems you have duplicate value \"{{duplicate}}\" found in {{key}}[{{axisIndex}}].",
|
|
23
23
|
"label_invalid-axis-categories": "It seems you are trying to use inappropriate value for \"categories\", or defined it incorrectly. Categories must be a non-empty array for an axis with \"category\" type.",
|
|
24
|
-
"label_inconsistent-y-axis-configuration": "It seems you have inconsistent Y-axis configuration. Possible reasons:\n1. Multiple Y axes with the same position and plot index.\n2. At the moment, 'category' axis is not supported in dual Y-axis configurations."
|
|
24
|
+
"label_inconsistent-y-axis-configuration": "It seems you have inconsistent Y-axis configuration. Possible reasons:\n1. Multiple Y axes with the same position and plot index.\n2. At the moment, 'category' axis is not supported in dual Y-axis configurations.",
|
|
25
|
+
"label_stacking-area-connect-null-mode": "It seems you are using \"nullMode: 'connect'\" with a stacking area series. The \"connect\" null mode is not supported in stacking mode. Use \"zero\" or \"skip\" instead."
|
|
25
26
|
},
|
|
26
27
|
"tooltip": {
|
|
27
28
|
"label_totals_sum": "Sum",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"label_invalid-axis-labels-html-not-supported-axis-type": "Похоже, что вы пытаетесь использовать свойство \"labels.html\" для оси с неподдерживаемым типом. Это свойство поддерживается только для оси типа \"category\".",
|
|
22
22
|
"label_duplicate-axis-categories": "Похоже, что у вас есть дублирующееся значение категории \"{{duplicate}}\" в оси {{key}}[{{axisIndex}}].",
|
|
23
23
|
"label_invalid-axis-categories": "Похоже, что вы пытаетесь использовать недопустимое значение для \"categories\", или указали его неверно. Категории для оси типа \"category\" должны быть непустым массивом.",
|
|
24
|
-
"label_inconsistent-y-axis-configuration": "Похоже, что конфигурация осей Y неконсистентна. Возможные причины:\n1. Несколько осей Y имеют одинаковые значения position и plotIndex.\n2. На данный момент категорийные оси не поддерживаются в конфигурациях с двумя осями Y."
|
|
24
|
+
"label_inconsistent-y-axis-configuration": "Похоже, что конфигурация осей Y неконсистентна. Возможные причины:\n1. Несколько осей Y имеют одинаковые значения position и plotIndex.\n2. На данный момент категорийные оси не поддерживаются в конфигурациях с двумя осями Y.",
|
|
25
|
+
"label_stacking-area-connect-null-mode": "Похоже, что вы используете \"nullMode: 'connect'\" с серией area с накоплением. Режим null \"connect\" не поддерживается в режиме накопления. Используйте \"zero\" или \"skip\"."
|
|
25
26
|
},
|
|
26
27
|
"tooltip": {
|
|
27
28
|
"label_totals_sum": "Сумма",
|