@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.
Files changed (128) hide show
  1. package/BarChart/BarChart.js +2 -0
  2. package/BarChart/BarPlot.js +4 -3
  3. package/BarChart/extremums.js +46 -9
  4. package/CHANGELOG.md +162 -1
  5. package/ChartContainer/ChartContainer.d.ts +3 -3
  6. package/ChartContainer/ChartContainer.js +4 -2
  7. package/ChartContainer/useChartContainerProps.d.ts +4 -2
  8. package/ChartContainer/useChartContainerProps.js +3 -3
  9. package/ChartContainer/useDefaultizeAxis.d.ts +3 -1
  10. package/ChartContainer/useDefaultizeAxis.js +16 -5
  11. package/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  12. package/ChartsGrid/ChartsGrid.js +6 -4
  13. package/ChartsTooltip/utils.js +4 -2
  14. package/ChartsXAxis/ChartsXAxis.js +25 -8
  15. package/ChartsYAxis/ChartsYAxis.js +19 -7
  16. package/LineChart/AreaPlot.js +11 -1
  17. package/LineChart/LineChart.js +2 -0
  18. package/LineChart/extremums.js +23 -18
  19. package/PieChart/PieChart.js +2 -0
  20. package/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
  21. package/ResponsiveChartContainer/useResponsiveChartContainerProps.d.ts +1 -1
  22. package/ScatterChart/ScatterChart.js +2 -0
  23. package/ScatterChart/extremums.js +30 -22
  24. package/SparkLineChart/SparkLineChart.js +2 -0
  25. package/context/CartesianProvider/Cartesian.types.d.ts +59 -0
  26. package/context/CartesianProvider/Cartesian.types.js +5 -0
  27. package/context/CartesianProvider/CartesianContext.d.ts +1 -22
  28. package/context/CartesianProvider/CartesianProvider.d.ts +3 -23
  29. package/context/CartesianProvider/CartesianProvider.js +4 -7
  30. package/context/CartesianProvider/computeValue.d.ts +18 -31
  31. package/context/CartesianProvider/computeValue.js +20 -23
  32. package/context/CartesianProvider/defaultizeAxis.d.ts +1 -0
  33. package/context/CartesianProvider/getAxisExtremum.d.ts +3 -2
  34. package/context/CartesianProvider/getAxisExtremum.js +10 -11
  35. package/context/CartesianProvider/index.d.ts +1 -0
  36. package/context/CartesianProvider/index.js +12 -0
  37. package/context/CartesianProvider/useCartesianContext.d.ts +1 -1
  38. package/context/CartesianProvider/zoom.d.ts +10 -0
  39. package/context/CartesianProvider/zoom.js +26 -0
  40. package/context/DrawingProvider.d.ts +7 -2
  41. package/context/DrawingProvider.js +11 -3
  42. package/context/PluginProvider/ExtremumGetter.types.d.ts +12 -2
  43. package/esm/BarChart/BarChart.js +2 -0
  44. package/esm/BarChart/BarPlot.js +4 -3
  45. package/esm/BarChart/extremums.js +46 -9
  46. package/esm/ChartContainer/ChartContainer.js +5 -3
  47. package/esm/ChartContainer/useChartContainerProps.js +3 -3
  48. package/esm/ChartContainer/useDefaultizeAxis.js +16 -5
  49. package/esm/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  50. package/esm/ChartsGrid/ChartsGrid.js +6 -4
  51. package/esm/ChartsTooltip/utils.js +4 -2
  52. package/esm/ChartsXAxis/ChartsXAxis.js +25 -8
  53. package/esm/ChartsYAxis/ChartsYAxis.js +19 -7
  54. package/esm/LineChart/AreaPlot.js +11 -1
  55. package/esm/LineChart/LineChart.js +2 -0
  56. package/esm/LineChart/extremums.js +23 -18
  57. package/esm/PieChart/PieChart.js +2 -0
  58. package/esm/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
  59. package/esm/ScatterChart/ScatterChart.js +2 -0
  60. package/esm/ScatterChart/extremums.js +30 -22
  61. package/esm/SparkLineChart/SparkLineChart.js +2 -0
  62. package/esm/context/CartesianProvider/Cartesian.types.js +1 -0
  63. package/esm/context/CartesianProvider/CartesianProvider.js +4 -7
  64. package/esm/context/CartesianProvider/computeValue.js +20 -23
  65. package/esm/context/CartesianProvider/getAxisExtremum.js +10 -11
  66. package/esm/context/CartesianProvider/index.js +1 -0
  67. package/esm/context/CartesianProvider/zoom.js +19 -0
  68. package/esm/context/DrawingProvider.js +11 -3
  69. package/esm/hooks/useAxisEvents.js +3 -1
  70. package/esm/hooks/useTicks.js +5 -2
  71. package/esm/internals/domUtils.js +16 -3
  72. package/esm/internals/index.js +3 -0
  73. package/esm/internals/isInfinity.js +3 -0
  74. package/esm/models/axis.js +5 -0
  75. package/esm/tests/firePointerEvent.js +35 -0
  76. package/hooks/useAxisEvents.js +3 -1
  77. package/hooks/useTicks.js +5 -2
  78. package/index.js +1 -1
  79. package/internals/defaultizeColor.d.ts +1 -0
  80. package/internals/domUtils.d.ts +2 -0
  81. package/internals/domUtils.js +19 -5
  82. package/internals/index.d.ts +2 -0
  83. package/internals/index.js +17 -1
  84. package/internals/isInfinity.d.ts +1 -0
  85. package/internals/isInfinity.js +9 -0
  86. package/models/axis.d.ts +6 -0
  87. package/models/axis.js +5 -0
  88. package/models/seriesType/line.d.ts +10 -0
  89. package/modern/BarChart/BarChart.js +2 -0
  90. package/modern/BarChart/BarPlot.js +4 -3
  91. package/modern/BarChart/extremums.js +46 -9
  92. package/modern/ChartContainer/ChartContainer.js +5 -3
  93. package/modern/ChartContainer/useChartContainerProps.js +3 -3
  94. package/modern/ChartContainer/useDefaultizeAxis.js +16 -5
  95. package/modern/ChartsAxisHighlight/ChartsAxisHighlight.js +23 -9
  96. package/modern/ChartsGrid/ChartsGrid.js +6 -4
  97. package/modern/ChartsTooltip/utils.js +4 -2
  98. package/modern/ChartsXAxis/ChartsXAxis.js +25 -8
  99. package/modern/ChartsYAxis/ChartsYAxis.js +19 -7
  100. package/modern/LineChart/AreaPlot.js +11 -1
  101. package/modern/LineChart/LineChart.js +2 -0
  102. package/modern/LineChart/extremums.js +23 -18
  103. package/modern/PieChart/PieChart.js +2 -0
  104. package/modern/ResponsiveChartContainer/ResponsiveChartContainer.js +2 -0
  105. package/modern/ScatterChart/ScatterChart.js +2 -0
  106. package/modern/ScatterChart/extremums.js +30 -22
  107. package/modern/SparkLineChart/SparkLineChart.js +2 -0
  108. package/modern/context/CartesianProvider/Cartesian.types.js +1 -0
  109. package/modern/context/CartesianProvider/CartesianProvider.js +4 -7
  110. package/modern/context/CartesianProvider/computeValue.js +20 -23
  111. package/modern/context/CartesianProvider/getAxisExtremum.js +10 -11
  112. package/modern/context/CartesianProvider/index.js +1 -0
  113. package/modern/context/CartesianProvider/zoom.js +19 -0
  114. package/modern/context/DrawingProvider.js +11 -3
  115. package/modern/hooks/useAxisEvents.js +3 -1
  116. package/modern/hooks/useTicks.js +5 -2
  117. package/modern/index.js +1 -1
  118. package/modern/internals/domUtils.js +16 -3
  119. package/modern/internals/index.js +3 -0
  120. package/modern/internals/isInfinity.js +3 -0
  121. package/modern/models/axis.js +5 -0
  122. package/modern/tests/firePointerEvent.js +35 -0
  123. package/package.json +4 -4
  124. package/tests/firePointerEvent.js +42 -0
  125. package/context/CartesianProvider/normalizeAxis.d.ts +0 -5
  126. package/context/CartesianProvider/normalizeAxis.js +0 -23
  127. package/esm/context/CartesianProvider/normalizeAxis.js +0 -15
  128. package/modern/context/CartesianProvider/normalizeAxis.js +0 -15
@@ -11,22 +11,12 @@ var _axis = require("../../models/axis");
11
11
  var _colorScale = require("../../internals/colorScale");
12
12
  var _useTicks = require("../../hooks/useTicks");
13
13
  var _getScale = require("../../internals/getScale");
14
+ var _zoom = require("./zoom");
14
15
  var _getAxisExtremum = require("./getAxisExtremum");
15
- var _normalizeAxis = require("./normalizeAxis");
16
16
  const getRange = (drawingArea, axisDirection, isReverse) => {
17
17
  const range = axisDirection === 'x' ? [drawingArea.left, drawingArea.left + drawingArea.width] : [drawingArea.top + drawingArea.height, drawingArea.top];
18
18
  return isReverse ? range.reverse() : range;
19
19
  };
20
- const zoomedScaleRange = (scaleRange, zoomRange) => {
21
- const rangeGap = scaleRange[1] - scaleRange[0];
22
- const zoomGap = zoomRange[1] - zoomRange[0];
23
-
24
- // If current zoom show the scale between p1 and p2 percents
25
- // The range should be extended by adding [0, p1] and [p2, 100] segments
26
- const min = scaleRange[0] - zoomRange[0] * rangeGap / zoomGap;
27
- const max = scaleRange[1] + (100 - zoomRange[1]) * rangeGap / zoomGap;
28
- return [min, max];
29
- };
30
20
  const isDateData = data => data?.[0] instanceof Date;
31
21
  function createDateFormatter(axis, range) {
32
22
  const timeScale = (0, _d3Scale.scaleTime)(axis.data, range);
@@ -39,32 +29,37 @@ const DEFAULT_BAR_GAP_RATIO = 0.1;
39
29
  function computeValue({
40
30
  drawingArea,
41
31
  formattedSeries,
42
- axis: inAxis,
32
+ axis: allAxis,
43
33
  extremumGetters,
44
- dataset,
45
34
  axisDirection,
46
- zoomData
35
+ zoomData,
36
+ zoomOptions,
37
+ getFilters
47
38
  }) {
48
- const allAxis = (0, _normalizeAxis.normalizeAxis)(inAxis, dataset, axisDirection);
49
39
  const completeAxis = {};
50
- allAxis.forEach((axis, axisIndex) => {
40
+ allAxis.forEach((eachAxis, axisIndex) => {
41
+ const axis = eachAxis;
51
42
  const isDefaultAxis = axisIndex === 0;
52
- const [minData, maxData] = (0, _getAxisExtremum.getAxisExtremum)(axis, extremumGetters, isDefaultAxis, formattedSeries);
43
+ const zoomOption = zoomOptions?.[axis.id];
53
44
  const zoom = zoomData?.find(({
54
45
  axisId
55
46
  }) => axisId === axis.id);
56
47
  const zoomRange = zoom ? [zoom.start, zoom.end] : [0, 100];
57
48
  const range = getRange(drawingArea, axisDirection, axis.reverse);
49
+ const [minData, maxData] = (0, _getAxisExtremum.getAxisExtremum)(axis, extremumGetters, isDefaultAxis, formattedSeries, zoom === undefined && !zoomOption ? getFilters : undefined // Do not apply filtering if zoom is already defined.
50
+ );
51
+ const data = axis.data ?? [];
58
52
  if ((0, _axis.isBandScaleConfig)(axis)) {
59
53
  const categoryGapRatio = axis.categoryGapRatio ?? DEFAULT_CATEGORY_GAP_RATIO;
60
54
  const barGapRatio = axis.barGapRatio ?? DEFAULT_BAR_GAP_RATIO;
61
55
  // Reverse range because ordinal scales are presented from top to bottom on y-axis
62
56
  const scaleRange = axisDirection === 'x' ? range : [range[1], range[0]];
63
- const zoomedRange = zoomedScaleRange(scaleRange, zoomRange);
57
+ const zoomedRange = (0, _zoom.zoomScaleRange)(scaleRange, zoomRange);
64
58
  completeAxis[axis.id] = (0, _extends2.default)({
65
59
  categoryGapRatio,
66
60
  barGapRatio
67
61
  }, axis, {
62
+ data,
68
63
  scale: (0, _d3Scale.scaleBand)(axis.data, zoomedRange).paddingInner(categoryGapRatio).paddingOuter(categoryGapRatio / 2),
69
64
  tickNumber: axis.data.length,
70
65
  colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({
@@ -78,8 +73,9 @@ function computeValue({
78
73
  }
79
74
  if ((0, _axis.isPointScaleConfig)(axis)) {
80
75
  const scaleRange = axisDirection === 'x' ? range : [...range].reverse();
81
- const zoomedRange = zoomedScaleRange(scaleRange, zoomRange);
76
+ const zoomedRange = (0, _zoom.zoomScaleRange)(scaleRange, zoomRange);
82
77
  completeAxis[axis.id] = (0, _extends2.default)({}, axis, {
78
+ data,
83
79
  scale: (0, _d3Scale.scalePoint)(axis.data, zoomedRange),
84
80
  tickNumber: axis.data.length,
85
81
  colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({
@@ -96,19 +92,20 @@ function computeValue({
96
92
  return;
97
93
  }
98
94
  const scaleType = axis.scaleType ?? 'linear';
99
- const extremums = [axis.min ?? minData, axis.max ?? maxData];
95
+ const axisExtremums = [axis.min ?? minData, axis.max ?? maxData];
100
96
  const rawTickNumber = (0, _useTicks.getTickNumber)((0, _extends2.default)({}, axis, {
101
97
  range,
102
- domain: extremums
98
+ domain: axisExtremums
103
99
  }));
104
100
  const tickNumber = rawTickNumber / ((zoomRange[1] - zoomRange[0]) / 100);
105
- const zoomedRange = zoomedScaleRange(range, zoomRange);
101
+ const zoomedRange = (0, _zoom.zoomScaleRange)(range, zoomRange);
106
102
 
107
103
  // TODO: move nice to prop? Disable when there is zoom?
108
- const scale = (0, _getScale.getScale)(scaleType, extremums, zoomedRange).nice(rawTickNumber);
104
+ const scale = (0, _getScale.getScale)(scaleType, axisExtremums, zoomedRange).nice(rawTickNumber);
109
105
  const [minDomain, maxDomain] = scale.domain();
110
106
  const domain = [axis.min ?? minDomain, axis.max ?? maxDomain];
111
107
  completeAxis[axis.id] = (0, _extends2.default)({}, axis, {
108
+ data,
112
109
  scaleType: scaleType,
113
110
  scale: scale.domain(domain),
114
111
  tickNumber,
@@ -9,6 +9,7 @@ export declare const defaultizeAxis: (inAxis: MakeOptional<AxisConfig<ScaleName,
9
9
  label?: string | undefined;
10
10
  max?: (number | Date) | undefined;
11
11
  min?: (number | Date) | undefined;
12
+ sx?: import("@mui/system").SxProps | undefined;
12
13
  classes?: Partial<import("../..").ChartsAxisClasses> | undefined;
13
14
  slots?: Partial<import("../../models/axis").ChartsAxisSlots> | undefined;
14
15
  slotProps?: Partial<import("../../models/axis").ChartsAxisSlotProps> | undefined;
@@ -1,4 +1,5 @@
1
1
  import { AxisConfig } from '../../models';
2
2
  import { FormattedSeries } from '../SeriesProvider';
3
- import { ExtremumGettersConfig, ExtremumGetterResult } from '../PluginProvider';
4
- export declare const getAxisExtremum: (axis: AxisConfig, getters: ExtremumGettersConfig, isDefaultAxis: boolean, formattedSeries: FormattedSeries) => ExtremumGetterResult;
3
+ import { ExtremumGettersConfig } from '../PluginProvider';
4
+ import { GetZoomAxisFilters } from './Cartesian.types';
5
+ export declare const getAxisExtremum: (axis: AxisConfig, getters: ExtremumGettersConfig, isDefaultAxis: boolean, formattedSeries: FormattedSeries, getFilters?: GetZoomAxisFilters) => number[];
@@ -4,25 +4,24 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getAxisExtremum = void 0;
7
- const axisExtremumCallback = (acc, chartType, axis, getters, isDefaultAxis, formattedSeries) => {
7
+ const axisExtremumCallback = (acc, chartType, axis, getters, isDefaultAxis, formattedSeries, getFilters) => {
8
8
  const getter = getters[chartType];
9
9
  const series = formattedSeries[chartType]?.series ?? {};
10
10
  const [minChartTypeData, maxChartTypeData] = getter?.({
11
11
  series,
12
12
  axis,
13
- isDefaultAxis
14
- }) ?? [null, null];
13
+ isDefaultAxis,
14
+ getFilters
15
+ }) ?? [Infinity, -Infinity];
15
16
  const [minData, maxData] = acc;
16
- if (minData === null || maxData === null) {
17
- return [minChartTypeData, maxChartTypeData];
18
- }
19
- if (minChartTypeData === null || maxChartTypeData === null) {
20
- return [minData, maxData];
21
- }
22
17
  return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)];
23
18
  };
24
- const getAxisExtremum = (axis, getters, isDefaultAxis, formattedSeries) => {
19
+ const getAxisExtremum = (axis, getters, isDefaultAxis, formattedSeries, getFilters) => {
25
20
  const charTypes = Object.keys(getters);
26
- return charTypes.reduce((acc, charType) => axisExtremumCallback(acc, charType, axis, getters, isDefaultAxis, formattedSeries), [null, null]);
21
+ const extremums = charTypes.reduce((acc, charType) => axisExtremumCallback(acc, charType, axis, getters, isDefaultAxis, formattedSeries, getFilters), [Infinity, -Infinity]);
22
+ if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) {
23
+ return [Infinity, -Infinity];
24
+ }
25
+ return extremums;
27
26
  };
28
27
  exports.getAxisExtremum = getAxisExtremum;
@@ -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
  declare const cartesianProviderUtils: {
6
7
  computeValue: typeof computeValue;
7
8
  };
@@ -44,6 +44,18 @@ Object.keys(_useCartesianContext).forEach(function (key) {
44
44
  }
45
45
  });
46
46
  });
47
+ var _Cartesian = require("./Cartesian.types");
48
+ Object.keys(_Cartesian).forEach(function (key) {
49
+ if (key === "default" || key === "__esModule") return;
50
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
51
+ if (key in exports && exports[key] === _Cartesian[key]) return;
52
+ Object.defineProperty(exports, key, {
53
+ enumerable: true,
54
+ get: function () {
55
+ return _Cartesian[key];
56
+ }
57
+ });
58
+ });
47
59
  const cartesianProviderUtils = exports.cartesianProviderUtils = {
48
60
  computeValue: _computeValue.computeValue
49
61
  };
@@ -1,2 +1,2 @@
1
- import { CartesianContextState } from './CartesianContext';
1
+ import { CartesianContextState } from './Cartesian.types';
2
2
  export declare const useCartesianContext: () => CartesianContextState;
@@ -0,0 +1,10 @@
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 declare const zoomScaleRange: (scaleRange: [number, number] | number[], zoomRange: [number, number] | number[]) => number[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.zoomScaleRange = void 0;
7
+ /**
8
+ * Applies the zoom into the scale range.
9
+ * It changes the screen coordinates that the scale covers.
10
+ * Not the data that is displayed.
11
+ *
12
+ * @param scaleRange the original range in real screen coordinates.
13
+ * @param zoomRange the zoom range in percentage.
14
+ * @returns zoomed range in real screen coordinates.
15
+ */
16
+ const zoomScaleRange = (scaleRange, zoomRange) => {
17
+ const rangeGap = scaleRange[1] - scaleRange[0];
18
+ const zoomGap = zoomRange[1] - zoomRange[0];
19
+
20
+ // If current zoom show the scale between p1 and p2 percents
21
+ // The range should be extended by adding [0, p1] and [p2, 100] segments
22
+ const min = scaleRange[0] - zoomRange[0] * rangeGap / zoomGap;
23
+ const max = scaleRange[1] + (100 - zoomRange[1]) * rangeGap / zoomGap;
24
+ return [min, max];
25
+ };
26
+ exports.zoomScaleRange = zoomScaleRange;
@@ -38,13 +38,18 @@ export type DrawingArea = {
38
38
  * @param {Object} point The point to check.
39
39
  * @param {number} point.x The x coordinate of the point.
40
40
  * @param {number} point.y The y coordinate of the point.
41
- * @param {Element} targetElement The target element if relevant.
41
+ * @param {Object} options The options of the check.
42
+ * @param {Element} [options.targetElement] The element to check if it is allowed to overflow the drawing area.
43
+ * @param {'x' | 'y'} [options.direction] The direction to check.
42
44
  * @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise.
43
45
  */
44
46
  isPointInside: (point: {
45
47
  x: number;
46
48
  y: number;
47
- }, targetElement?: Element) => boolean;
49
+ }, options?: {
50
+ targetElement?: Element;
51
+ direction?: 'x' | 'y';
52
+ }) => boolean;
48
53
  };
49
54
  export declare const DrawingContext: React.Context<DrawingArea & {
50
55
  /**
@@ -53,12 +53,20 @@ function DrawingProvider(props) {
53
53
  const isPointInside = React.useCallback(({
54
54
  x,
55
55
  y
56
- }, targetElement) => {
56
+ }, options) => {
57
57
  // For element allowed to overflow, wrapping them in <g data-drawing-container /> make them fully part of the drawing area.
58
- if (targetElement && targetElement.closest('[data-drawing-container]')) {
58
+ if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) {
59
59
  return true;
60
60
  }
61
- return x >= drawingArea.left && x <= drawingArea.left + drawingArea.width && y >= drawingArea.top && y <= drawingArea.top + drawingArea.height;
61
+ const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width;
62
+ const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height;
63
+ if (options?.direction === 'x') {
64
+ return isInsideX;
65
+ }
66
+ if (options?.direction === 'y') {
67
+ return isInsideY;
68
+ }
69
+ return isInsideX && isInsideY;
62
70
  }, [drawingArea]);
63
71
  const value = React.useMemo(() => (0, _extends2.default)({
64
72
  chartId: chartId ?? ''
@@ -1,5 +1,5 @@
1
1
  import type { CartesianChartSeriesType, ChartSeries, ChartSeriesType } from '../../models/seriesType/config';
2
- import type { AxisConfig } from '../../models/axis';
2
+ import type { AxisConfig, AxisId } from '../../models/axis';
3
3
  import type { SeriesId } from '../../models/seriesType/common';
4
4
  export type ExtremumGettersConfig<T extends ChartSeriesType = CartesianChartSeriesType> = {
5
5
  [K in T]?: ExtremumGetter<K>;
@@ -8,7 +8,17 @@ type ExtremumGetterParams<T extends ChartSeriesType> = {
8
8
  series: Record<SeriesId, ChartSeries<T>>;
9
9
  axis: AxisConfig;
10
10
  isDefaultAxis: boolean;
11
+ getFilters?: (params: {
12
+ currentAxisId: AxisId | undefined;
13
+ seriesXAxisId?: AxisId;
14
+ seriesYAxisId?: AxisId;
15
+ isDefaultAxis: boolean;
16
+ }) => ExtremumFilter;
11
17
  };
12
- export type ExtremumGetterResult = [number, number] | [null, null];
18
+ export type ExtremumGetterResult = [number, number];
13
19
  export type ExtremumGetter<T extends ChartSeriesType> = (params: ExtremumGetterParams<T>) => ExtremumGetterResult;
20
+ export type ExtremumFilter = (value: {
21
+ x: number | Date | string | null;
22
+ y: number | Date | string | null;
23
+ }, dataIndex: number) => boolean;
14
24
  export {};
@@ -273,6 +273,7 @@ process.env.NODE_ENV !== "production" ? BarChart.propTypes = {
273
273
  slotProps: PropTypes.object,
274
274
  slots: PropTypes.object,
275
275
  stroke: PropTypes.string,
276
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
276
277
  tickFontSize: PropTypes.number,
277
278
  tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
278
279
  tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
@@ -325,6 +326,7 @@ process.env.NODE_ENV !== "production" ? BarChart.propTypes = {
325
326
  slotProps: PropTypes.object,
326
327
  slots: PropTypes.object,
327
328
  stroke: PropTypes.string,
329
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
328
330
  tickFontSize: PropTypes.number,
329
331
  tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
330
332
  tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
@@ -191,6 +191,7 @@ function BarPlot(props) {
191
191
  barLabel
192
192
  } = props,
193
193
  other = _objectWithoutPropertiesLoose(props, _excluded);
194
+ const withoutBorderRadius = !borderRadius || borderRadius <= 0;
194
195
  const transition = useTransition(completedData, {
195
196
  keys: bar => `${bar.seriesId}-${bar.dataIndex}`,
196
197
  from: leaveStyle,
@@ -199,7 +200,7 @@ function BarPlot(props) {
199
200
  update: enterStyle,
200
201
  immediate: skipAnimation
201
202
  });
202
- const maskTransition = useTransition(masksData, {
203
+ const maskTransition = useTransition(withoutBorderRadius ? [] : masksData, {
203
204
  keys: v => v.id,
204
205
  from: leaveStyle,
205
206
  leave: leaveStyle,
@@ -208,7 +209,7 @@ function BarPlot(props) {
208
209
  immediate: skipAnimation
209
210
  });
210
211
  return /*#__PURE__*/_jsxs(React.Fragment, {
211
- children: [maskTransition((style, {
212
+ children: [!withoutBorderRadius && maskTransition((style, {
212
213
  id,
213
214
  hasPositive,
214
215
  hasNegative,
@@ -242,7 +243,7 @@ function BarPlot(props) {
242
243
  }),
243
244
  style: style
244
245
  }));
245
- if (!borderRadius || borderRadius <= 0) {
246
+ if (withoutBorderRadius) {
246
247
  return barElement;
247
248
  }
248
249
  return /*#__PURE__*/_jsx("g", {
@@ -1,31 +1,68 @@
1
+ const createResult = (data, direction) => {
2
+ if (direction === 'x') {
3
+ return {
4
+ x: data,
5
+ y: null
6
+ };
7
+ }
8
+ return {
9
+ x: null,
10
+ y: data
11
+ };
12
+ };
1
13
  const getBaseExtremum = params => {
2
14
  const {
3
- axis
15
+ axis,
16
+ getFilters,
17
+ isDefaultAxis
4
18
  } = params;
5
- const minX = Math.min(...(axis.data ?? []));
6
- const maxX = Math.max(...(axis.data ?? []));
19
+ const filter = getFilters?.({
20
+ currentAxisId: axis.id,
21
+ isDefaultAxis
22
+ });
23
+ const data = filter ? axis.data?.filter((_, i) => filter({
24
+ x: null,
25
+ y: null
26
+ }, i)) : axis.data;
27
+ const minX = Math.min(...(data ?? []));
28
+ const maxX = Math.max(...(data ?? []));
7
29
  return [minX, maxX];
8
30
  };
9
- const getValueExtremum = params => {
31
+ const getValueExtremum = direction => params => {
10
32
  const {
11
33
  series,
12
34
  axis,
35
+ getFilters,
13
36
  isDefaultAxis
14
37
  } = params;
15
38
  return Object.keys(series).filter(seriesId => {
16
39
  const yAxisId = series[seriesId].yAxisId ?? series[seriesId].yAxisKey;
17
40
  return yAxisId === axis.id || isDefaultAxis && yAxisId === undefined;
18
41
  }).reduce((acc, seriesId) => {
19
- const [seriesMin, seriesMax] = series[seriesId].stackedData?.reduce((seriesAcc, values) => [Math.min(...values, ...(seriesAcc[0] === null ? [] : [seriesAcc[0]])), Math.max(...values, ...(seriesAcc[1] === null ? [] : [seriesAcc[1]]))], series[seriesId].stackedData[0]) ?? [null, null];
20
- return [acc[0] === null ? seriesMin : Math.min(seriesMin, acc[0]), acc[1] === null ? seriesMax : Math.max(seriesMax, acc[1])];
21
- }, [null, null]);
42
+ const {
43
+ stackedData
44
+ } = series[seriesId];
45
+ const filter = getFilters?.({
46
+ currentAxisId: axis.id,
47
+ isDefaultAxis,
48
+ seriesXAxisId: series[seriesId].xAxisId ?? series[seriesId].xAxisKey,
49
+ seriesYAxisId: series[seriesId].yAxisId ?? series[seriesId].yAxisKey
50
+ });
51
+ const [seriesMin, seriesMax] = stackedData?.reduce((seriesAcc, values, index) => {
52
+ if (filter && (!filter(createResult(values[0], direction), index) || !filter(createResult(values[1], direction), index))) {
53
+ return seriesAcc;
54
+ }
55
+ return [Math.min(...values, seriesAcc[0]), Math.max(...values, seriesAcc[1])];
56
+ }, [Infinity, -Infinity]) ?? [Infinity, -Infinity];
57
+ return [Math.min(seriesMin, acc[0]), Math.max(seriesMax, acc[1])];
58
+ }, [Infinity, -Infinity]);
22
59
  };
23
60
  export const getExtremumX = params => {
24
61
  // Notice that bar should be all horizontal or all vertical.
25
62
  // Don't think it's a problem for now
26
63
  const isHorizontal = Object.keys(params.series).some(seriesId => params.series[seriesId].layout === 'horizontal');
27
64
  if (isHorizontal) {
28
- return getValueExtremum(params);
65
+ return getValueExtremum('x')(params);
29
66
  }
30
67
  return getBaseExtremum(params);
31
68
  };
@@ -34,5 +71,5 @@ export const getExtremumY = params => {
34
71
  if (isHorizontal) {
35
72
  return getBaseExtremum(params);
36
73
  }
37
- return getValueExtremum(params);
74
+ return getValueExtremum('y')(params);
38
75
  };
@@ -5,7 +5,7 @@ import { DrawingProvider } from '../context/DrawingProvider';
5
5
  import { SeriesProvider } from '../context/SeriesProvider';
6
6
  import { InteractionProvider } from '../context/InteractionProvider';
7
7
  import { ChartsSurface } from '../ChartsSurface';
8
- import { CartesianContextProvider } from '../context/CartesianProvider';
8
+ import { CartesianProvider } from '../context/CartesianProvider';
9
9
  import { ChartsAxesGradients } from '../internals/components/ChartsAxesGradients';
10
10
  import { HighlightedProvider, ZAxisContextProvider } from '../context';
11
11
  import { PluginProvider } from '../context/PluginProvider';
@@ -16,7 +16,7 @@ const ChartContainer = /*#__PURE__*/React.forwardRef(function ChartContainer(pro
16
16
  children,
17
17
  drawingProviderProps,
18
18
  seriesProviderProps,
19
- cartesianContextProps,
19
+ cartesianProviderProps,
20
20
  zAxisContextProps,
21
21
  highlightedProviderProps,
22
22
  chartsSurfaceProps,
@@ -25,7 +25,7 @@ const ChartContainer = /*#__PURE__*/React.forwardRef(function ChartContainer(pro
25
25
  return /*#__PURE__*/_jsx(DrawingProvider, _extends({}, drawingProviderProps, {
26
26
  children: /*#__PURE__*/_jsx(PluginProvider, _extends({}, pluginProviderProps, {
27
27
  children: /*#__PURE__*/_jsx(SeriesProvider, _extends({}, seriesProviderProps, {
28
- children: /*#__PURE__*/_jsx(CartesianContextProvider, _extends({}, cartesianContextProps, {
28
+ children: /*#__PURE__*/_jsx(CartesianProvider, _extends({}, cartesianProviderProps, {
29
29
  children: /*#__PURE__*/_jsx(ZAxisContextProvider, _extends({}, zAxisContextProps, {
30
30
  children: /*#__PURE__*/_jsx(InteractionProvider, {
31
31
  children: /*#__PURE__*/_jsx(HighlightedProvider, _extends({}, highlightedProviderProps, {
@@ -155,6 +155,7 @@ process.env.NODE_ENV !== "production" ? ChartContainer.propTypes = {
155
155
  slotProps: PropTypes.object,
156
156
  slots: PropTypes.object,
157
157
  stroke: PropTypes.string,
158
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
158
159
  tickFontSize: PropTypes.number,
159
160
  tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
160
161
  tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
@@ -207,6 +208,7 @@ process.env.NODE_ENV !== "production" ? ChartContainer.propTypes = {
207
208
  slotProps: PropTypes.object,
208
209
  slots: PropTypes.object,
209
210
  stroke: PropTypes.string,
211
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
210
212
  tickFontSize: PropTypes.number,
211
213
  tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
212
214
  tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
@@ -30,7 +30,7 @@ export const useChartContainerProps = (props, ref) => {
30
30
  const chartSurfaceRef = useForkRef(ref, svgRef);
31
31
  useReducedMotion(); // a11y reduce motion (see: https://react-spring.dev/docs/utilities/use-reduced-motion)
32
32
 
33
- const [defaultizedXAxis, defaultizedYAxis] = useDefaultizeAxis(xAxis, yAxis);
33
+ const [defaultizedXAxis, defaultizedYAxis] = useDefaultizeAxis(xAxis, yAxis, dataset);
34
34
  const drawingProviderProps = {
35
35
  width,
36
36
  height,
@@ -45,7 +45,7 @@ export const useChartContainerProps = (props, ref) => {
45
45
  colors,
46
46
  dataset
47
47
  };
48
- const cartesianContextProps = {
48
+ const cartesianProviderProps = {
49
49
  xAxis: defaultizedXAxis,
50
50
  yAxis: defaultizedYAxis,
51
51
  dataset
@@ -71,7 +71,7 @@ export const useChartContainerProps = (props, ref) => {
71
71
  children,
72
72
  drawingProviderProps,
73
73
  seriesProviderProps,
74
- cartesianContextProps,
74
+ cartesianProviderProps,
75
75
  zAxisContextProps,
76
76
  highlightedProviderProps,
77
77
  chartsSurfaceProps,
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../constants';
4
- const defaultizeAxis = (inAxis, axisName) => {
4
+ const defaultizeAxis = (inAxis, dataset, axisName) => {
5
5
  const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY;
6
6
  return [...(inAxis?.map((axis, index) => _extends({
7
7
  id: `defaultized-${axisName}-axis-${index}`
@@ -10,10 +10,21 @@ const defaultizeAxis = (inAxis, axisName) => {
10
10
  }) => id === DEFAULT_AXIS_KEY) === -1 ? [{
11
11
  id: DEFAULT_AXIS_KEY,
12
12
  scaleType: 'linear'
13
- }] : [])];
13
+ }] : [])].map(axisConfig => {
14
+ const dataKey = axisConfig.dataKey;
15
+ if (dataKey === undefined || axisConfig.data !== undefined) {
16
+ return axisConfig;
17
+ }
18
+ if (dataset === undefined) {
19
+ throw Error(`MUI X: ${axisName}-axis uses \`dataKey\` but no \`dataset\` is provided.`);
20
+ }
21
+ return _extends({}, axisConfig, {
22
+ data: dataset.map(d => d[dataKey])
23
+ });
24
+ });
14
25
  };
15
- export const useDefaultizeAxis = (inXAxis, inYAxis) => {
16
- const xAxis = React.useMemo(() => defaultizeAxis(inXAxis, 'x'), [inXAxis]);
17
- const yAxis = React.useMemo(() => defaultizeAxis(inYAxis, 'y'), [inYAxis]);
26
+ export const useDefaultizeAxis = (inXAxis, inYAxis, dataset) => {
27
+ const xAxis = React.useMemo(() => defaultizeAxis(inXAxis, dataset, 'x'), [inXAxis, dataset]);
28
+ const yAxis = React.useMemo(() => defaultizeAxis(inYAxis, dataset, 'y'), [inYAxis, dataset]);
18
29
  return [xAxis, yAxis];
19
30
  };
@@ -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
- }) => _extends({
31
- pointerEvents: 'none'
32
- }, ownerState.axisHighlight === 'band' && {
33
- fill: theme.palette.mode === 'light' ? 'gray' : 'white',
34
- fillOpacity: 0.1
35
- }, ownerState.axisHighlight === 'line' && {
36
- strokeDasharray: '5 2',
37
- stroke: theme.palette.mode === 'light' ? '#000000' : '#ffffff'
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: yScale.range()[0],
97
- y2: yScale.range()[1],
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: xScale.range()[0],
108
- x2: xScale.range()[1],
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
- setMousePosition(null);
50
+ const handleOut = event => {
51
+ if (event.pointerType !== 'mouse') {
52
+ setMousePosition(null);
53
+ }
52
54
  };
53
55
  const handleMove = event => {
54
56
  setMousePosition({