@mui/x-charts 7.13.0 → 7.14.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/BarChart/BarPlot.js +4 -3
- package/BarChart/extremums.js +42 -7
- package/CHANGELOG.md +82 -2
- package/ChartContainer/useChartContainerProps.js +1 -1
- package/ChartContainer/useDefaultizeAxis.d.ts +2 -1
- package/ChartContainer/useDefaultizeAxis.js +16 -5
- package/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/ChartsGrid/ChartsGrid.js +6 -4
- package/ChartsXAxis/ChartsXAxis.js +14 -3
- package/ChartsYAxis/ChartsYAxis.js +8 -2
- package/LineChart/extremums.js +20 -4
- package/ScatterChart/extremums.js +26 -10
- package/context/CartesianProvider/Cartesian.types.d.ts +59 -0
- package/context/CartesianProvider/Cartesian.types.js +5 -0
- package/context/CartesianProvider/CartesianContext.d.ts +1 -22
- package/context/CartesianProvider/CartesianProvider.d.ts +1 -21
- package/context/CartesianProvider/CartesianProvider.js +2 -5
- package/context/CartesianProvider/computeValue.d.ts +18 -31
- package/context/CartesianProvider/computeValue.js +20 -23
- package/context/CartesianProvider/getAxisExtremum.d.ts +3 -2
- package/context/CartesianProvider/getAxisExtremum.js +11 -5
- package/context/CartesianProvider/index.d.ts +1 -0
- package/context/CartesianProvider/index.js +12 -0
- package/context/CartesianProvider/useCartesianContext.d.ts +1 -1
- package/context/CartesianProvider/zoom.d.ts +10 -0
- package/context/CartesianProvider/zoom.js +26 -0
- package/context/DrawingProvider.d.ts +7 -2
- package/context/DrawingProvider.js +11 -3
- package/context/PluginProvider/ExtremumGetter.types.d.ts +11 -1
- package/esm/BarChart/BarPlot.js +4 -3
- package/esm/BarChart/extremums.js +42 -7
- package/esm/ChartContainer/useChartContainerProps.js +1 -1
- package/esm/ChartContainer/useDefaultizeAxis.js +16 -5
- package/esm/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/esm/ChartsGrid/ChartsGrid.js +6 -4
- package/esm/ChartsXAxis/ChartsXAxis.js +14 -3
- package/esm/ChartsYAxis/ChartsYAxis.js +8 -2
- package/esm/LineChart/extremums.js +20 -4
- package/esm/ScatterChart/extremums.js +26 -10
- package/esm/context/CartesianProvider/Cartesian.types.js +1 -0
- package/esm/context/CartesianProvider/CartesianProvider.js +2 -5
- package/esm/context/CartesianProvider/computeValue.js +20 -23
- package/esm/context/CartesianProvider/getAxisExtremum.js +11 -5
- package/esm/context/CartesianProvider/index.js +1 -0
- package/esm/context/CartesianProvider/zoom.js +19 -0
- package/esm/context/DrawingProvider.js +11 -3
- package/esm/hooks/useAxisEvents.js +3 -1
- package/esm/internals/domUtils.js +16 -3
- package/esm/internals/index.js +3 -0
- package/esm/models/axis.js +5 -0
- package/esm/tests/firePointerEvent.js +35 -0
- package/hooks/useAxisEvents.js +3 -1
- package/index.js +1 -1
- package/internals/domUtils.d.ts +2 -0
- package/internals/domUtils.js +19 -5
- package/internals/index.d.ts +2 -0
- package/internals/index.js +17 -1
- package/models/axis.d.ts +4 -0
- package/models/axis.js +5 -0
- package/modern/BarChart/BarPlot.js +4 -3
- package/modern/BarChart/extremums.js +42 -7
- package/modern/ChartContainer/useChartContainerProps.js +1 -1
- package/modern/ChartContainer/useDefaultizeAxis.js +16 -5
- package/modern/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/modern/ChartsGrid/ChartsGrid.js +6 -4
- package/modern/ChartsXAxis/ChartsXAxis.js +14 -3
- package/modern/ChartsYAxis/ChartsYAxis.js +8 -2
- package/modern/LineChart/extremums.js +20 -4
- package/modern/ScatterChart/extremums.js +26 -10
- package/modern/context/CartesianProvider/Cartesian.types.js +1 -0
- package/modern/context/CartesianProvider/CartesianProvider.js +2 -5
- package/modern/context/CartesianProvider/computeValue.js +20 -23
- package/modern/context/CartesianProvider/getAxisExtremum.js +11 -5
- package/modern/context/CartesianProvider/index.js +1 -0
- package/modern/context/CartesianProvider/zoom.js +19 -0
- package/modern/context/DrawingProvider.js +11 -3
- package/modern/hooks/useAxisEvents.js +3 -1
- package/modern/index.js +1 -1
- package/modern/internals/domUtils.js +16 -3
- package/modern/internals/index.js +3 -0
- package/modern/models/axis.js +5 -0
- package/modern/tests/firePointerEvent.js +35 -0
- package/package.json +4 -4
- package/tests/firePointerEvent.js +42 -0
- package/context/CartesianProvider/normalizeAxis.d.ts +0 -5
- package/context/CartesianProvider/normalizeAxis.js +0 -23
- package/esm/context/CartesianProvider/normalizeAxis.js +0 -15
- package/modern/context/CartesianProvider/normalizeAxis.js +0 -15
|
@@ -92,7 +92,8 @@ function ChartsYAxis(inProps) {
|
|
|
92
92
|
left,
|
|
93
93
|
top,
|
|
94
94
|
width,
|
|
95
|
-
height
|
|
95
|
+
height,
|
|
96
|
+
isPointInside
|
|
96
97
|
} = useDrawingArea();
|
|
97
98
|
const tickSize = disableTicks ? 4 : tickSizeProp;
|
|
98
99
|
const yTicks = useTicks({
|
|
@@ -172,7 +173,12 @@ function ChartsYAxis(inProps) {
|
|
|
172
173
|
const xTickLabel = positionSign * (tickSize + 2);
|
|
173
174
|
const yTickLabel = labelOffset;
|
|
174
175
|
const skipLabel = typeof tickLabelInterval === 'function' && !tickLabelInterval?.(value, index);
|
|
175
|
-
const showLabel =
|
|
176
|
+
const showLabel = isPointInside({
|
|
177
|
+
x: -1,
|
|
178
|
+
y: offset
|
|
179
|
+
}, {
|
|
180
|
+
direction: 'y'
|
|
181
|
+
});
|
|
176
182
|
if (!showLabel) {
|
|
177
183
|
return null;
|
|
178
184
|
}
|
|
@@ -6,9 +6,18 @@ export const getExtremumX = params => {
|
|
|
6
6
|
const maxX = Math.max(...(axis.data ?? []));
|
|
7
7
|
return [minX, maxX];
|
|
8
8
|
};
|
|
9
|
-
function getSeriesExtremums(getValues, stackedData) {
|
|
10
|
-
return stackedData.reduce((seriesAcc, stackedValue) => {
|
|
9
|
+
function getSeriesExtremums(getValues, stackedData, filter) {
|
|
10
|
+
return stackedData.reduce((seriesAcc, stackedValue, index) => {
|
|
11
11
|
const [base, value] = getValues(stackedValue);
|
|
12
|
+
if (filter && (!filter({
|
|
13
|
+
y: base,
|
|
14
|
+
x: null
|
|
15
|
+
}, index) || !filter({
|
|
16
|
+
y: value,
|
|
17
|
+
x: null
|
|
18
|
+
}, index))) {
|
|
19
|
+
return seriesAcc;
|
|
20
|
+
}
|
|
12
21
|
return [Math.min(base, value, seriesAcc[0]), Math.max(base, value, seriesAcc[1])];
|
|
13
22
|
}, [Infinity, -Infinity]);
|
|
14
23
|
}
|
|
@@ -16,7 +25,8 @@ export const getExtremumY = params => {
|
|
|
16
25
|
const {
|
|
17
26
|
series,
|
|
18
27
|
axis,
|
|
19
|
-
isDefaultAxis
|
|
28
|
+
isDefaultAxis,
|
|
29
|
+
getFilters
|
|
20
30
|
} = params;
|
|
21
31
|
return Object.keys(series).filter(seriesId => {
|
|
22
32
|
const yAxisId = series[seriesId].yAxisId ?? series[seriesId].yAxisKey;
|
|
@@ -27,10 +37,16 @@ export const getExtremumY = params => {
|
|
|
27
37
|
stackedData
|
|
28
38
|
} = series[seriesId];
|
|
29
39
|
const isArea = area !== undefined;
|
|
40
|
+
const filter = getFilters?.({
|
|
41
|
+
currentAxisId: axis.id,
|
|
42
|
+
isDefaultAxis,
|
|
43
|
+
seriesXAxisId: series[seriesId].xAxisId ?? series[seriesId].xAxisKey,
|
|
44
|
+
seriesYAxisId: series[seriesId].yAxisId ?? series[seriesId].yAxisKey
|
|
45
|
+
});
|
|
30
46
|
|
|
31
47
|
// Since this series is not used to display an area, we do not consider the base (the d[0]).
|
|
32
48
|
const getValues = isArea && axis.scaleType !== 'log' && typeof series[seriesId].baseline !== 'string' ? d => d : d => [d[1], d[1]];
|
|
33
|
-
const seriesExtremums = getSeriesExtremums(getValues, stackedData);
|
|
49
|
+
const seriesExtremums = getSeriesExtremums(getValues, stackedData, filter);
|
|
34
50
|
const [seriesMin, seriesMax] = seriesExtremums;
|
|
35
51
|
return [Math.min(seriesMin, acc[0]), Math.max(seriesMax, acc[1])];
|
|
36
52
|
}, [Infinity, -Infinity]);
|
|
@@ -5,16 +5,24 @@ export const getExtremumX = params => {
|
|
|
5
5
|
const {
|
|
6
6
|
series,
|
|
7
7
|
axis,
|
|
8
|
-
isDefaultAxis
|
|
8
|
+
isDefaultAxis,
|
|
9
|
+
getFilters
|
|
9
10
|
} = params;
|
|
10
11
|
return Object.keys(series).filter(seriesId => {
|
|
11
12
|
const axisId = series[seriesId].xAxisId ?? series[seriesId].xAxisKey;
|
|
12
13
|
return axisId === axis.id || axisId === undefined && isDefaultAxis;
|
|
13
14
|
}).reduce((acc, seriesId) => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const filter = getFilters?.({
|
|
16
|
+
currentAxisId: axis.id,
|
|
17
|
+
isDefaultAxis,
|
|
18
|
+
seriesXAxisId: series[seriesId].xAxisId ?? series[seriesId].xAxisKey,
|
|
19
|
+
seriesYAxisId: series[seriesId].yAxisId ?? series[seriesId].yAxisKey
|
|
20
|
+
});
|
|
21
|
+
const seriesMinMax = series[seriesId].data.reduce((accSeries, d, dataIndex) => {
|
|
22
|
+
if (filter && !filter(d, dataIndex)) {
|
|
23
|
+
return accSeries;
|
|
24
|
+
}
|
|
25
|
+
return mergeMinMax(accSeries, [d.x, d.x]);
|
|
18
26
|
}, [Infinity, -Infinity]);
|
|
19
27
|
return mergeMinMax(acc, seriesMinMax);
|
|
20
28
|
}, [Infinity, -Infinity]);
|
|
@@ -23,16 +31,24 @@ export const getExtremumY = params => {
|
|
|
23
31
|
const {
|
|
24
32
|
series,
|
|
25
33
|
axis,
|
|
26
|
-
isDefaultAxis
|
|
34
|
+
isDefaultAxis,
|
|
35
|
+
getFilters
|
|
27
36
|
} = params;
|
|
28
37
|
return Object.keys(series).filter(seriesId => {
|
|
29
38
|
const axisId = series[seriesId].yAxisId ?? series[seriesId].yAxisKey;
|
|
30
39
|
return axisId === axis.id || axisId === undefined && isDefaultAxis;
|
|
31
40
|
}).reduce((acc, seriesId) => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
const filter = getFilters?.({
|
|
42
|
+
currentAxisId: axis.id,
|
|
43
|
+
isDefaultAxis,
|
|
44
|
+
seriesXAxisId: series[seriesId].xAxisId ?? series[seriesId].xAxisKey,
|
|
45
|
+
seriesYAxisId: series[seriesId].yAxisId ?? series[seriesId].yAxisKey
|
|
46
|
+
});
|
|
47
|
+
const seriesMinMax = series[seriesId].data.reduce((accSeries, d, dataIndex) => {
|
|
48
|
+
if (filter && !filter(d, dataIndex)) {
|
|
49
|
+
return accSeries;
|
|
50
|
+
}
|
|
51
|
+
return mergeMinMax(accSeries, [d.y, d.y]);
|
|
36
52
|
}, [Infinity, -Infinity]);
|
|
37
53
|
return mergeMinMax(acc, seriesMinMax);
|
|
38
54
|
}, [Infinity, -Infinity]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,7 +10,6 @@ function CartesianProvider(props) {
|
|
|
10
10
|
const {
|
|
11
11
|
xAxis,
|
|
12
12
|
yAxis,
|
|
13
|
-
dataset,
|
|
14
13
|
children
|
|
15
14
|
} = props;
|
|
16
15
|
const formattedSeries = useSeries();
|
|
@@ -22,17 +21,15 @@ function CartesianProvider(props) {
|
|
|
22
21
|
formattedSeries,
|
|
23
22
|
axis: xAxis,
|
|
24
23
|
extremumGetters: xExtremumGetters,
|
|
25
|
-
dataset,
|
|
26
24
|
axisDirection: 'x'
|
|
27
|
-
}), [drawingArea, formattedSeries, xAxis, xExtremumGetters
|
|
25
|
+
}), [drawingArea, formattedSeries, xAxis, xExtremumGetters]);
|
|
28
26
|
const yValues = React.useMemo(() => computeValue({
|
|
29
27
|
drawingArea,
|
|
30
28
|
formattedSeries,
|
|
31
29
|
axis: yAxis,
|
|
32
30
|
extremumGetters: yExtremumGetters,
|
|
33
|
-
dataset,
|
|
34
31
|
axisDirection: 'y'
|
|
35
|
-
}), [drawingArea, formattedSeries, yAxis, yExtremumGetters
|
|
32
|
+
}), [drawingArea, formattedSeries, yAxis, yExtremumGetters]);
|
|
36
33
|
const value = React.useMemo(() => ({
|
|
37
34
|
isInitialized: true,
|
|
38
35
|
data: {
|
|
@@ -4,22 +4,12 @@ import { isBandScaleConfig, isPointScaleConfig } from '../../models/axis';
|
|
|
4
4
|
import { getColorScale, getOrdinalColorScale } from '../../internals/colorScale';
|
|
5
5
|
import { getTickNumber } from '../../hooks/useTicks';
|
|
6
6
|
import { getScale } from '../../internals/getScale';
|
|
7
|
+
import { zoomScaleRange } from './zoom';
|
|
7
8
|
import { getAxisExtremum } from './getAxisExtremum';
|
|
8
|
-
import { normalizeAxis } from './normalizeAxis';
|
|
9
9
|
const getRange = (drawingArea, axisDirection, isReverse) => {
|
|
10
10
|
const range = axisDirection === 'x' ? [drawingArea.left, drawingArea.left + drawingArea.width] : [drawingArea.top + drawingArea.height, drawingArea.top];
|
|
11
11
|
return isReverse ? range.reverse() : range;
|
|
12
12
|
};
|
|
13
|
-
const zoomedScaleRange = (scaleRange, zoomRange) => {
|
|
14
|
-
const rangeGap = scaleRange[1] - scaleRange[0];
|
|
15
|
-
const zoomGap = zoomRange[1] - zoomRange[0];
|
|
16
|
-
|
|
17
|
-
// If current zoom show the scale between p1 and p2 percents
|
|
18
|
-
// The range should be extended by adding [0, p1] and [p2, 100] segments
|
|
19
|
-
const min = scaleRange[0] - zoomRange[0] * rangeGap / zoomGap;
|
|
20
|
-
const max = scaleRange[1] + (100 - zoomRange[1]) * rangeGap / zoomGap;
|
|
21
|
-
return [min, max];
|
|
22
|
-
};
|
|
23
13
|
const isDateData = data => data?.[0] instanceof Date;
|
|
24
14
|
function createDateFormatter(axis, range) {
|
|
25
15
|
const timeScale = scaleTime(axis.data, range);
|
|
@@ -32,32 +22,37 @@ const DEFAULT_BAR_GAP_RATIO = 0.1;
|
|
|
32
22
|
export function computeValue({
|
|
33
23
|
drawingArea,
|
|
34
24
|
formattedSeries,
|
|
35
|
-
axis:
|
|
25
|
+
axis: allAxis,
|
|
36
26
|
extremumGetters,
|
|
37
|
-
dataset,
|
|
38
27
|
axisDirection,
|
|
39
|
-
zoomData
|
|
28
|
+
zoomData,
|
|
29
|
+
zoomOptions,
|
|
30
|
+
getFilters
|
|
40
31
|
}) {
|
|
41
|
-
const allAxis = normalizeAxis(inAxis, dataset, axisDirection);
|
|
42
32
|
const completeAxis = {};
|
|
43
|
-
allAxis.forEach((
|
|
33
|
+
allAxis.forEach((eachAxis, axisIndex) => {
|
|
34
|
+
const axis = eachAxis;
|
|
44
35
|
const isDefaultAxis = axisIndex === 0;
|
|
45
|
-
const
|
|
36
|
+
const zoomOption = zoomOptions?.[axis.id];
|
|
46
37
|
const zoom = zoomData?.find(({
|
|
47
38
|
axisId
|
|
48
39
|
}) => axisId === axis.id);
|
|
49
40
|
const zoomRange = zoom ? [zoom.start, zoom.end] : [0, 100];
|
|
50
41
|
const range = getRange(drawingArea, axisDirection, axis.reverse);
|
|
42
|
+
const [minData, maxData] = getAxisExtremum(axis, extremumGetters, isDefaultAxis, formattedSeries, zoom === undefined && !zoomOption ? getFilters : undefined // Do not apply filtering if zoom is already defined.
|
|
43
|
+
);
|
|
44
|
+
const data = axis.data ?? [];
|
|
51
45
|
if (isBandScaleConfig(axis)) {
|
|
52
46
|
const categoryGapRatio = axis.categoryGapRatio ?? DEFAULT_CATEGORY_GAP_RATIO;
|
|
53
47
|
const barGapRatio = axis.barGapRatio ?? DEFAULT_BAR_GAP_RATIO;
|
|
54
48
|
// Reverse range because ordinal scales are presented from top to bottom on y-axis
|
|
55
49
|
const scaleRange = axisDirection === 'x' ? range : [range[1], range[0]];
|
|
56
|
-
const zoomedRange =
|
|
50
|
+
const zoomedRange = zoomScaleRange(scaleRange, zoomRange);
|
|
57
51
|
completeAxis[axis.id] = _extends({
|
|
58
52
|
categoryGapRatio,
|
|
59
53
|
barGapRatio
|
|
60
54
|
}, axis, {
|
|
55
|
+
data,
|
|
61
56
|
scale: scaleBand(axis.data, zoomedRange).paddingInner(categoryGapRatio).paddingOuter(categoryGapRatio / 2),
|
|
62
57
|
tickNumber: axis.data.length,
|
|
63
58
|
colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? getOrdinalColorScale(_extends({
|
|
@@ -71,8 +66,9 @@ export function computeValue({
|
|
|
71
66
|
}
|
|
72
67
|
if (isPointScaleConfig(axis)) {
|
|
73
68
|
const scaleRange = axisDirection === 'x' ? range : [...range].reverse();
|
|
74
|
-
const zoomedRange =
|
|
69
|
+
const zoomedRange = zoomScaleRange(scaleRange, zoomRange);
|
|
75
70
|
completeAxis[axis.id] = _extends({}, axis, {
|
|
71
|
+
data,
|
|
76
72
|
scale: scalePoint(axis.data, zoomedRange),
|
|
77
73
|
tickNumber: axis.data.length,
|
|
78
74
|
colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? getOrdinalColorScale(_extends({
|
|
@@ -89,19 +85,20 @@ export function computeValue({
|
|
|
89
85
|
return;
|
|
90
86
|
}
|
|
91
87
|
const scaleType = axis.scaleType ?? 'linear';
|
|
92
|
-
const
|
|
88
|
+
const axisExtremums = [axis.min ?? minData, axis.max ?? maxData];
|
|
93
89
|
const rawTickNumber = getTickNumber(_extends({}, axis, {
|
|
94
90
|
range,
|
|
95
|
-
domain:
|
|
91
|
+
domain: axisExtremums
|
|
96
92
|
}));
|
|
97
93
|
const tickNumber = rawTickNumber / ((zoomRange[1] - zoomRange[0]) / 100);
|
|
98
|
-
const zoomedRange =
|
|
94
|
+
const zoomedRange = zoomScaleRange(range, zoomRange);
|
|
99
95
|
|
|
100
96
|
// TODO: move nice to prop? Disable when there is zoom?
|
|
101
|
-
const scale = getScale(scaleType,
|
|
97
|
+
const scale = getScale(scaleType, axisExtremums, zoomedRange).nice(rawTickNumber);
|
|
102
98
|
const [minDomain, maxDomain] = scale.domain();
|
|
103
99
|
const domain = [axis.min ?? minDomain, axis.max ?? maxDomain];
|
|
104
100
|
completeAxis[axis.id] = _extends({}, axis, {
|
|
101
|
+
data,
|
|
105
102
|
scaleType: scaleType,
|
|
106
103
|
scale: scale.domain(domain),
|
|
107
104
|
tickNumber,
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
const axisExtremumCallback = (acc, chartType, axis, getters, isDefaultAxis, formattedSeries) => {
|
|
1
|
+
const axisExtremumCallback = (acc, chartType, axis, getters, isDefaultAxis, formattedSeries, getFilters) => {
|
|
2
2
|
const getter = getters[chartType];
|
|
3
3
|
const series = formattedSeries[chartType]?.series ?? {};
|
|
4
4
|
const [minChartTypeData, maxChartTypeData] = getter?.({
|
|
5
5
|
series,
|
|
6
6
|
axis,
|
|
7
|
-
isDefaultAxis
|
|
7
|
+
isDefaultAxis,
|
|
8
|
+
getFilters
|
|
8
9
|
}) ?? [Infinity, -Infinity];
|
|
9
|
-
|
|
10
|
+
const [minData, maxData] = acc;
|
|
11
|
+
return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)];
|
|
10
12
|
};
|
|
11
|
-
export const getAxisExtremum = (axis, getters, isDefaultAxis, formattedSeries) => {
|
|
13
|
+
export const getAxisExtremum = (axis, getters, isDefaultAxis, formattedSeries, getFilters) => {
|
|
12
14
|
const charTypes = Object.keys(getters);
|
|
13
|
-
|
|
15
|
+
const extremums = charTypes.reduce((acc, charType) => axisExtremumCallback(acc, charType, axis, getters, isDefaultAxis, formattedSeries, getFilters), [Infinity, -Infinity]);
|
|
16
|
+
if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) {
|
|
17
|
+
return [Infinity, -Infinity];
|
|
18
|
+
}
|
|
19
|
+
return extremums;
|
|
14
20
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Applies the zoom into the scale range.
|
|
3
|
+
* It changes the screen coordinates that the scale covers.
|
|
4
|
+
* Not the data that is displayed.
|
|
5
|
+
*
|
|
6
|
+
* @param scaleRange the original range in real screen coordinates.
|
|
7
|
+
* @param zoomRange the zoom range in percentage.
|
|
8
|
+
* @returns zoomed range in real screen coordinates.
|
|
9
|
+
*/
|
|
10
|
+
export const zoomScaleRange = (scaleRange, zoomRange) => {
|
|
11
|
+
const rangeGap = scaleRange[1] - scaleRange[0];
|
|
12
|
+
const zoomGap = zoomRange[1] - zoomRange[0];
|
|
13
|
+
|
|
14
|
+
// If current zoom show the scale between p1 and p2 percents
|
|
15
|
+
// The range should be extended by adding [0, p1] and [p2, 100] segments
|
|
16
|
+
const min = scaleRange[0] - zoomRange[0] * rangeGap / zoomGap;
|
|
17
|
+
const max = scaleRange[1] + (100 - zoomRange[1]) * rangeGap / zoomGap;
|
|
18
|
+
return [min, max];
|
|
19
|
+
};
|
|
@@ -42,12 +42,20 @@ export function DrawingProvider(props) {
|
|
|
42
42
|
const isPointInside = React.useCallback(({
|
|
43
43
|
x,
|
|
44
44
|
y
|
|
45
|
-
},
|
|
45
|
+
}, options) => {
|
|
46
46
|
// For element allowed to overflow, wrapping them in <g data-drawing-container /> make them fully part of the drawing area.
|
|
47
|
-
if (targetElement && targetElement.closest('[data-drawing-container]')) {
|
|
47
|
+
if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) {
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width;
|
|
51
|
+
const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height;
|
|
52
|
+
if (options?.direction === 'x') {
|
|
53
|
+
return isInsideX;
|
|
54
|
+
}
|
|
55
|
+
if (options?.direction === 'y') {
|
|
56
|
+
return isInsideY;
|
|
57
|
+
}
|
|
58
|
+
return isInsideX && isInsideY;
|
|
51
59
|
}, [drawingArea]);
|
|
52
60
|
const value = React.useMemo(() => _extends({
|
|
53
61
|
chartId: chartId ?? ''
|
|
@@ -98,7 +98,9 @@ export const useAxisEvents = disableAxisListener => {
|
|
|
98
98
|
const svgPoint = getSVGPoint(element, target);
|
|
99
99
|
mousePosition.current.x = svgPoint.x;
|
|
100
100
|
mousePosition.current.y = svgPoint.y;
|
|
101
|
-
if (!drawingArea.isPointInside(svgPoint,
|
|
101
|
+
if (!drawingArea.isPointInside(svgPoint, {
|
|
102
|
+
targetElement: event.target
|
|
103
|
+
})) {
|
|
102
104
|
if (mousePosition.current.isInChart) {
|
|
103
105
|
dispatch({
|
|
104
106
|
type: 'exitChart'
|
|
@@ -20,7 +20,7 @@ const SPAN_STYLE = {
|
|
|
20
20
|
whiteSpace: 'pre'
|
|
21
21
|
};
|
|
22
22
|
const STYLE_LIST = ['minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height', 'top', 'left', 'fontSize', 'padding', 'margin', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom'];
|
|
23
|
-
const MEASUREMENT_SPAN_ID = 'mui_measurement_span';
|
|
23
|
+
export const MEASUREMENT_SPAN_ID = 'mui_measurement_span';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
*
|
|
@@ -57,7 +57,7 @@ function camelToMiddleLine(text) {
|
|
|
57
57
|
* @returns CSS styling string
|
|
58
58
|
*/
|
|
59
59
|
export const getStyleString = style => Object.keys(style).sort().reduce((result, s) => `${result}${camelToMiddleLine(s)}:${autoCompleteStyle(s, style[s])};`, '');
|
|
60
|
-
|
|
60
|
+
let domCleanTimeout;
|
|
61
61
|
/**
|
|
62
62
|
*
|
|
63
63
|
* @param text The string to estimate
|
|
@@ -105,6 +105,13 @@ export const getStringSize = (text, style = {}) => {
|
|
|
105
105
|
} else {
|
|
106
106
|
stringCache.cacheCount += 1;
|
|
107
107
|
}
|
|
108
|
+
if (domCleanTimeout) {
|
|
109
|
+
clearTimeout(domCleanTimeout);
|
|
110
|
+
}
|
|
111
|
+
domCleanTimeout = setTimeout(() => {
|
|
112
|
+
// Limit node cleaning to once per render cycle
|
|
113
|
+
measurementSpan.textContent = '';
|
|
114
|
+
}, 0);
|
|
108
115
|
return result;
|
|
109
116
|
} catch (e) {
|
|
110
117
|
return {
|
|
@@ -112,4 +119,10 @@ export const getStringSize = (text, style = {}) => {
|
|
|
112
119
|
height: 0
|
|
113
120
|
};
|
|
114
121
|
}
|
|
115
|
-
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
125
|
+
export function unstable_cleanupDOM() {
|
|
126
|
+
// const measurementSpan = document.getElementById(MEASUREMENT_SPAN_ID);
|
|
127
|
+
// measurementSpan?.remove();
|
|
128
|
+
}
|
package/esm/internals/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export * from './configInit';
|
|
|
20
20
|
export * from './getLabel';
|
|
21
21
|
export * from './getSVGPoint';
|
|
22
22
|
export * from './isDefined';
|
|
23
|
+
export { unstable_cleanupDOM } from './domUtils';
|
|
23
24
|
|
|
24
25
|
// contexts
|
|
25
26
|
|
|
@@ -29,6 +30,8 @@ export * from '../context/InteractionProvider';
|
|
|
29
30
|
export * from '../context/SeriesProvider';
|
|
30
31
|
export * from '../context/ZAxisContextProvider';
|
|
31
32
|
export * from '../context/PluginProvider';
|
|
33
|
+
export { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum';
|
|
34
|
+
|
|
32
35
|
// series configuration
|
|
33
36
|
export * from '../models/seriesType/config';
|
|
34
37
|
export * from '../models/seriesType/common';
|
package/esm/models/axis.js
CHANGED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
import { fireEvent } from '@mui/internal-test-utils';
|
|
3
|
+
export function firePointerEvent(target, type, options) {
|
|
4
|
+
const originalGetBoundingClientRect = target.getBoundingClientRect;
|
|
5
|
+
target.getBoundingClientRect = () => ({
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
bottom: 0,
|
|
9
|
+
height: 0,
|
|
10
|
+
left: 0,
|
|
11
|
+
right: 0,
|
|
12
|
+
top: 0,
|
|
13
|
+
width: 0,
|
|
14
|
+
toJSON() {
|
|
15
|
+
return {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0,
|
|
18
|
+
bottom: 0,
|
|
19
|
+
height: 0,
|
|
20
|
+
left: 0,
|
|
21
|
+
right: 0,
|
|
22
|
+
top: 0,
|
|
23
|
+
width: 0
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const event = new window.PointerEvent(type, _extends({
|
|
28
|
+
bubbles: true,
|
|
29
|
+
cancelable: true,
|
|
30
|
+
composed: true,
|
|
31
|
+
isPrimary: true
|
|
32
|
+
}, options));
|
|
33
|
+
fireEvent(target, event);
|
|
34
|
+
target.getBoundingClientRect = originalGetBoundingClientRect;
|
|
35
|
+
}
|
package/hooks/useAxisEvents.js
CHANGED
|
@@ -106,7 +106,9 @@ const useAxisEvents = disableAxisListener => {
|
|
|
106
106
|
const svgPoint = (0, _getSVGPoint.getSVGPoint)(element, target);
|
|
107
107
|
mousePosition.current.x = svgPoint.x;
|
|
108
108
|
mousePosition.current.y = svgPoint.y;
|
|
109
|
-
if (!drawingArea.isPointInside(svgPoint,
|
|
109
|
+
if (!drawingArea.isPointInside(svgPoint, {
|
|
110
|
+
targetElement: event.target
|
|
111
|
+
})) {
|
|
110
112
|
if (mousePosition.current.isInChart) {
|
|
111
113
|
dispatch({
|
|
112
114
|
type: 'exitChart'
|
package/index.js
CHANGED
package/internals/domUtils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const MEASUREMENT_SPAN_ID = "mui_measurement_span";
|
|
1
2
|
/**
|
|
2
3
|
*
|
|
3
4
|
* @param style React style object
|
|
@@ -11,3 +12,4 @@ export declare const getStyleString: (style: React.CSSProperties) => string;
|
|
|
11
12
|
* @returns width and height of the text
|
|
12
13
|
*/
|
|
13
14
|
export declare const getStringSize: (text: string | number, style?: React.CSSProperties) => any;
|
|
15
|
+
export declare function unstable_cleanupDOM(): void;
|
package/internals/domUtils.js
CHANGED
|
@@ -4,7 +4,8 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.getStyleString = exports.getStringSize = void 0;
|
|
7
|
+
exports.getStyleString = exports.getStringSize = exports.MEASUREMENT_SPAN_ID = void 0;
|
|
8
|
+
exports.unstable_cleanupDOM = unstable_cleanupDOM;
|
|
8
9
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
10
|
// DOM utils taken from
|
|
10
11
|
// https://github.com/recharts/recharts/blob/master/src/util/DOMUtils.ts
|
|
@@ -27,7 +28,7 @@ const SPAN_STYLE = {
|
|
|
27
28
|
whiteSpace: 'pre'
|
|
28
29
|
};
|
|
29
30
|
const STYLE_LIST = ['minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height', 'top', 'left', 'fontSize', 'padding', 'margin', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom'];
|
|
30
|
-
const MEASUREMENT_SPAN_ID = 'mui_measurement_span';
|
|
31
|
+
const MEASUREMENT_SPAN_ID = exports.MEASUREMENT_SPAN_ID = 'mui_measurement_span';
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
*
|
|
@@ -64,14 +65,14 @@ function camelToMiddleLine(text) {
|
|
|
64
65
|
* @returns CSS styling string
|
|
65
66
|
*/
|
|
66
67
|
const getStyleString = style => Object.keys(style).sort().reduce((result, s) => `${result}${camelToMiddleLine(s)}:${autoCompleteStyle(s, style[s])};`, '');
|
|
67
|
-
|
|
68
|
+
exports.getStyleString = getStyleString;
|
|
69
|
+
let domCleanTimeout;
|
|
68
70
|
/**
|
|
69
71
|
*
|
|
70
72
|
* @param text The string to estimate
|
|
71
73
|
* @param style The style applied
|
|
72
74
|
* @returns width and height of the text
|
|
73
75
|
*/
|
|
74
|
-
exports.getStyleString = getStyleString;
|
|
75
76
|
const getStringSize = (text, style = {}) => {
|
|
76
77
|
if (text === undefined || text === null || isSsr()) {
|
|
77
78
|
return {
|
|
@@ -113,6 +114,13 @@ const getStringSize = (text, style = {}) => {
|
|
|
113
114
|
} else {
|
|
114
115
|
stringCache.cacheCount += 1;
|
|
115
116
|
}
|
|
117
|
+
if (domCleanTimeout) {
|
|
118
|
+
clearTimeout(domCleanTimeout);
|
|
119
|
+
}
|
|
120
|
+
domCleanTimeout = setTimeout(() => {
|
|
121
|
+
// Limit node cleaning to once per render cycle
|
|
122
|
+
measurementSpan.textContent = '';
|
|
123
|
+
}, 0);
|
|
116
124
|
return result;
|
|
117
125
|
} catch (e) {
|
|
118
126
|
return {
|
|
@@ -121,4 +129,10 @@ const getStringSize = (text, style = {}) => {
|
|
|
121
129
|
};
|
|
122
130
|
}
|
|
123
131
|
};
|
|
124
|
-
|
|
132
|
+
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
134
|
+
exports.getStringSize = getStringSize;
|
|
135
|
+
function unstable_cleanupDOM() {
|
|
136
|
+
// const measurementSpan = document.getElementById(MEASUREMENT_SPAN_ID);
|
|
137
|
+
// measurementSpan?.remove();
|
|
138
|
+
}
|
package/internals/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './configInit';
|
|
|
15
15
|
export * from './getLabel';
|
|
16
16
|
export * from './getSVGPoint';
|
|
17
17
|
export * from './isDefined';
|
|
18
|
+
export { unstable_cleanupDOM } from './domUtils';
|
|
18
19
|
export * from '../context/CartesianProvider';
|
|
19
20
|
export * from '../context/DrawingProvider';
|
|
20
21
|
export * from '../context/InteractionProvider';
|
|
@@ -22,6 +23,7 @@ export * from '../context/SeriesProvider';
|
|
|
22
23
|
export * from '../context/ZAxisContextProvider';
|
|
23
24
|
export * from '../context/PluginProvider';
|
|
24
25
|
export type * from '../context/context.types';
|
|
26
|
+
export { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum';
|
|
25
27
|
export * from '../models/seriesType/config';
|
|
26
28
|
export * from '../models/seriesType/common';
|
|
27
29
|
export * from '../models/helpers';
|
package/internals/index.js
CHANGED
|
@@ -12,8 +12,22 @@ var _exportNames = {
|
|
|
12
12
|
useLineChartProps: true,
|
|
13
13
|
useBarChartProps: true,
|
|
14
14
|
useResponsiveChartContainerProps: true,
|
|
15
|
-
useChartContainerProps: true
|
|
15
|
+
useChartContainerProps: true,
|
|
16
|
+
unstable_cleanupDOM: true,
|
|
17
|
+
getAxisExtremum: true
|
|
16
18
|
};
|
|
19
|
+
Object.defineProperty(exports, "getAxisExtremum", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () {
|
|
22
|
+
return _getAxisExtremum.getAxisExtremum;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
Object.defineProperty(exports, "unstable_cleanupDOM", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return _domUtils.unstable_cleanupDOM;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
17
31
|
Object.defineProperty(exports, "useBarChartProps", {
|
|
18
32
|
enumerable: true,
|
|
19
33
|
get: function () {
|
|
@@ -173,6 +187,7 @@ Object.keys(_isDefined).forEach(function (key) {
|
|
|
173
187
|
}
|
|
174
188
|
});
|
|
175
189
|
});
|
|
190
|
+
var _domUtils = require("./domUtils");
|
|
176
191
|
var _CartesianProvider = require("../context/CartesianProvider");
|
|
177
192
|
Object.keys(_CartesianProvider).forEach(function (key) {
|
|
178
193
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -245,6 +260,7 @@ Object.keys(_PluginProvider).forEach(function (key) {
|
|
|
245
260
|
}
|
|
246
261
|
});
|
|
247
262
|
});
|
|
263
|
+
var _getAxisExtremum = require("../context/CartesianProvider/getAxisExtremum");
|
|
248
264
|
var _config = require("../models/seriesType/config");
|
|
249
265
|
Object.keys(_config).forEach(function (key) {
|
|
250
266
|
if (key === "default" || key === "__esModule") return;
|
package/models/axis.d.ts
CHANGED
|
@@ -183,6 +183,10 @@ export interface AxisScaleConfig {
|
|
|
183
183
|
colorMap?: ContinuousColorConfig | PiecewiseColorConfig;
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Use this type instead of `AxisScaleConfig` when the values
|
|
188
|
+
* shouldn't be provided by the user.
|
|
189
|
+
*/
|
|
186
190
|
export interface AxisScaleComputedConfig {
|
|
187
191
|
band: {
|
|
188
192
|
colorScale?: ScaleOrdinal<string | number | Date, string, string | null> | ScaleOrdinal<number, string, string | null> | ScaleSequential<string, string | null> | ScaleThreshold<number | Date, string | null>;
|
package/models/axis.js
CHANGED
|
@@ -5,6 +5,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isBandScaleConfig = isBandScaleConfig;
|
|
7
7
|
exports.isPointScaleConfig = isPointScaleConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Use this type instead of `AxisScaleConfig` when the values
|
|
10
|
+
* shouldn't be provided by the user.
|
|
11
|
+
*/
|
|
12
|
+
|
|
8
13
|
function isBandScaleConfig(scaleConfig) {
|
|
9
14
|
return scaleConfig.scaleType === 'band';
|
|
10
15
|
}
|