@gravity-ui/charts 1.37.1 → 1.38.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/index.js +3 -2
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +24 -26
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +58 -21
- package/dist/cjs/components/Legend/index.d.ts +2 -1
- package/dist/cjs/components/Legend/index.js +17 -16
- package/dist/cjs/hooks/useAxis/index.d.ts +2 -1
- package/dist/cjs/hooks/useAxis/index.js +9 -2
- package/dist/cjs/hooks/useChartDimensions/index.d.ts +2 -1
- package/dist/cjs/hooks/useChartDimensions/index.js +27 -13
- package/dist/cjs/hooks/useChartOptions/tooltip.d.ts +5 -0
- package/dist/cjs/hooks/useChartOptions/tooltip.js +2 -2
- package/dist/cjs/hooks/useRangeSlider/index.js +2 -1
- package/dist/cjs/hooks/useRangeSlider/types.d.ts +2 -1
- package/dist/cjs/hooks/useSeries/prepare-legend.d.ts +4 -2
- package/dist/cjs/hooks/useSeries/prepare-legend.js +76 -55
- package/dist/cjs/hooks/useSeries/types.d.ts +1 -13
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/types/chart-ui.d.ts +15 -0
- package/dist/cjs/utils/chart/index.js +4 -2
- package/dist/cjs/utils/chart/text.js +4 -6
- package/dist/esm/components/ChartInner/index.js +3 -2
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +17 -19
- package/dist/esm/components/ChartInner/useChartInnerProps.js +58 -21
- package/dist/esm/components/Legend/index.d.ts +2 -1
- package/dist/esm/components/Legend/index.js +17 -16
- package/dist/esm/hooks/useAxis/index.d.ts +2 -1
- package/dist/esm/hooks/useAxis/index.js +9 -2
- package/dist/esm/hooks/useChartDimensions/index.d.ts +2 -1
- package/dist/esm/hooks/useChartDimensions/index.js +27 -13
- package/dist/esm/hooks/useChartOptions/tooltip.d.ts +5 -0
- package/dist/esm/hooks/useChartOptions/tooltip.js +2 -2
- package/dist/esm/hooks/useRangeSlider/index.js +2 -1
- package/dist/esm/hooks/useRangeSlider/types.d.ts +2 -1
- package/dist/esm/hooks/useSeries/prepare-legend.d.ts +4 -2
- package/dist/esm/hooks/useSeries/prepare-legend.js +76 -55
- package/dist/esm/hooks/useSeries/types.d.ts +1 -13
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/chart-ui.d.ts +15 -0
- package/dist/esm/utils/chart/index.js +4 -2
- package/dist/esm/utils/chart/text.js +4 -6
- package/package.json +1 -1
|
@@ -66,7 +66,8 @@ export const ChartInner = (props) => {
|
|
|
66
66
|
const { allPreparedSeries, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, isOutsideBounds, legendConfig, legendItems, preparedLegend, preparedSeries, preparedSeriesOptions, preparedSplit, prevHeight, prevWidth, shapes, shapesData, shapesReady, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
|
|
67
67
|
dispatcher,
|
|
68
68
|
htmlLayout, plotNode: plotRef.current, preparedChart,
|
|
69
|
-
rangeSliderState,
|
|
69
|
+
rangeSliderState,
|
|
70
|
+
updateZoomState,
|
|
70
71
|
zoomState }));
|
|
71
72
|
const debouncedBoundsWidth = useDebouncedValue({
|
|
72
73
|
value: boundsWidth,
|
|
@@ -248,7 +249,7 @@ export const ChartInner = (props) => {
|
|
|
248
249
|
React.createElement("g", { ref: plotBeforeRef }),
|
|
249
250
|
shapes,
|
|
250
251
|
React.createElement("g", { ref: plotAfterRef })),
|
|
251
|
-
((_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, ref: rangeSliderRef, width: width, xAxis: data.xAxis, yAxis: data.yAxis })),
|
|
252
|
+
((_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, ref: rangeSliderRef, width: width, xAxis: data.xAxis, yAxis: data.yAxis, legendConfig: legendConfig })),
|
|
252
253
|
(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 }))));
|
|
253
254
|
return (React.createElement("div", { className: b() },
|
|
254
255
|
React.createElement("svg", { ref: svgRef, width: width, height: height,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Dispatch } from 'd3';
|
|
3
|
-
import type { PreparedChart, PreparedLegend, RangeSliderState, ZoomState } from '../../hooks';
|
|
3
|
+
import type { LegendItem, PreparedChart, PreparedLegend, PreparedSeries, RangeSliderState, ZoomState } from '../../hooks';
|
|
4
|
+
import type { LegendConfig } from '../../types';
|
|
4
5
|
import type { ChartInnerProps } from './types';
|
|
5
6
|
type Props = ChartInnerProps & {
|
|
6
7
|
clipPathId: string;
|
|
@@ -8,35 +9,33 @@ type Props = ChartInnerProps & {
|
|
|
8
9
|
htmlLayout: HTMLElement | null;
|
|
9
10
|
plotNode: SVGGElement | null;
|
|
10
11
|
preparedChart: PreparedChart;
|
|
11
|
-
svgContainer: SVGGElement | null;
|
|
12
12
|
updateZoomState: (nextZoomState: Partial<ZoomState>) => void;
|
|
13
13
|
zoomState: Partial<ZoomState>;
|
|
14
14
|
rangeSliderState?: RangeSliderState;
|
|
15
15
|
};
|
|
16
|
+
type LegendState = {
|
|
17
|
+
legendConfig?: LegendConfig;
|
|
18
|
+
legendItems: LegendItem[][];
|
|
19
|
+
};
|
|
20
|
+
export declare function useLegend({ preparedLegend, preparedChart, preparedSeries, width, height, }: {
|
|
21
|
+
preparedLegend: PreparedLegend | null;
|
|
22
|
+
preparedChart: PreparedChart;
|
|
23
|
+
preparedSeries: PreparedSeries[];
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
}): LegendState;
|
|
16
27
|
export declare function useChartInnerProps(props: Props): {
|
|
17
|
-
allPreparedSeries:
|
|
28
|
+
allPreparedSeries: PreparedSeries[];
|
|
18
29
|
boundsHeight: number;
|
|
19
30
|
boundsOffsetLeft: number;
|
|
20
31
|
boundsOffsetTop: number;
|
|
21
32
|
boundsWidth: number;
|
|
22
33
|
handleLegendItemClick: import("../../hooks").OnLegendItemClick;
|
|
23
34
|
isOutsideBounds: (x: number, y: number) => boolean;
|
|
24
|
-
legendConfig:
|
|
25
|
-
|
|
26
|
-
left: number;
|
|
27
|
-
top: number;
|
|
28
|
-
};
|
|
29
|
-
pagination: {
|
|
30
|
-
pages: {
|
|
31
|
-
start: number;
|
|
32
|
-
end: number;
|
|
33
|
-
}[];
|
|
34
|
-
} | undefined;
|
|
35
|
-
maxWidth: number;
|
|
36
|
-
} | undefined;
|
|
37
|
-
legendItems: never[] | import("../../hooks").LegendItem[][];
|
|
35
|
+
legendConfig: LegendConfig | undefined;
|
|
36
|
+
legendItems: LegendItem[][];
|
|
38
37
|
preparedLegend: PreparedLegend | null;
|
|
39
|
-
preparedSeries:
|
|
38
|
+
preparedSeries: PreparedSeries[];
|
|
40
39
|
preparedSeriesOptions: import("../../constants").SeriesOptionsDefaults;
|
|
41
40
|
preparedSplit: import("../../hooks").PreparedSplit;
|
|
42
41
|
prevHeight: number | undefined;
|
|
@@ -44,13 +43,12 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
44
43
|
shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
|
|
45
44
|
shapesData: import("../../hooks").ShapeData[];
|
|
46
45
|
shapesReady: boolean;
|
|
47
|
-
svgXPos: number | undefined;
|
|
48
46
|
xAxis: import("../../hooks").PreparedXAxis | null;
|
|
49
47
|
xScale: import("../../hooks").ChartScale | undefined;
|
|
50
|
-
yAxis: (Omit<import("
|
|
51
|
-
type: import("
|
|
52
|
-
labels: Omit<import("
|
|
53
|
-
style: import("
|
|
48
|
+
yAxis: (Omit<import("../../types").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
|
|
49
|
+
type: import("../../types").ChartAxisType;
|
|
50
|
+
labels: Omit<import("../../types").ChartAxisLabels, "enabled" | "style" | "padding" | "autoRotation"> & Required<Pick<import("../../types").ChartAxisLabels, "margin" | "html" | "enabled" | "rotation" | "padding">> & {
|
|
51
|
+
style: import("../../types").BaseTextStyle;
|
|
54
52
|
rotation: number;
|
|
55
53
|
height: number;
|
|
56
54
|
width: number;
|
|
@@ -62,8 +60,8 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
62
60
|
width: number;
|
|
63
61
|
text: string;
|
|
64
62
|
margin: number;
|
|
65
|
-
style: import("
|
|
66
|
-
align: import("
|
|
63
|
+
style: import("../../types").BaseTextStyle;
|
|
64
|
+
align: import("../../types").ChartAxisTitleAlignment;
|
|
67
65
|
maxRowCount: number;
|
|
68
66
|
rotation: number;
|
|
69
67
|
maxWidth: number;
|
|
@@ -82,7 +80,7 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
82
80
|
plotIndex: number;
|
|
83
81
|
plotLines: import("../../hooks").PreparedAxisPlotLine[];
|
|
84
82
|
plotBands: import("../../hooks").PreparedAxisPlotBand[];
|
|
85
|
-
crosshair: Required<import("
|
|
83
|
+
crosshair: Required<import("../../types").AxisCrosshair>;
|
|
86
84
|
})[];
|
|
87
85
|
yScale: (import("../../hooks").ChartScale | undefined)[] | undefined;
|
|
88
86
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
2
3
|
import { DEFAULT_PALETTE, SERIES_TYPE } from '../../constants';
|
|
3
4
|
import { useAxis, useAxisScales, useChartDimensions, useNormalizedOriginalData, usePrevious, useSeries, useShapes, useSplit, useYAxisLabelWidth, useZoom, } from '../../hooks';
|
|
4
5
|
import { getYAxisWidth } from '../../hooks/useChartDimensions/utils';
|
|
@@ -9,17 +10,18 @@ import { hasAtLeastOneSeriesDataPerPlot } from './utils';
|
|
|
9
10
|
const CLIP_PATH_BY_SERIES_TYPE = {
|
|
10
11
|
[SERIES_TYPE.Scatter]: false,
|
|
11
12
|
};
|
|
12
|
-
function getBoundsOffsetTop(
|
|
13
|
-
|
|
13
|
+
function getBoundsOffsetTop({ chartMarginTop, preparedLegend, legendConfig, }) {
|
|
14
|
+
var _a;
|
|
14
15
|
return (chartMarginTop +
|
|
15
16
|
((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'top'
|
|
16
|
-
?
|
|
17
|
+
? ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.height) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin
|
|
17
18
|
: 0));
|
|
18
19
|
}
|
|
19
20
|
function getBoundsOffsetLeft(args) {
|
|
20
|
-
|
|
21
|
+
var _a;
|
|
22
|
+
const { chartMarginLeft, preparedLegend, yAxis, getYAxisWidth: getAxisWidth, legendConfig, } = args;
|
|
21
23
|
const legendOffset = (preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'left'
|
|
22
|
-
?
|
|
24
|
+
? ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.width) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin
|
|
23
25
|
: 0;
|
|
24
26
|
const leftAxisWidth = yAxis.reduce((acc, axis) => {
|
|
25
27
|
if (axis.position !== 'left') {
|
|
@@ -33,9 +35,47 @@ function getBoundsOffsetLeft(args) {
|
|
|
33
35
|
}, 0);
|
|
34
36
|
return chartMarginLeft + legendOffset + leftAxisWidth;
|
|
35
37
|
}
|
|
38
|
+
export function useLegend({ preparedLegend, preparedChart, preparedSeries, width, height, }) {
|
|
39
|
+
const [legendState, setLegend] = React.useState({
|
|
40
|
+
legendConfig: undefined,
|
|
41
|
+
legendItems: [],
|
|
42
|
+
});
|
|
43
|
+
const legendStateRunRef = React.useRef(0);
|
|
44
|
+
const prevLegendStateValue = React.useRef(legendState);
|
|
45
|
+
const legendStateReady = React.useRef(false);
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
legendStateRunRef.current++;
|
|
48
|
+
legendStateReady.current = false;
|
|
49
|
+
(async function () {
|
|
50
|
+
const currentRun = legendStateRunRef.current;
|
|
51
|
+
if (!preparedLegend) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const newStateValue = await getLegendComponents({
|
|
55
|
+
chartWidth: width,
|
|
56
|
+
chartHeight: height,
|
|
57
|
+
chartMargin: preparedChart.margin,
|
|
58
|
+
series: preparedSeries,
|
|
59
|
+
preparedLegend,
|
|
60
|
+
});
|
|
61
|
+
if (legendStateRunRef.current === currentRun) {
|
|
62
|
+
if (!isEqual(prevLegendStateValue.current, newStateValue)) {
|
|
63
|
+
setLegend(newStateValue);
|
|
64
|
+
prevLegendStateValue.current = newStateValue;
|
|
65
|
+
}
|
|
66
|
+
legendStateReady.current = true;
|
|
67
|
+
}
|
|
68
|
+
})();
|
|
69
|
+
}, [height, preparedChart.margin, preparedLegend, preparedSeries, width]);
|
|
70
|
+
return legendStateReady.current
|
|
71
|
+
? legendState
|
|
72
|
+
: {
|
|
73
|
+
legendConfig: undefined,
|
|
74
|
+
legendItems: [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
36
77
|
export function useChartInnerProps(props) {
|
|
37
|
-
|
|
38
|
-
const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, preparedChart, rangeSliderState, svgContainer, width, updateZoomState, zoomState, } = props;
|
|
78
|
+
const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, preparedChart, rangeSliderState, width, updateZoomState, zoomState, } = props;
|
|
39
79
|
const prevWidth = usePrevious(width);
|
|
40
80
|
const prevHeight = usePrevious(height);
|
|
41
81
|
const colors = React.useMemo(() => {
|
|
@@ -76,21 +116,17 @@ export function useChartInnerProps(props) {
|
|
|
76
116
|
zoomState: effectiveZoomState,
|
|
77
117
|
});
|
|
78
118
|
}, [allPreparedSeries, normalizedXAxis, normalizedYAxis, effectiveZoomState]);
|
|
79
|
-
const { legendConfig, legendItems } =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
chartMargin: preparedChart.margin,
|
|
87
|
-
series: preparedSeries,
|
|
88
|
-
preparedLegend,
|
|
89
|
-
});
|
|
90
|
-
}, [width, height, preparedChart.margin, preparedSeries, preparedLegend]);
|
|
119
|
+
const { legendConfig, legendItems } = useLegend({
|
|
120
|
+
width,
|
|
121
|
+
height,
|
|
122
|
+
preparedChart,
|
|
123
|
+
preparedSeries,
|
|
124
|
+
preparedLegend,
|
|
125
|
+
});
|
|
91
126
|
const { xAxis, yAxis, setAxes } = useAxis({
|
|
92
127
|
height,
|
|
93
128
|
preparedChart,
|
|
129
|
+
legendConfig,
|
|
94
130
|
preparedLegend,
|
|
95
131
|
preparedSeries,
|
|
96
132
|
preparedSeriesOptions,
|
|
@@ -106,6 +142,7 @@ export function useChartInnerProps(props) {
|
|
|
106
142
|
preparedYAxis: yAxis,
|
|
107
143
|
preparedXAxis: xAxis,
|
|
108
144
|
width,
|
|
145
|
+
legendConfig,
|
|
109
146
|
});
|
|
110
147
|
const preparedSplit = useSplit({ split: data.split, boundsHeight, chartWidth: width });
|
|
111
148
|
const { xScale, yScale } = useAxisScales({
|
|
@@ -166,6 +203,7 @@ export function useChartInnerProps(props) {
|
|
|
166
203
|
const boundsOffsetTop = getBoundsOffsetTop({
|
|
167
204
|
chartMarginTop: preparedChart.margin.top,
|
|
168
205
|
preparedLegend,
|
|
206
|
+
legendConfig,
|
|
169
207
|
});
|
|
170
208
|
// We need to calculate the width of each left axis because the first axis can be hidden
|
|
171
209
|
const boundsOffsetLeft = getBoundsOffsetLeft({
|
|
@@ -173,8 +211,8 @@ export function useChartInnerProps(props) {
|
|
|
173
211
|
preparedLegend,
|
|
174
212
|
yAxis,
|
|
175
213
|
getYAxisWidth,
|
|
214
|
+
legendConfig,
|
|
176
215
|
});
|
|
177
|
-
const { x } = (_a = svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {};
|
|
178
216
|
return {
|
|
179
217
|
allPreparedSeries,
|
|
180
218
|
boundsHeight,
|
|
@@ -194,7 +232,6 @@ export function useChartInnerProps(props) {
|
|
|
194
232
|
shapes,
|
|
195
233
|
shapesData,
|
|
196
234
|
shapesReady,
|
|
197
|
-
svgXPos: x,
|
|
198
235
|
xAxis,
|
|
199
236
|
xScale,
|
|
200
237
|
yAxis,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries } from '../../hooks';
|
|
3
|
+
import type { LegendConfig } from '../../types';
|
|
3
4
|
import './styles.css';
|
|
4
5
|
type Props = {
|
|
5
6
|
chartSeries: PreparedSeries[];
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { scaleLinear, select, symbol } from 'd3';
|
|
3
3
|
import { CONTINUOUS_LEGEND_SIZE } from '../../constants';
|
|
4
4
|
import { formatNumber } from '../../libs';
|
|
5
|
-
import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getSymbol, getUniqId,
|
|
5
|
+
import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getSymbol, getUniqId, } from '../../utils';
|
|
6
6
|
import { axisBottom } from '../../utils/chart/axis-generators';
|
|
7
7
|
import { appendLinePathElement } from '../utils';
|
|
8
8
|
import './styles.css';
|
|
@@ -163,7 +163,6 @@ export const Legend = (props) => {
|
|
|
163
163
|
: items;
|
|
164
164
|
const legendLineHeights = [];
|
|
165
165
|
pageItems.forEach((line) => {
|
|
166
|
-
var _a;
|
|
167
166
|
const legendLine = svgElement.append('g').attr('class', b('line'));
|
|
168
167
|
const htmlLegendLine = htmlContainer === null || htmlContainer === void 0 ? void 0 : htmlContainer.append('div').style('position', 'absolute');
|
|
169
168
|
const legendItemTemplate = legendLine
|
|
@@ -214,9 +213,8 @@ export const Legend = (props) => {
|
|
|
214
213
|
.on('click', function (e, d) {
|
|
215
214
|
onItemClick({ id: d.id, name: d.name, metaKey: e.metaKey });
|
|
216
215
|
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate();
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
});
|
|
216
|
+
})
|
|
217
|
+
.html((d) => d.text);
|
|
220
218
|
}
|
|
221
219
|
else {
|
|
222
220
|
legendItemTemplate
|
|
@@ -231,19 +229,22 @@ export const Legend = (props) => {
|
|
|
231
229
|
const mods = { selected: d.visible, unselected: !d.visible };
|
|
232
230
|
return b('item-text', mods);
|
|
233
231
|
})
|
|
234
|
-
.html(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
232
|
+
.html((d) => d.text)
|
|
233
|
+
.style('font-size', legend.itemStyle.fontSize);
|
|
234
|
+
}
|
|
235
|
+
let contentWidth = 0;
|
|
236
|
+
if (legend.html) {
|
|
237
|
+
contentWidth = getXPosition(line.length) - legend.itemDistance;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
contentWidth = line.reduce((sum, l, index) => {
|
|
241
|
+
sum += l.textWidth + l.symbol.width + l.symbol.padding;
|
|
242
|
+
if (index > 0) {
|
|
243
|
+
sum += legend.itemDistance;
|
|
241
244
|
}
|
|
242
|
-
|
|
245
|
+
return sum;
|
|
246
|
+
}, 0);
|
|
243
247
|
}
|
|
244
|
-
const contentWidth = (legend.html
|
|
245
|
-
? getXPosition(line.length) - legend.itemDistance
|
|
246
|
-
: (_a = legendLine.node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0;
|
|
247
248
|
let left = 0;
|
|
248
249
|
switch (legend.justifyContent) {
|
|
249
250
|
case 'center': {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { ChartXAxis, ChartYAxis } from '../../types';
|
|
2
|
+
import type { ChartXAxis, ChartYAxis, LegendConfig } from '../../types';
|
|
3
3
|
import type { PreparedChart } from '../useChartOptions/types';
|
|
4
4
|
import type { PreparedLegend, PreparedSeries, PreparedSeriesOptions } from '../useSeries/types';
|
|
5
5
|
import type { AxesState } from './types';
|
|
6
6
|
interface UseAxesProps {
|
|
7
7
|
height: number;
|
|
8
8
|
preparedChart: PreparedChart;
|
|
9
|
+
legendConfig: LegendConfig | undefined;
|
|
9
10
|
preparedLegend: PreparedLegend | null;
|
|
10
11
|
preparedSeries: PreparedSeries[];
|
|
11
12
|
preparedSeriesOptions: PreparedSeriesOptions;
|
|
@@ -4,15 +4,20 @@ import { getWidthOccupiedByYAxis } from '../useChartDimensions/utils';
|
|
|
4
4
|
import { getPreparedXAxis } from './x-axis';
|
|
5
5
|
import { getPreparedYAxis } from './y-axis';
|
|
6
6
|
export function useAxis(props) {
|
|
7
|
-
const { boundsHeight, height, preparedChart, preparedLegend, preparedSeries, preparedSeriesOptions, width, xAxis, yAxis, } = props;
|
|
7
|
+
const { boundsHeight, height, preparedChart, legendConfig, preparedLegend, preparedSeries, preparedSeriesOptions, width, xAxis, yAxis, } = props;
|
|
8
8
|
const [axesState, setAxes] = React.useState({ xAxis: null, yAxis: [] });
|
|
9
9
|
const axesStateRunRef = React.useRef(0);
|
|
10
10
|
const prevAxesStateValue = React.useRef(axesState);
|
|
11
11
|
const axesStateReady = React.useRef(false);
|
|
12
12
|
React.useEffect(() => {
|
|
13
|
+
const shouldWaitForLegendReady = !preparedLegend || ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && !legendConfig);
|
|
14
|
+
if (shouldWaitForLegendReady) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
13
17
|
axesStateRunRef.current++;
|
|
14
18
|
axesStateReady.current = false;
|
|
15
19
|
(async function () {
|
|
20
|
+
var _a, _b;
|
|
16
21
|
const currentRun = axesStateRunRef.current;
|
|
17
22
|
const seriesData = preparedSeries.filter((s) => s.visible);
|
|
18
23
|
const estimatedPreparedYAxis = await getPreparedYAxis({
|
|
@@ -41,7 +46,8 @@ export function useAxis(props) {
|
|
|
41
46
|
(preparedXAxis.rangeSlider.enabled
|
|
42
47
|
? preparedXAxis.rangeSlider.height + preparedXAxis.rangeSlider.margin
|
|
43
48
|
: 0) +
|
|
44
|
-
(
|
|
49
|
+
((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.height) !== null && _a !== void 0 ? _a : 0) +
|
|
50
|
+
((_b = preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.margin) !== null && _b !== void 0 ? _b : 0) +
|
|
45
51
|
preparedChart.margin.top +
|
|
46
52
|
preparedChart.margin.bottom);
|
|
47
53
|
}
|
|
@@ -65,6 +71,7 @@ export function useAxis(props) {
|
|
|
65
71
|
boundsHeight,
|
|
66
72
|
height,
|
|
67
73
|
preparedChart.margin,
|
|
74
|
+
legendConfig,
|
|
68
75
|
preparedLegend,
|
|
69
76
|
preparedSeries,
|
|
70
77
|
preparedSeriesOptions,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PreparedLegend, PreparedSeries, PreparedXAxis, PreparedYAxis } from '../../hooks';
|
|
2
|
-
import type { ChartMargin } from '../../types';
|
|
2
|
+
import type { ChartMargin, LegendConfig } from '../../types';
|
|
3
3
|
export { getBoundsWidth } from './utils';
|
|
4
4
|
type Args = {
|
|
5
5
|
height: number;
|
|
@@ -9,6 +9,7 @@ type Args = {
|
|
|
9
9
|
preparedXAxis: PreparedXAxis | null;
|
|
10
10
|
preparedYAxis: PreparedYAxis[] | null;
|
|
11
11
|
width: number;
|
|
12
|
+
legendConfig: LegendConfig | undefined;
|
|
12
13
|
};
|
|
13
14
|
export declare const useChartDimensions: (args: Args) => {
|
|
14
15
|
boundsWidth: number;
|
|
@@ -3,10 +3,11 @@ import { isAxisRelatedSeries } from '../../utils';
|
|
|
3
3
|
import { getBoundsWidth } from './utils';
|
|
4
4
|
export { getBoundsWidth } from './utils';
|
|
5
5
|
const getBottomOffset = (args) => {
|
|
6
|
-
|
|
6
|
+
var _a;
|
|
7
|
+
const { hasAxisRelatedSeries, preparedLegend, legendConfig, preparedXAxis } = args;
|
|
7
8
|
let result = 0;
|
|
8
9
|
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'bottom') {
|
|
9
|
-
result +=
|
|
10
|
+
result += ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.height) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin;
|
|
10
11
|
}
|
|
11
12
|
if (!(preparedXAxis === null || preparedXAxis === void 0 ? void 0 : preparedXAxis.visible)) {
|
|
12
13
|
return result;
|
|
@@ -24,26 +25,29 @@ const getBottomOffset = (args) => {
|
|
|
24
25
|
}
|
|
25
26
|
return result;
|
|
26
27
|
};
|
|
27
|
-
const getTopOffset = ({ preparedLegend }) => {
|
|
28
|
+
const getTopOffset = ({ preparedLegend, legendConfig, }) => {
|
|
29
|
+
var _a;
|
|
28
30
|
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'top') {
|
|
29
|
-
return
|
|
31
|
+
return ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.height) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin;
|
|
30
32
|
}
|
|
31
33
|
return 0;
|
|
32
34
|
};
|
|
33
|
-
const getRightOffset = ({ preparedLegend }) => {
|
|
35
|
+
const getRightOffset = ({ preparedLegend, legendConfig, }) => {
|
|
36
|
+
var _a;
|
|
34
37
|
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'right') {
|
|
35
|
-
return
|
|
38
|
+
return ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.width) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin;
|
|
36
39
|
}
|
|
37
40
|
return 0;
|
|
38
41
|
};
|
|
39
|
-
const getLeftOffset = ({ preparedLegend }) => {
|
|
42
|
+
const getLeftOffset = ({ preparedLegend, legendConfig, }) => {
|
|
43
|
+
var _a;
|
|
40
44
|
if ((preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) && preparedLegend.position === 'left') {
|
|
41
|
-
return
|
|
45
|
+
return ((_a = legendConfig === null || legendConfig === void 0 ? void 0 : legendConfig.width) !== null && _a !== void 0 ? _a : 0) + preparedLegend.margin;
|
|
42
46
|
}
|
|
43
47
|
return 0;
|
|
44
48
|
};
|
|
45
49
|
export const useChartDimensions = (args) => {
|
|
46
|
-
const { height, margin, preparedLegend, preparedSeries, preparedXAxis, preparedYAxis, width } = args;
|
|
50
|
+
const { height, margin, preparedLegend, preparedSeries, preparedXAxis, preparedYAxis, width, legendConfig, } = args;
|
|
47
51
|
return React.useMemo(() => {
|
|
48
52
|
const hasAxisRelatedSeries = preparedSeries.some(isAxisRelatedSeries);
|
|
49
53
|
const boundsWidth = getBoundsWidth({ chartWidth: width, chartMargin: margin, preparedYAxis });
|
|
@@ -51,12 +55,22 @@ export const useChartDimensions = (args) => {
|
|
|
51
55
|
hasAxisRelatedSeries,
|
|
52
56
|
preparedLegend,
|
|
53
57
|
preparedXAxis,
|
|
58
|
+
legendConfig,
|
|
54
59
|
});
|
|
55
|
-
const topOffset = getTopOffset({ preparedLegend });
|
|
56
|
-
const rightOffset = getRightOffset({ preparedLegend });
|
|
57
|
-
const leftOffset = getLeftOffset({ preparedLegend });
|
|
60
|
+
const topOffset = getTopOffset({ preparedLegend, legendConfig });
|
|
61
|
+
const rightOffset = getRightOffset({ preparedLegend, legendConfig });
|
|
62
|
+
const leftOffset = getLeftOffset({ preparedLegend, legendConfig });
|
|
58
63
|
const boundsHeight = height - margin.top - margin.bottom - bottomOffset - topOffset;
|
|
59
64
|
const adjustedBoundsWidth = boundsWidth - rightOffset - leftOffset;
|
|
60
65
|
return { boundsWidth: adjustedBoundsWidth, boundsHeight };
|
|
61
|
-
}, [
|
|
66
|
+
}, [
|
|
67
|
+
height,
|
|
68
|
+
margin,
|
|
69
|
+
preparedLegend,
|
|
70
|
+
legendConfig,
|
|
71
|
+
preparedSeries,
|
|
72
|
+
preparedXAxis,
|
|
73
|
+
preparedYAxis,
|
|
74
|
+
width,
|
|
75
|
+
]);
|
|
62
76
|
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { ChartData, ChartSeries, ChartXAxis, ChartYAxis } from '../../types';
|
|
2
2
|
import type { PreparedTooltip } from './types';
|
|
3
|
+
export declare function getDefaultTooltipHeaderFormat({ seriesData, yAxes, xAxis, }: {
|
|
4
|
+
seriesData: ChartSeries[];
|
|
5
|
+
yAxes?: ChartYAxis[];
|
|
6
|
+
xAxis?: ChartXAxis;
|
|
7
|
+
}): import("../../types").ValueFormat | undefined;
|
|
3
8
|
export declare const getPreparedTooltip: (args: {
|
|
4
9
|
tooltip: ChartData["tooltip"];
|
|
5
10
|
seriesData: ChartSeries[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
import { getDefaultValueFormat } from '../../components/Tooltip/DefaultTooltipContent/utils';
|
|
3
3
|
import { getDomainDataXBySeries, getDomainDataYBySeries, getMinSpaceBetween } from '../../utils';
|
|
4
|
-
function
|
|
4
|
+
export function getDefaultTooltipHeaderFormat({ seriesData, yAxes, xAxis, }) {
|
|
5
5
|
if (seriesData.every((item) => ['pie', 'treemap', 'waterfall', 'sankey', 'radar', 'heatmap', 'funnel'].includes(item.type))) {
|
|
6
6
|
return undefined;
|
|
7
7
|
}
|
|
@@ -17,5 +17,5 @@ function getDefaultHeaderFormat({ seriesData, yAxes, xAxis, }) {
|
|
|
17
17
|
export const getPreparedTooltip = (args) => {
|
|
18
18
|
var _a, _b;
|
|
19
19
|
const { tooltip, seriesData, yAxes, xAxis } = args;
|
|
20
|
-
return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0, headerFormat: (_b = tooltip === null || tooltip === void 0 ? void 0 : tooltip.headerFormat) !== null && _b !== void 0 ? _b :
|
|
20
|
+
return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true), throttle: (_a = tooltip === null || tooltip === void 0 ? void 0 : tooltip.throttle) !== null && _a !== void 0 ? _a : 0, headerFormat: (_b = tooltip === null || tooltip === void 0 ? void 0 : tooltip.headerFormat) !== null && _b !== void 0 ? _b : getDefaultTooltipHeaderFormat({ seriesData, yAxes, xAxis }) });
|
|
21
21
|
};
|
|
@@ -17,7 +17,7 @@ const CLIP_PATH_BY_SERIES_TYPE = {
|
|
|
17
17
|
[SERIES_TYPE.Scatter]: true,
|
|
18
18
|
};
|
|
19
19
|
export function useRangeSlider(props) {
|
|
20
|
-
const { boundsWidth, boundsOffsetLeft, clipPathId, height, htmlLayout, onUpdate, preparedChart, preparedLegend, preparedSeries, preparedSeriesOptions, preparedRangeSlider, rangeSliderState, width, xAxis, yAxis, } = props;
|
|
20
|
+
const { boundsWidth, boundsOffsetLeft, clipPathId, height, htmlLayout, onUpdate, preparedChart, preparedLegend, legendConfig, preparedSeries, preparedSeriesOptions, preparedRangeSlider, rangeSliderState, width, xAxis, yAxis, } = props;
|
|
21
21
|
const filteredPreparedSeries = React.useMemo(() => {
|
|
22
22
|
return preparedSeries.filter((s) => {
|
|
23
23
|
if ('rangeSlider' in s && !s.rangeSlider.visible) {
|
|
@@ -31,6 +31,7 @@ export function useRangeSlider(props) {
|
|
|
31
31
|
height,
|
|
32
32
|
preparedChart,
|
|
33
33
|
preparedLegend,
|
|
34
|
+
legendConfig,
|
|
34
35
|
preparedSeries,
|
|
35
36
|
preparedSeriesOptions,
|
|
36
37
|
width,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChartXAxis, ChartYAxis } from '../../types';
|
|
1
|
+
import type { ChartXAxis, ChartYAxis, LegendConfig } from '../../types';
|
|
2
2
|
import type { PreparedRangeSlider, PreparedXAxis, PreparedYAxis } from '../useAxis/types';
|
|
3
3
|
import type { ChartScale } from '../useAxisScales/types';
|
|
4
4
|
import type { BrushSelection, UseBrushProps } from '../useBrush/types';
|
|
@@ -16,6 +16,7 @@ export interface RangeSliderProps {
|
|
|
16
16
|
onUpdate: (nextRangeSliderState?: RangeSliderState) => void;
|
|
17
17
|
preparedChart: PreparedChart;
|
|
18
18
|
preparedLegend: PreparedLegend | null;
|
|
19
|
+
legendConfig: LegendConfig | undefined;
|
|
19
20
|
preparedRangeSlider: PreparedRangeSlider;
|
|
20
21
|
preparedSeries: PreparedSeries[];
|
|
21
22
|
preparedSeriesOptions: PreparedSeriesOptions;
|
|
@@ -11,7 +11,7 @@ export declare function getLegendComponents(args: {
|
|
|
11
11
|
chartMargin: PreparedChart['margin'];
|
|
12
12
|
series: PreparedSeries[];
|
|
13
13
|
preparedLegend: PreparedLegend;
|
|
14
|
-
}): {
|
|
14
|
+
}): Promise<{
|
|
15
15
|
legendConfig: {
|
|
16
16
|
offset: {
|
|
17
17
|
left: number;
|
|
@@ -24,6 +24,8 @@ export declare function getLegendComponents(args: {
|
|
|
24
24
|
}[];
|
|
25
25
|
} | undefined;
|
|
26
26
|
maxWidth: number;
|
|
27
|
+
height: number;
|
|
28
|
+
width: number;
|
|
27
29
|
};
|
|
28
30
|
legendItems: LegendItem[][];
|
|
29
|
-
}
|
|
31
|
+
}>;
|