@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.
Files changed (88) hide show
  1. package/BarChart/BarPlot.js +4 -3
  2. package/BarChart/extremums.js +42 -7
  3. package/CHANGELOG.md +82 -2
  4. package/ChartContainer/useChartContainerProps.js +1 -1
  5. package/ChartContainer/useDefaultizeAxis.d.ts +2 -1
  6. package/ChartContainer/useDefaultizeAxis.js +16 -5
  7. package/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  8. package/ChartsGrid/ChartsGrid.js +6 -4
  9. package/ChartsXAxis/ChartsXAxis.js +14 -3
  10. package/ChartsYAxis/ChartsYAxis.js +8 -2
  11. package/LineChart/extremums.js +20 -4
  12. package/ScatterChart/extremums.js +26 -10
  13. package/context/CartesianProvider/Cartesian.types.d.ts +59 -0
  14. package/context/CartesianProvider/Cartesian.types.js +5 -0
  15. package/context/CartesianProvider/CartesianContext.d.ts +1 -22
  16. package/context/CartesianProvider/CartesianProvider.d.ts +1 -21
  17. package/context/CartesianProvider/CartesianProvider.js +2 -5
  18. package/context/CartesianProvider/computeValue.d.ts +18 -31
  19. package/context/CartesianProvider/computeValue.js +20 -23
  20. package/context/CartesianProvider/getAxisExtremum.d.ts +3 -2
  21. package/context/CartesianProvider/getAxisExtremum.js +11 -5
  22. package/context/CartesianProvider/index.d.ts +1 -0
  23. package/context/CartesianProvider/index.js +12 -0
  24. package/context/CartesianProvider/useCartesianContext.d.ts +1 -1
  25. package/context/CartesianProvider/zoom.d.ts +10 -0
  26. package/context/CartesianProvider/zoom.js +26 -0
  27. package/context/DrawingProvider.d.ts +7 -2
  28. package/context/DrawingProvider.js +11 -3
  29. package/context/PluginProvider/ExtremumGetter.types.d.ts +11 -1
  30. package/esm/BarChart/BarPlot.js +4 -3
  31. package/esm/BarChart/extremums.js +42 -7
  32. package/esm/ChartContainer/useChartContainerProps.js +1 -1
  33. package/esm/ChartContainer/useDefaultizeAxis.js +16 -5
  34. package/esm/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  35. package/esm/ChartsGrid/ChartsGrid.js +6 -4
  36. package/esm/ChartsXAxis/ChartsXAxis.js +14 -3
  37. package/esm/ChartsYAxis/ChartsYAxis.js +8 -2
  38. package/esm/LineChart/extremums.js +20 -4
  39. package/esm/ScatterChart/extremums.js +26 -10
  40. package/esm/context/CartesianProvider/Cartesian.types.js +1 -0
  41. package/esm/context/CartesianProvider/CartesianProvider.js +2 -5
  42. package/esm/context/CartesianProvider/computeValue.js +20 -23
  43. package/esm/context/CartesianProvider/getAxisExtremum.js +11 -5
  44. package/esm/context/CartesianProvider/index.js +1 -0
  45. package/esm/context/CartesianProvider/zoom.js +19 -0
  46. package/esm/context/DrawingProvider.js +11 -3
  47. package/esm/hooks/useAxisEvents.js +3 -1
  48. package/esm/internals/domUtils.js +16 -3
  49. package/esm/internals/index.js +3 -0
  50. package/esm/models/axis.js +5 -0
  51. package/esm/tests/firePointerEvent.js +35 -0
  52. package/hooks/useAxisEvents.js +3 -1
  53. package/index.js +1 -1
  54. package/internals/domUtils.d.ts +2 -0
  55. package/internals/domUtils.js +19 -5
  56. package/internals/index.d.ts +2 -0
  57. package/internals/index.js +17 -1
  58. package/models/axis.d.ts +4 -0
  59. package/models/axis.js +5 -0
  60. package/modern/BarChart/BarPlot.js +4 -3
  61. package/modern/BarChart/extremums.js +42 -7
  62. package/modern/ChartContainer/useChartContainerProps.js +1 -1
  63. package/modern/ChartContainer/useDefaultizeAxis.js +16 -5
  64. package/modern/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  65. package/modern/ChartsGrid/ChartsGrid.js +6 -4
  66. package/modern/ChartsXAxis/ChartsXAxis.js +14 -3
  67. package/modern/ChartsYAxis/ChartsYAxis.js +8 -2
  68. package/modern/LineChart/extremums.js +20 -4
  69. package/modern/ScatterChart/extremums.js +26 -10
  70. package/modern/context/CartesianProvider/Cartesian.types.js +1 -0
  71. package/modern/context/CartesianProvider/CartesianProvider.js +2 -5
  72. package/modern/context/CartesianProvider/computeValue.js +20 -23
  73. package/modern/context/CartesianProvider/getAxisExtremum.js +11 -5
  74. package/modern/context/CartesianProvider/index.js +1 -0
  75. package/modern/context/CartesianProvider/zoom.js +19 -0
  76. package/modern/context/DrawingProvider.js +11 -3
  77. package/modern/hooks/useAxisEvents.js +3 -1
  78. package/modern/index.js +1 -1
  79. package/modern/internals/domUtils.js +16 -3
  80. package/modern/internals/index.js +3 -0
  81. package/modern/models/axis.js +5 -0
  82. package/modern/tests/firePointerEvent.js +35 -0
  83. package/package.json +4 -4
  84. package/tests/firePointerEvent.js +42 -0
  85. package/context/CartesianProvider/normalizeAxis.d.ts +0 -5
  86. package/context/CartesianProvider/normalizeAxis.js +0 -23
  87. package/esm/context/CartesianProvider/normalizeAxis.js +0 -15
  88. 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 = offset >= top - 1 && offset <= height + top + 1;
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 seriesMinMax = series[seriesId].data.reduce((accSeries, {
15
- x
16
- }) => {
17
- return mergeMinMax(accSeries, [x, x]);
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 seriesMinMax = series[seriesId].data.reduce((accSeries, {
33
- y
34
- }) => {
35
- return mergeMinMax(accSeries, [y, y]);
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, dataset]);
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, dataset]);
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: inAxis,
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((axis, axisIndex) => {
33
+ allAxis.forEach((eachAxis, axisIndex) => {
34
+ const axis = eachAxis;
44
35
  const isDefaultAxis = axisIndex === 0;
45
- const [minData, maxData] = getAxisExtremum(axis, extremumGetters, isDefaultAxis, formattedSeries);
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 = zoomedScaleRange(scaleRange, zoomRange);
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 = zoomedScaleRange(scaleRange, zoomRange);
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 extremums = [axis.min ?? minData, axis.max ?? maxData];
88
+ const axisExtremums = [axis.min ?? minData, axis.max ?? maxData];
93
89
  const rawTickNumber = getTickNumber(_extends({}, axis, {
94
90
  range,
95
- domain: extremums
91
+ domain: axisExtremums
96
92
  }));
97
93
  const tickNumber = rawTickNumber / ((zoomRange[1] - zoomRange[0]) / 100);
98
- const zoomedRange = zoomedScaleRange(range, zoomRange);
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, extremums, zoomedRange).nice(rawTickNumber);
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
- return [Math.min(minChartTypeData, acc[0]), Math.max(maxChartTypeData, acc[1])];
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
- return charTypes.reduce((acc, charType) => axisExtremumCallback(acc, charType, axis, getters, isDefaultAxis, formattedSeries), [Infinity, -Infinity]);
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
  };
@@ -2,6 +2,7 @@ import { computeValue } from './computeValue';
2
2
  export * from './CartesianProvider';
3
3
  export * from './CartesianContext';
4
4
  export * from './useCartesianContext';
5
+ export * from './Cartesian.types';
5
6
  const cartesianProviderUtils = {
6
7
  computeValue
7
8
  };
@@ -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
- }, targetElement) => {
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
- return x >= drawingArea.left && x <= drawingArea.left + drawingArea.width && y >= drawingArea.top && y <= drawingArea.top + drawingArea.height;
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, event.target)) {
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
+ }
@@ -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';
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Use this type instead of `AxisScaleConfig` when the values
3
+ * shouldn't be provided by the user.
4
+ */
5
+
1
6
  export function isBandScaleConfig(scaleConfig) {
2
7
  return scaleConfig.scaleType === 'band';
3
8
  }
@@ -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
+ }
@@ -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, event.target)) {
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
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-charts v7.13.0
2
+ * @mui/x-charts v7.14.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -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;
@@ -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
- exports.getStringSize = getStringSize;
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
+ }
@@ -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';
@@ -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
  }