@mui/x-charts 7.12.1 → 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/BarChart.js +2 -0
- package/BarChart/BarPlot.js +4 -3
- package/BarChart/extremums.js +46 -9
- package/CHANGELOG.md +162 -1
- package/ChartContainer/ChartContainer.d.ts +3 -3
- package/ChartContainer/ChartContainer.js +4 -2
- package/ChartContainer/useChartContainerProps.d.ts +4 -2
- package/ChartContainer/useChartContainerProps.js +3 -3
- package/ChartContainer/useDefaultizeAxis.d.ts +3 -1
- package/ChartContainer/useDefaultizeAxis.js +16 -5
- package/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/ChartsGrid/ChartsGrid.js +6 -4
- package/ChartsTooltip/utils.js +4 -2
- package/ChartsXAxis/ChartsXAxis.js +25 -8
- package/ChartsYAxis/ChartsYAxis.js +19 -7
- package/LineChart/AreaPlot.js +11 -1
- package/LineChart/LineChart.js +2 -0
- package/LineChart/extremums.js +23 -18
- package/PieChart/PieChart.js +2 -0
- package/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
- package/ResponsiveChartContainer/useResponsiveChartContainerProps.d.ts +1 -1
- package/ScatterChart/ScatterChart.js +2 -0
- package/ScatterChart/extremums.js +30 -22
- package/SparkLineChart/SparkLineChart.js +2 -0
- 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 +3 -23
- package/context/CartesianProvider/CartesianProvider.js +4 -7
- package/context/CartesianProvider/computeValue.d.ts +18 -31
- package/context/CartesianProvider/computeValue.js +20 -23
- package/context/CartesianProvider/defaultizeAxis.d.ts +1 -0
- package/context/CartesianProvider/getAxisExtremum.d.ts +3 -2
- package/context/CartesianProvider/getAxisExtremum.js +10 -11
- 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 +12 -2
- package/esm/BarChart/BarChart.js +2 -0
- package/esm/BarChart/BarPlot.js +4 -3
- package/esm/BarChart/extremums.js +46 -9
- package/esm/ChartContainer/ChartContainer.js +5 -3
- package/esm/ChartContainer/useChartContainerProps.js +3 -3
- package/esm/ChartContainer/useDefaultizeAxis.js +16 -5
- package/esm/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/esm/ChartsGrid/ChartsGrid.js +6 -4
- package/esm/ChartsTooltip/utils.js +4 -2
- package/esm/ChartsXAxis/ChartsXAxis.js +25 -8
- package/esm/ChartsYAxis/ChartsYAxis.js +19 -7
- package/esm/LineChart/AreaPlot.js +11 -1
- package/esm/LineChart/LineChart.js +2 -0
- package/esm/LineChart/extremums.js +23 -18
- package/esm/PieChart/PieChart.js +2 -0
- package/esm/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
- package/esm/ScatterChart/ScatterChart.js +2 -0
- package/esm/ScatterChart/extremums.js +30 -22
- package/esm/SparkLineChart/SparkLineChart.js +2 -0
- package/esm/context/CartesianProvider/Cartesian.types.js +1 -0
- package/esm/context/CartesianProvider/CartesianProvider.js +4 -7
- package/esm/context/CartesianProvider/computeValue.js +20 -23
- package/esm/context/CartesianProvider/getAxisExtremum.js +10 -11
- 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/hooks/useTicks.js +5 -2
- package/esm/internals/domUtils.js +16 -3
- package/esm/internals/index.js +3 -0
- package/esm/internals/isInfinity.js +3 -0
- package/esm/models/axis.js +5 -0
- package/esm/tests/firePointerEvent.js +35 -0
- package/hooks/useAxisEvents.js +3 -1
- package/hooks/useTicks.js +5 -2
- package/index.js +1 -1
- package/internals/defaultizeColor.d.ts +1 -0
- 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/internals/isInfinity.d.ts +1 -0
- package/internals/isInfinity.js +9 -0
- package/models/axis.d.ts +6 -0
- package/models/axis.js +5 -0
- package/models/seriesType/line.d.ts +10 -0
- package/modern/BarChart/BarChart.js +2 -0
- package/modern/BarChart/BarPlot.js +4 -3
- package/modern/BarChart/extremums.js +46 -9
- package/modern/ChartContainer/ChartContainer.js +5 -3
- package/modern/ChartContainer/useChartContainerProps.js +3 -3
- package/modern/ChartContainer/useDefaultizeAxis.js +16 -5
- package/modern/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
- package/modern/ChartsGrid/ChartsGrid.js +6 -4
- package/modern/ChartsTooltip/utils.js +4 -2
- package/modern/ChartsXAxis/ChartsXAxis.js +25 -8
- package/modern/ChartsYAxis/ChartsYAxis.js +19 -7
- package/modern/LineChart/AreaPlot.js +11 -1
- package/modern/LineChart/LineChart.js +2 -0
- package/modern/LineChart/extremums.js +23 -18
- package/modern/PieChart/PieChart.js +2 -0
- package/modern/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
- package/modern/ScatterChart/ScatterChart.js +2 -0
- package/modern/ScatterChart/extremums.js +30 -22
- package/modern/SparkLineChart/SparkLineChart.js +2 -0
- package/modern/context/CartesianProvider/Cartesian.types.js +1 -0
- package/modern/context/CartesianProvider/CartesianProvider.js +4 -7
- package/modern/context/CartesianProvider/computeValue.js +20 -23
- package/modern/context/CartesianProvider/getAxisExtremum.js +10 -11
- 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/hooks/useTicks.js +5 -2
- package/modern/index.js +1 -1
- package/modern/internals/domUtils.js +16 -3
- package/modern/internals/index.js +3 -0
- package/modern/internals/isInfinity.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
|
@@ -25,16 +25,30 @@ export const ChartsAxisHighlightPath = styled('path', {
|
|
|
25
25
|
slot: 'Root',
|
|
26
26
|
overridesResolver: (_, styles) => styles.root
|
|
27
27
|
})(({
|
|
28
|
-
ownerState,
|
|
29
28
|
theme
|
|
30
|
-
}) =>
|
|
31
|
-
pointerEvents: 'none'
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
}) => ({
|
|
30
|
+
pointerEvents: 'none',
|
|
31
|
+
variants: [{
|
|
32
|
+
props: {
|
|
33
|
+
axisHighlight: 'band'
|
|
34
|
+
},
|
|
35
|
+
style: _extends({
|
|
36
|
+
fill: 'white',
|
|
37
|
+
fillOpacity: 0.1
|
|
38
|
+
}, theme.applyStyles('light', {
|
|
39
|
+
fill: 'gray'
|
|
40
|
+
}))
|
|
41
|
+
}, {
|
|
42
|
+
props: {
|
|
43
|
+
axisHighlight: 'line'
|
|
44
|
+
},
|
|
45
|
+
style: _extends({
|
|
46
|
+
strokeDasharray: '5 2',
|
|
47
|
+
stroke: '#ffffff'
|
|
48
|
+
}, theme.applyStyles('light', {
|
|
49
|
+
stroke: '#000000'
|
|
50
|
+
}))
|
|
51
|
+
}]
|
|
38
52
|
}));
|
|
39
53
|
/**
|
|
40
54
|
* Demos:
|
|
@@ -8,6 +8,7 @@ import { styled, useThemeProps } from '@mui/material/styles';
|
|
|
8
8
|
import { useCartesianContext } from '../context/CartesianProvider';
|
|
9
9
|
import { useTicks } from '../hooks/useTicks';
|
|
10
10
|
import { getChartsGridUtilityClass, chartsGridClasses } from './chartsGridClasses';
|
|
11
|
+
import { useDrawingArea } from '../hooks/useDrawingArea';
|
|
11
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
13
|
const GridRoot = styled('g', {
|
|
13
14
|
name: 'MuiChartsGrid',
|
|
@@ -53,6 +54,7 @@ function ChartsGrid(props) {
|
|
|
53
54
|
props,
|
|
54
55
|
name: 'MuiChartsGrid'
|
|
55
56
|
});
|
|
57
|
+
const drawingArea = useDrawingArea();
|
|
56
58
|
const {
|
|
57
59
|
vertical,
|
|
58
60
|
horizontal
|
|
@@ -93,8 +95,8 @@ function ChartsGrid(props) {
|
|
|
93
95
|
formattedValue,
|
|
94
96
|
offset
|
|
95
97
|
}) => /*#__PURE__*/_jsx(GridLine, {
|
|
96
|
-
y1:
|
|
97
|
-
y2:
|
|
98
|
+
y1: drawingArea.top,
|
|
99
|
+
y2: drawingArea.top + drawingArea.height,
|
|
98
100
|
x1: offset,
|
|
99
101
|
x2: offset,
|
|
100
102
|
className: classes.verticalLine
|
|
@@ -104,8 +106,8 @@ function ChartsGrid(props) {
|
|
|
104
106
|
}) => /*#__PURE__*/_jsx(GridLine, {
|
|
105
107
|
y1: offset,
|
|
106
108
|
y2: offset,
|
|
107
|
-
x1:
|
|
108
|
-
x2:
|
|
109
|
+
x1: drawingArea.left,
|
|
110
|
+
x2: drawingArea.left + drawingArea.width,
|
|
109
111
|
className: classes.horizontalLine
|
|
110
112
|
}, `horizontal-${formattedValue}`))]
|
|
111
113
|
}));
|
|
@@ -47,8 +47,10 @@ export function useMouseTracker() {
|
|
|
47
47
|
if (element === null) {
|
|
48
48
|
return () => {};
|
|
49
49
|
}
|
|
50
|
-
const handleOut =
|
|
51
|
-
|
|
50
|
+
const handleOut = event => {
|
|
51
|
+
if (event.pointerType !== 'mouse') {
|
|
52
|
+
setMousePosition(null);
|
|
53
|
+
}
|
|
52
54
|
};
|
|
53
55
|
const handleMove = event => {
|
|
54
56
|
setMousePosition({
|
|
@@ -15,6 +15,8 @@ import { getMinXTranslation } from '../internals/geometry';
|
|
|
15
15
|
import { useMounted } from '../hooks/useMounted';
|
|
16
16
|
import { useDrawingArea } from '../hooks/useDrawingArea';
|
|
17
17
|
import { getWordsByLines } from '../internals/getWordsByLines';
|
|
18
|
+
import { isInfinity } from '../internals/isInfinity';
|
|
19
|
+
import { isBandScale } from '../internals/isBandScale';
|
|
18
20
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
21
|
const useUtilityClasses = ownerState => {
|
|
20
22
|
const {
|
|
@@ -137,7 +139,8 @@ function ChartsXAxis(inProps) {
|
|
|
137
139
|
tickInterval,
|
|
138
140
|
tickLabelInterval,
|
|
139
141
|
tickPlacement,
|
|
140
|
-
tickLabelPlacement
|
|
142
|
+
tickLabelPlacement,
|
|
143
|
+
sx
|
|
141
144
|
} = defaultizedProps;
|
|
142
145
|
const theme = useTheme();
|
|
143
146
|
const classes = useUtilityClasses(_extends({}, defaultizedProps, {
|
|
@@ -147,7 +150,8 @@ function ChartsXAxis(inProps) {
|
|
|
147
150
|
left,
|
|
148
151
|
top,
|
|
149
152
|
width,
|
|
150
|
-
height
|
|
153
|
+
height,
|
|
154
|
+
isPointInside
|
|
151
155
|
} = useDrawingArea();
|
|
152
156
|
const tickSize = disableTicks ? 4 : tickSizeProp;
|
|
153
157
|
const positionSign = position === 'bottom' ? 1 : -1;
|
|
@@ -199,15 +203,17 @@ function ChartsXAxis(inProps) {
|
|
|
199
203
|
ownerState: {}
|
|
200
204
|
});
|
|
201
205
|
const domain = xScale.domain();
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
const ordinalAxis = isBandScale(xScale);
|
|
207
|
+
// Skip axis rendering if no data is available
|
|
208
|
+
// - The domain is an empty array for band/point scales.
|
|
209
|
+
// - The domains contains Infinity for continuous scales.
|
|
210
|
+
if (ordinalAxis && domain.length === 0 || !ordinalAxis && domain.some(isInfinity)) {
|
|
206
211
|
return null;
|
|
207
212
|
}
|
|
208
213
|
return /*#__PURE__*/_jsxs(AxisRoot, {
|
|
209
214
|
transform: `translate(0, ${position === 'bottom' ? top + height : top})`,
|
|
210
215
|
className: classes.root,
|
|
216
|
+
sx: sx,
|
|
211
217
|
children: [!disableLine && /*#__PURE__*/_jsx(Line, _extends({
|
|
212
218
|
x1: left,
|
|
213
219
|
x2: left + width,
|
|
@@ -220,8 +226,18 @@ function ChartsXAxis(inProps) {
|
|
|
220
226
|
}, index) => {
|
|
221
227
|
const xTickLabel = labelOffset ?? 0;
|
|
222
228
|
const yTickLabel = positionSign * (tickSize + 3);
|
|
223
|
-
const showTick =
|
|
224
|
-
|
|
229
|
+
const showTick = isPointInside({
|
|
230
|
+
x: offset,
|
|
231
|
+
y: -1
|
|
232
|
+
}, {
|
|
233
|
+
direction: 'x'
|
|
234
|
+
});
|
|
235
|
+
const showTickLabel = isPointInside({
|
|
236
|
+
x: offset + xTickLabel,
|
|
237
|
+
y: -1
|
|
238
|
+
}, {
|
|
239
|
+
direction: 'x'
|
|
240
|
+
});
|
|
225
241
|
return /*#__PURE__*/_jsxs("g", {
|
|
226
242
|
transform: `translate(${offset}, 0)`,
|
|
227
243
|
className: classes.tickContainer,
|
|
@@ -305,6 +321,7 @@ process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
|
|
|
305
321
|
* @default 'currentColor'
|
|
306
322
|
*/
|
|
307
323
|
stroke: PropTypes.string,
|
|
324
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
308
325
|
/**
|
|
309
326
|
* The font size of the axis ticks text.
|
|
310
327
|
* @default 12
|
|
@@ -12,6 +12,8 @@ import { useDrawingArea } from '../hooks/useDrawingArea';
|
|
|
12
12
|
import { AxisRoot } from '../internals/components/AxisSharedComponents';
|
|
13
13
|
import { ChartsText } from '../ChartsText';
|
|
14
14
|
import { getAxisUtilityClass } from '../ChartsAxis/axisClasses';
|
|
15
|
+
import { isInfinity } from '../internals/isInfinity';
|
|
16
|
+
import { isBandScale } from '../internals/isBandScale';
|
|
15
17
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
18
|
const useUtilityClasses = ownerState => {
|
|
17
19
|
const {
|
|
@@ -78,7 +80,8 @@ function ChartsYAxis(inProps) {
|
|
|
78
80
|
tickPlacement,
|
|
79
81
|
tickLabelPlacement,
|
|
80
82
|
tickInterval,
|
|
81
|
-
tickLabelInterval
|
|
83
|
+
tickLabelInterval,
|
|
84
|
+
sx
|
|
82
85
|
} = defaultizedProps;
|
|
83
86
|
const theme = useTheme();
|
|
84
87
|
const isRTL = theme.direction === 'rtl';
|
|
@@ -89,7 +92,8 @@ function ChartsYAxis(inProps) {
|
|
|
89
92
|
left,
|
|
90
93
|
top,
|
|
91
94
|
width,
|
|
92
|
-
height
|
|
95
|
+
height,
|
|
96
|
+
isPointInside
|
|
93
97
|
} = useDrawingArea();
|
|
94
98
|
const tickSize = disableTicks ? 4 : tickSizeProp;
|
|
95
99
|
const yTicks = useTicks({
|
|
@@ -145,15 +149,17 @@ function ChartsYAxis(inProps) {
|
|
|
145
149
|
ownerState: {}
|
|
146
150
|
});
|
|
147
151
|
const domain = yScale.domain();
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
const ordinalAxis = isBandScale(yScale);
|
|
153
|
+
// Skip axis rendering if no data is available
|
|
154
|
+
// - The domain is an empty array for band/point scales.
|
|
155
|
+
// - The domains contains Infinity for continuous scales.
|
|
156
|
+
if (ordinalAxis && domain.length === 0 || !ordinalAxis && domain.some(isInfinity)) {
|
|
152
157
|
return null;
|
|
153
158
|
}
|
|
154
159
|
return /*#__PURE__*/_jsxs(AxisRoot, {
|
|
155
160
|
transform: `translate(${position === 'right' ? left + width : left}, 0)`,
|
|
156
161
|
className: classes.root,
|
|
162
|
+
sx: sx,
|
|
157
163
|
children: [!disableLine && /*#__PURE__*/_jsx(Line, _extends({
|
|
158
164
|
y1: top,
|
|
159
165
|
y2: top + height,
|
|
@@ -167,7 +173,12 @@ function ChartsYAxis(inProps) {
|
|
|
167
173
|
const xTickLabel = positionSign * (tickSize + 2);
|
|
168
174
|
const yTickLabel = labelOffset;
|
|
169
175
|
const skipLabel = typeof tickLabelInterval === 'function' && !tickLabelInterval?.(value, index);
|
|
170
|
-
const showLabel =
|
|
176
|
+
const showLabel = isPointInside({
|
|
177
|
+
x: -1,
|
|
178
|
+
y: offset
|
|
179
|
+
}, {
|
|
180
|
+
direction: 'y'
|
|
181
|
+
});
|
|
171
182
|
if (!showLabel) {
|
|
172
183
|
return null;
|
|
173
184
|
}
|
|
@@ -253,6 +264,7 @@ process.env.NODE_ENV !== "production" ? ChartsYAxis.propTypes = {
|
|
|
253
264
|
* @default 'currentColor'
|
|
254
265
|
*/
|
|
255
266
|
stroke: PropTypes.string,
|
|
267
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
256
268
|
/**
|
|
257
269
|
* The font size of the axis ticks text.
|
|
258
270
|
* @default 12
|
|
@@ -42,7 +42,8 @@ const useAggregatedData = () => {
|
|
|
42
42
|
yAxisKey = defaultYAxisId,
|
|
43
43
|
stackedData,
|
|
44
44
|
data,
|
|
45
|
-
connectNulls
|
|
45
|
+
connectNulls,
|
|
46
|
+
baseline
|
|
46
47
|
} = series[seriesId];
|
|
47
48
|
const xAxisId = xAxisIdProp ?? xAxisKey;
|
|
48
49
|
const yAxisId = yAxisIdProp ?? yAxisKey;
|
|
@@ -59,6 +60,15 @@ const useAggregatedData = () => {
|
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
const areaPath = d3Area().x(d => xScale(d.x)).defined((_, i) => connectNulls || data[i] != null).y0(d => {
|
|
63
|
+
if (typeof baseline === 'number') {
|
|
64
|
+
return yScale(baseline);
|
|
65
|
+
}
|
|
66
|
+
if (baseline === 'max') {
|
|
67
|
+
return yScale.range()[1];
|
|
68
|
+
}
|
|
69
|
+
if (baseline === 'min') {
|
|
70
|
+
return yScale.range()[0];
|
|
71
|
+
}
|
|
62
72
|
const value = d.y && yScale(d.y[0]);
|
|
63
73
|
if (Number.isNaN(value)) {
|
|
64
74
|
return yScale.range()[0];
|
|
@@ -274,6 +274,7 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
|
|
|
274
274
|
slotProps: PropTypes.object,
|
|
275
275
|
slots: PropTypes.object,
|
|
276
276
|
stroke: PropTypes.string,
|
|
277
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
277
278
|
tickFontSize: PropTypes.number,
|
|
278
279
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
279
280
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -326,6 +327,7 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
|
|
|
326
327
|
slotProps: PropTypes.object,
|
|
327
328
|
slots: PropTypes.object,
|
|
328
329
|
stroke: PropTypes.string,
|
|
330
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
329
331
|
tickFontSize: PropTypes.number,
|
|
330
332
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
331
333
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -6,23 +6,27 @@ 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
|
-
|
|
11
|
-
return [null, null];
|
|
12
|
-
}
|
|
13
|
-
return stackedData.reduce((seriesAcc, stackedValue) => {
|
|
9
|
+
function getSeriesExtremums(getValues, stackedData, filter) {
|
|
10
|
+
return stackedData.reduce((seriesAcc, stackedValue, index) => {
|
|
14
11
|
const [base, value] = getValues(stackedValue);
|
|
15
|
-
if (
|
|
16
|
-
|
|
12
|
+
if (filter && (!filter({
|
|
13
|
+
y: base,
|
|
14
|
+
x: null
|
|
15
|
+
}, index) || !filter({
|
|
16
|
+
y: value,
|
|
17
|
+
x: null
|
|
18
|
+
}, index))) {
|
|
19
|
+
return seriesAcc;
|
|
17
20
|
}
|
|
18
21
|
return [Math.min(base, value, seriesAcc[0]), Math.max(base, value, seriesAcc[1])];
|
|
19
|
-
},
|
|
22
|
+
}, [Infinity, -Infinity]);
|
|
20
23
|
}
|
|
21
24
|
export const getExtremumY = params => {
|
|
22
25
|
const {
|
|
23
26
|
series,
|
|
24
27
|
axis,
|
|
25
|
-
isDefaultAxis
|
|
28
|
+
isDefaultAxis,
|
|
29
|
+
getFilters
|
|
26
30
|
} = params;
|
|
27
31
|
return Object.keys(series).filter(seriesId => {
|
|
28
32
|
const yAxisId = series[seriesId].yAxisId ?? series[seriesId].yAxisKey;
|
|
@@ -33,16 +37,17 @@ export const getExtremumY = params => {
|
|
|
33
37
|
stackedData
|
|
34
38
|
} = series[seriesId];
|
|
35
39
|
const isArea = area !== undefined;
|
|
36
|
-
const
|
|
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
|
+
});
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
if (seriesExtremums[0] === null) {
|
|
43
|
-
return acc;
|
|
44
|
-
}
|
|
47
|
+
// Since this series is not used to display an area, we do not consider the base (the d[0]).
|
|
48
|
+
const getValues = isArea && axis.scaleType !== 'log' && typeof series[seriesId].baseline !== 'string' ? d => d : d => [d[1], d[1]];
|
|
49
|
+
const seriesExtremums = getSeriesExtremums(getValues, stackedData, filter);
|
|
45
50
|
const [seriesMin, seriesMax] = seriesExtremums;
|
|
46
51
|
return [Math.min(seriesMin, acc[0]), Math.max(seriesMax, acc[1])];
|
|
47
|
-
}, [
|
|
52
|
+
}, [Infinity, -Infinity]);
|
|
48
53
|
};
|
|
@@ -318,6 +318,7 @@ process.env.NODE_ENV !== "production" ? PieChart.propTypes = {
|
|
|
318
318
|
slotProps: PropTypes.object,
|
|
319
319
|
slots: PropTypes.object,
|
|
320
320
|
stroke: PropTypes.string,
|
|
321
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
321
322
|
tickFontSize: PropTypes.number,
|
|
322
323
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
323
324
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -370,6 +371,7 @@ process.env.NODE_ENV !== "production" ? PieChart.propTypes = {
|
|
|
370
371
|
slotProps: PropTypes.object,
|
|
371
372
|
slots: PropTypes.object,
|
|
372
373
|
stroke: PropTypes.string,
|
|
374
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
373
375
|
tickFontSize: PropTypes.number,
|
|
374
376
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
375
377
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -130,6 +130,7 @@ process.env.NODE_ENV !== "production" ? ResponsiveChartContainer.propTypes = {
|
|
|
130
130
|
slotProps: PropTypes.object,
|
|
131
131
|
slots: PropTypes.object,
|
|
132
132
|
stroke: PropTypes.string,
|
|
133
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
133
134
|
tickFontSize: PropTypes.number,
|
|
134
135
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
135
136
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -182,6 +183,7 @@ process.env.NODE_ENV !== "production" ? ResponsiveChartContainer.propTypes = {
|
|
|
182
183
|
slotProps: PropTypes.object,
|
|
183
184
|
slots: PropTypes.object,
|
|
184
185
|
stroke: PropTypes.string,
|
|
186
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
185
187
|
tickFontSize: PropTypes.number,
|
|
186
188
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
187
189
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -255,6 +255,7 @@ process.env.NODE_ENV !== "production" ? ScatterChart.propTypes = {
|
|
|
255
255
|
slotProps: PropTypes.object,
|
|
256
256
|
slots: PropTypes.object,
|
|
257
257
|
stroke: PropTypes.string,
|
|
258
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
258
259
|
tickFontSize: PropTypes.number,
|
|
259
260
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
260
261
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -307,6 +308,7 @@ process.env.NODE_ENV !== "production" ? ScatterChart.propTypes = {
|
|
|
307
308
|
slotProps: PropTypes.object,
|
|
308
309
|
slots: PropTypes.object,
|
|
309
310
|
stroke: PropTypes.string,
|
|
311
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
310
312
|
tickFontSize: PropTypes.number,
|
|
311
313
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
312
314
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -1,47 +1,55 @@
|
|
|
1
1
|
const mergeMinMax = (acc, val) => {
|
|
2
|
-
if (acc[0] === null || acc[1] === null) {
|
|
3
|
-
return val;
|
|
4
|
-
}
|
|
5
|
-
if (val[0] === null || val[1] === null) {
|
|
6
|
-
return acc;
|
|
7
|
-
}
|
|
8
2
|
return [Math.min(acc[0], val[0]), Math.max(acc[1], val[1])];
|
|
9
3
|
};
|
|
10
4
|
export const getExtremumX = params => {
|
|
11
5
|
const {
|
|
12
6
|
series,
|
|
13
7
|
axis,
|
|
14
|
-
isDefaultAxis
|
|
8
|
+
isDefaultAxis,
|
|
9
|
+
getFilters
|
|
15
10
|
} = params;
|
|
16
11
|
return Object.keys(series).filter(seriesId => {
|
|
17
12
|
const axisId = series[seriesId].xAxisId ?? series[seriesId].xAxisKey;
|
|
18
13
|
return axisId === axis.id || axisId === undefined && isDefaultAxis;
|
|
19
14
|
}).reduce((acc, seriesId) => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
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]);
|
|
26
|
+
}, [Infinity, -Infinity]);
|
|
26
27
|
return mergeMinMax(acc, seriesMinMax);
|
|
27
|
-
}, [
|
|
28
|
+
}, [Infinity, -Infinity]);
|
|
28
29
|
};
|
|
29
30
|
export const getExtremumY = params => {
|
|
30
31
|
const {
|
|
31
32
|
series,
|
|
32
33
|
axis,
|
|
33
|
-
isDefaultAxis
|
|
34
|
+
isDefaultAxis,
|
|
35
|
+
getFilters
|
|
34
36
|
} = params;
|
|
35
37
|
return Object.keys(series).filter(seriesId => {
|
|
36
38
|
const axisId = series[seriesId].yAxisId ?? series[seriesId].yAxisKey;
|
|
37
39
|
return axisId === axis.id || axisId === undefined && isDefaultAxis;
|
|
38
40
|
}).reduce((acc, seriesId) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
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]);
|
|
52
|
+
}, [Infinity, -Infinity]);
|
|
45
53
|
return mergeMinMax(acc, seriesMinMax);
|
|
46
|
-
}, [
|
|
54
|
+
}, [Infinity, -Infinity]);
|
|
47
55
|
};
|
|
@@ -279,6 +279,7 @@ process.env.NODE_ENV !== "production" ? SparkLineChart.propTypes = {
|
|
|
279
279
|
slotProps: PropTypes.object,
|
|
280
280
|
slots: PropTypes.object,
|
|
281
281
|
stroke: PropTypes.string,
|
|
282
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
282
283
|
tickFontSize: PropTypes.number,
|
|
283
284
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
284
285
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -330,6 +331,7 @@ process.env.NODE_ENV !== "production" ? SparkLineChart.propTypes = {
|
|
|
330
331
|
slotProps: PropTypes.object,
|
|
331
332
|
slots: PropTypes.object,
|
|
332
333
|
stroke: PropTypes.string,
|
|
334
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
|
|
333
335
|
tickFontSize: PropTypes.number,
|
|
334
336
|
tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
|
|
335
337
|
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,11 +6,10 @@ import { computeValue } from './computeValue';
|
|
|
6
6
|
import { useXExtremumGetter } from '../PluginProvider/useXExtremumGetter';
|
|
7
7
|
import { useYExtremumGetter } from '../PluginProvider';
|
|
8
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
-
function
|
|
9
|
+
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 CartesianContextProvider(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: {
|
|
@@ -47,4 +44,4 @@ function CartesianContextProvider(props) {
|
|
|
47
44
|
children: children
|
|
48
45
|
});
|
|
49
46
|
}
|
|
50
|
-
export {
|
|
47
|
+
export { CartesianProvider };
|
|
@@ -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,
|