@mui/x-charts 6.0.0-alpha.15 → 6.0.0-alpha.16

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 (173) hide show
  1. package/BarChart/BarChart.d.ts +13 -2
  2. package/BarChart/BarChart.js +45 -3
  3. package/BarChart/BarElement.d.ts +1318 -3
  4. package/BarChart/BarElement.js +10 -8
  5. package/BarChart/BarPlot.d.ts +17 -1
  6. package/BarChart/BarPlot.js +152 -66
  7. package/CHANGELOG.md +65 -0
  8. package/ChartContainer/index.js +5 -2
  9. package/ChartsAxis/ChartsAxis.js +18 -2
  10. package/ChartsAxis/axisClasses.d.ts +1 -1
  11. package/ChartsAxisHighlight/ChartsAxisHighlight.js +2 -2
  12. package/ChartsClipPath/ChartsClipPath.js +2 -2
  13. package/ChartsLegend/ChartsLegend.d.ts +2 -1
  14. package/ChartsLegend/ChartsLegend.js +12 -8
  15. package/ChartsSurface.js +2 -2
  16. package/ChartsTooltip/ChartsAxisTooltipContent.js +2 -2
  17. package/ChartsTooltip/ChartsItemTooltipContent.js +2 -2
  18. package/ChartsTooltip/ChartsTooltip.js +2 -2
  19. package/ChartsTooltip/utils.js +2 -2
  20. package/ChartsXAxis/ChartsXAxis.js +123 -35
  21. package/ChartsYAxis/ChartsYAxis.js +38 -16
  22. package/LineChart/AreaElement.d.ts +10 -0
  23. package/LineChart/AreaElement.js +12 -2
  24. package/LineChart/AreaPlot.d.ts +11 -0
  25. package/LineChart/AreaPlot.js +13 -2
  26. package/LineChart/LineChart.d.ts +10 -0
  27. package/LineChart/LineChart.js +36 -2
  28. package/LineChart/LineElement.d.ts +10 -0
  29. package/LineChart/LineElement.js +12 -2
  30. package/LineChart/LineHighlightElement.d.ts +10 -0
  31. package/LineChart/LineHighlightElement.js +12 -2
  32. package/LineChart/LineHighlightPlot.d.ts +10 -0
  33. package/LineChart/LineHighlightPlot.js +12 -2
  34. package/LineChart/LinePlot.d.ts +10 -0
  35. package/LineChart/LinePlot.js +12 -2
  36. package/LineChart/MarkElement.d.ts +10 -0
  37. package/LineChart/MarkElement.js +12 -2
  38. package/LineChart/MarkPlot.d.ts +10 -0
  39. package/LineChart/MarkPlot.js +12 -2
  40. package/PieChart/PieArc.js +2 -2
  41. package/PieChart/PieArcLabel.js +2 -2
  42. package/PieChart/PieChart.d.ts +10 -0
  43. package/PieChart/PieChart.js +37 -2
  44. package/PieChart/PiePlot.d.ts +10 -0
  45. package/PieChart/PiePlot.js +12 -2
  46. package/ResponsiveChartContainer/index.js +4 -4
  47. package/ScatterChart/Scatter.d.ts +10 -0
  48. package/ScatterChart/Scatter.js +12 -2
  49. package/ScatterChart/ScatterChart.d.ts +10 -0
  50. package/ScatterChart/ScatterChart.js +36 -2
  51. package/ScatterChart/ScatterPlot.d.ts +10 -0
  52. package/ScatterChart/ScatterPlot.js +12 -2
  53. package/SparkLineChart/SparkLineChart.d.ts +9 -0
  54. package/SparkLineChart/SparkLineChart.js +16 -2
  55. package/context/CartesianContextProvider.js +10 -2
  56. package/context/DrawingProvider.js +2 -2
  57. package/context/HighlightProvider.js +2 -2
  58. package/context/InteractionProvider.js +2 -2
  59. package/context/SeriesContextProvider.js +2 -2
  60. package/esm/BarChart/BarChart.js +43 -1
  61. package/esm/BarChart/BarElement.js +7 -4
  62. package/esm/BarChart/BarPlot.js +152 -67
  63. package/esm/ChartContainer/index.js +3 -0
  64. package/esm/ChartsAxis/ChartsAxis.js +16 -0
  65. package/esm/ChartsLegend/ChartsLegend.js +10 -6
  66. package/esm/ChartsXAxis/ChartsXAxis.js +122 -34
  67. package/esm/ChartsYAxis/ChartsYAxis.js +36 -14
  68. package/esm/LineChart/AreaElement.js +10 -0
  69. package/esm/LineChart/AreaPlot.js +11 -0
  70. package/esm/LineChart/LineChart.js +34 -0
  71. package/esm/LineChart/LineElement.js +10 -0
  72. package/esm/LineChart/LineHighlightElement.js +10 -0
  73. package/esm/LineChart/LineHighlightPlot.js +10 -0
  74. package/esm/LineChart/LinePlot.js +10 -0
  75. package/esm/LineChart/MarkElement.js +10 -0
  76. package/esm/LineChart/MarkPlot.js +10 -0
  77. package/esm/PieChart/PieChart.js +35 -0
  78. package/esm/PieChart/PiePlot.js +10 -0
  79. package/esm/ResponsiveChartContainer/index.js +2 -2
  80. package/esm/ScatterChart/Scatter.js +10 -0
  81. package/esm/ScatterChart/ScatterChart.js +34 -0
  82. package/esm/ScatterChart/ScatterPlot.js +10 -0
  83. package/esm/SparkLineChart/SparkLineChart.js +14 -0
  84. package/esm/context/CartesianContextProvider.js +8 -0
  85. package/esm/hooks/useMounted.js +16 -0
  86. package/esm/hooks/useReducedMotion.js +27 -0
  87. package/esm/hooks/useTicks.js +12 -6
  88. package/esm/internals/components/ChartsText.js +17 -13
  89. package/esm/internals/geometry.js +36 -0
  90. package/hooks/useAxisEvents.js +2 -2
  91. package/hooks/useChartDimensions.js +2 -2
  92. package/hooks/useDrawingArea.js +2 -2
  93. package/hooks/useInteractionItemProps.js +2 -2
  94. package/hooks/useMounted.d.ts +1 -0
  95. package/hooks/useMounted.js +25 -0
  96. package/hooks/useReducedMotion.d.ts +8 -0
  97. package/hooks/useReducedMotion.js +33 -0
  98. package/hooks/useScale.d.ts +2 -2
  99. package/hooks/useScale.js +2 -2
  100. package/hooks/useTicks.d.ts +18 -9
  101. package/hooks/useTicks.js +14 -8
  102. package/index.js +1 -1
  103. package/internals/components/ChartsText.d.ts +11 -8
  104. package/internals/components/ChartsText.js +19 -15
  105. package/internals/defaultizeColor.d.ts +1 -1
  106. package/internals/domUtils.d.ts +0 -1
  107. package/internals/geometry.d.ts +9 -0
  108. package/internals/geometry.js +42 -0
  109. package/legacy/BarChart/BarChart.js +43 -1
  110. package/legacy/BarChart/BarElement.js +6 -3
  111. package/legacy/BarChart/BarPlot.js +151 -63
  112. package/legacy/ChartContainer/index.js +3 -0
  113. package/legacy/ChartsAxis/ChartsAxis.js +16 -0
  114. package/legacy/ChartsLegend/ChartsLegend.js +14 -7
  115. package/legacy/ChartsXAxis/ChartsXAxis.js +126 -36
  116. package/legacy/ChartsYAxis/ChartsYAxis.js +36 -14
  117. package/legacy/LineChart/AreaElement.js +10 -0
  118. package/legacy/LineChart/AreaPlot.js +11 -0
  119. package/legacy/LineChart/LineChart.js +34 -0
  120. package/legacy/LineChart/LineElement.js +10 -0
  121. package/legacy/LineChart/LineHighlightElement.js +10 -0
  122. package/legacy/LineChart/LineHighlightPlot.js +10 -0
  123. package/legacy/LineChart/LinePlot.js +10 -0
  124. package/legacy/LineChart/MarkElement.js +10 -0
  125. package/legacy/LineChart/MarkPlot.js +10 -0
  126. package/legacy/PieChart/PieChart.js +35 -0
  127. package/legacy/PieChart/PiePlot.js +10 -0
  128. package/legacy/ResponsiveChartContainer/index.js +2 -2
  129. package/legacy/ScatterChart/Scatter.js +10 -0
  130. package/legacy/ScatterChart/ScatterChart.js +34 -0
  131. package/legacy/ScatterChart/ScatterPlot.js +10 -0
  132. package/legacy/SparkLineChart/SparkLineChart.js +14 -0
  133. package/legacy/context/CartesianContextProvider.js +8 -0
  134. package/legacy/hooks/useMounted.js +21 -0
  135. package/legacy/hooks/useReducedMotion.js +27 -0
  136. package/legacy/hooks/useTicks.js +13 -6
  137. package/legacy/index.js +1 -1
  138. package/legacy/internals/components/ChartsText.js +15 -15
  139. package/legacy/internals/geometry.js +37 -0
  140. package/models/axis.d.ts +19 -2
  141. package/models/seriesType/line.d.ts +2 -2
  142. package/modern/BarChart/BarChart.js +43 -1
  143. package/modern/BarChart/BarElement.js +7 -4
  144. package/modern/BarChart/BarPlot.js +149 -65
  145. package/modern/ChartContainer/index.js +3 -0
  146. package/modern/ChartsAxis/ChartsAxis.js +16 -0
  147. package/modern/ChartsLegend/ChartsLegend.js +10 -6
  148. package/modern/ChartsXAxis/ChartsXAxis.js +122 -34
  149. package/modern/ChartsYAxis/ChartsYAxis.js +36 -14
  150. package/modern/LineChart/AreaElement.js +10 -0
  151. package/modern/LineChart/AreaPlot.js +11 -0
  152. package/modern/LineChart/LineChart.js +34 -0
  153. package/modern/LineChart/LineElement.js +10 -0
  154. package/modern/LineChart/LineHighlightElement.js +10 -0
  155. package/modern/LineChart/LineHighlightPlot.js +10 -0
  156. package/modern/LineChart/LinePlot.js +10 -0
  157. package/modern/LineChart/MarkElement.js +10 -0
  158. package/modern/LineChart/MarkPlot.js +10 -0
  159. package/modern/PieChart/PieChart.js +35 -0
  160. package/modern/PieChart/PiePlot.js +10 -0
  161. package/modern/ResponsiveChartContainer/index.js +2 -2
  162. package/modern/ScatterChart/Scatter.js +10 -0
  163. package/modern/ScatterChart/ScatterChart.js +34 -0
  164. package/modern/ScatterChart/ScatterPlot.js +10 -0
  165. package/modern/SparkLineChart/SparkLineChart.js +14 -0
  166. package/modern/context/CartesianContextProvider.js +8 -0
  167. package/modern/hooks/useMounted.js +16 -0
  168. package/modern/hooks/useReducedMotion.js +27 -0
  169. package/modern/hooks/useTicks.js +12 -6
  170. package/modern/index.js +1 -1
  171. package/modern/internals/components/ChartsText.js +17 -13
  172. package/modern/internals/geometry.js +36 -0
  173. package/package.json +5 -3
@@ -1,11 +1,14 @@
1
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
1
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
+ const _excluded = ["skipAnimation"];
2
4
  import * as React from 'react';
3
5
  import PropTypes from 'prop-types';
6
+ import { useTransition } from '@react-spring/web';
4
7
  import { SeriesContext } from '../context/SeriesContextProvider';
5
8
  import { CartesianContext } from '../context/CartesianContextProvider';
6
9
  import { BarElement } from './BarElement';
7
10
  import { isBandScaleConfig } from '../models/axis';
8
-
11
+ import { jsx as _jsx } from "react/jsx-runtime";
9
12
  /**
10
13
  * Solution of the equations
11
14
  * W = barWidth * N + offset * (N-1)
@@ -15,7 +18,6 @@ import { isBandScaleConfig } from '../models/axis';
15
18
  * @param gapRatio The ratio of the gap between bars over the bar width.
16
19
  * @returns The bar width and the offset between bars.
17
20
  */
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
21
  function getBandSize({
20
22
  bandWidth: W,
21
23
  numberOfGroups: N,
@@ -34,12 +36,13 @@ function getBandSize({
34
36
  offset
35
37
  };
36
38
  }
37
- function BarPlot(props) {
38
- const seriesData = React.useContext(SeriesContext).bar;
39
+ const useCompletedData = () => {
40
+ const seriesData = React.useContext(SeriesContext).bar ?? {
41
+ series: {},
42
+ stackingGroups: [],
43
+ seriesOrder: []
44
+ };
39
45
  const axisData = React.useContext(CartesianContext);
40
- if (seriesData === undefined) {
41
- return null;
42
- }
43
46
  const {
44
47
  series,
45
48
  stackingGroups
@@ -52,66 +55,142 @@ function BarPlot(props) {
52
55
  } = axisData;
53
56
  const defaultXAxisId = xAxisIds[0];
54
57
  const defaultYAxisId = yAxisIds[0];
55
- return /*#__PURE__*/_jsx(React.Fragment, {
56
- children: stackingGroups.flatMap(({
57
- ids: groupIds
58
- }, groupIndex) => {
59
- return groupIds.flatMap(seriesId => {
60
- const xAxisKey = series[seriesId].xAxisKey ?? defaultXAxisId;
61
- const yAxisKey = series[seriesId].yAxisKey ?? defaultYAxisId;
62
- const xAxisConfig = xAxis[xAxisKey];
63
- const yAxisConfig = yAxis[yAxisKey];
64
- const verticalLayout = series[seriesId].layout === 'vertical';
65
- let baseScaleConfig;
66
- if (verticalLayout) {
67
- if (!isBandScaleConfig(xAxisConfig)) {
68
- throw new Error(`Axis with id "${xAxisKey}" shoud be of type "band" to display the bar series of id "${seriesId}"`);
69
- }
70
- if (xAxis[xAxisKey].data === undefined) {
71
- throw new Error(`Axis with id "${xAxisKey}" shoud have data property`);
72
- }
73
- baseScaleConfig = xAxisConfig;
74
- } else {
75
- if (!isBandScaleConfig(yAxisConfig)) {
76
- throw new Error(`Axis with id "${yAxisKey}" shoud be of type "band" to display the bar series of id "${seriesId}"`);
77
- }
78
- if (yAxis[yAxisKey].data === undefined) {
79
- throw new Error(`Axis with id "${xAxisKey}" shoud have data property`);
80
- }
81
- baseScaleConfig = yAxisConfig;
58
+ const data = stackingGroups.flatMap(({
59
+ ids: groupIds
60
+ }, groupIndex) => {
61
+ return groupIds.flatMap(seriesId => {
62
+ const xAxisKey = series[seriesId].xAxisKey ?? defaultXAxisId;
63
+ const yAxisKey = series[seriesId].yAxisKey ?? defaultYAxisId;
64
+ const xAxisConfig = xAxis[xAxisKey];
65
+ const yAxisConfig = yAxis[yAxisKey];
66
+ const verticalLayout = series[seriesId].layout === 'vertical';
67
+ let baseScaleConfig;
68
+ if (verticalLayout) {
69
+ if (!isBandScaleConfig(xAxisConfig)) {
70
+ throw new Error(`Axis with id "${xAxisKey}" shoud be of type "band" to display the bar series of id "${seriesId}"`);
71
+ }
72
+ if (xAxis[xAxisKey].data === undefined) {
73
+ throw new Error(`Axis with id "${xAxisKey}" shoud have data property`);
74
+ }
75
+ baseScaleConfig = xAxisConfig;
76
+ } else {
77
+ if (!isBandScaleConfig(yAxisConfig)) {
78
+ throw new Error(`Axis with id "${yAxisKey}" shoud be of type "band" to display the bar series of id "${seriesId}"`);
82
79
  }
83
- const xScale = xAxisConfig.scale;
84
- const yScale = yAxisConfig.scale;
85
- const bandWidth = baseScaleConfig.scale.bandwidth();
86
- const {
87
- barWidth,
88
- offset
89
- } = getBandSize({
90
- bandWidth,
91
- numberOfGroups: stackingGroups.length,
92
- gapRatio: baseScaleConfig.barGapRatio
93
- });
94
- const barOffset = groupIndex * (barWidth + offset);
95
- const {
96
- stackedData,
97
- color
98
- } = series[seriesId];
99
- return stackedData.map((values, dataIndex) => {
100
- const baseline = Math.min(...values);
101
- const value = Math.max(...values);
102
- return /*#__PURE__*/_jsx(BarElement, _extends({
103
- id: seriesId,
104
- dataIndex: dataIndex,
105
- x: verticalLayout ? xScale(xAxis[xAxisKey].data?.[dataIndex]) + barOffset : xScale(baseline),
106
- y: verticalLayout ? yScale(value) : yScale(yAxis[yAxisKey].data?.[dataIndex]) + barOffset,
107
- height: verticalLayout ? Math.abs(yScale(baseline) - yScale(value)) : barWidth,
108
- width: verticalLayout ? barWidth : Math.abs(xScale(baseline) - xScale(value)),
109
- color: color,
110
- highlightScope: series[seriesId].highlightScope
111
- }, props), `${seriesId}-${dataIndex}`);
112
- });
80
+ if (yAxis[yAxisKey].data === undefined) {
81
+ throw new Error(`Axis with id "${xAxisKey}" shoud have data property`);
82
+ }
83
+ baseScaleConfig = yAxisConfig;
84
+ }
85
+ const xScale = xAxisConfig.scale;
86
+ const yScale = yAxisConfig.scale;
87
+ const bandWidth = baseScaleConfig.scale.bandwidth();
88
+ const {
89
+ barWidth,
90
+ offset
91
+ } = getBandSize({
92
+ bandWidth,
93
+ numberOfGroups: stackingGroups.length,
94
+ gapRatio: baseScaleConfig.barGapRatio
95
+ });
96
+ const barOffset = groupIndex * (barWidth + offset);
97
+ const {
98
+ stackedData,
99
+ color
100
+ } = series[seriesId];
101
+ return stackedData.map((values, dataIndex) => {
102
+ const bottom = Math.min(...values);
103
+ const top = Math.max(...values);
104
+ return {
105
+ bottom,
106
+ top,
107
+ seriesId,
108
+ dataIndex,
109
+ layout: series[seriesId].layout,
110
+ x: verticalLayout ? xScale(xAxis[xAxisKey].data?.[dataIndex]) + barOffset : xScale(bottom),
111
+ y: verticalLayout ? yScale(top) : yScale(yAxis[yAxisKey].data?.[dataIndex]) + barOffset,
112
+ xOrigin: xScale(0),
113
+ yOrigin: yScale(0),
114
+ height: verticalLayout ? Math.abs(yScale(bottom) - yScale(top)) : barWidth,
115
+ width: verticalLayout ? barWidth : Math.abs(xScale(bottom) - xScale(top)),
116
+ color,
117
+ highlightScope: series[seriesId].highlightScope
118
+ };
113
119
  });
114
- })
120
+ });
121
+ });
122
+ return data;
123
+ };
124
+ const getOutStyle = ({
125
+ layout,
126
+ yOrigin,
127
+ x,
128
+ width,
129
+ y,
130
+ xOrigin,
131
+ height
132
+ }) => _extends({}, layout === 'vertical' ? {
133
+ y: yOrigin,
134
+ x,
135
+ height: 0,
136
+ width
137
+ } : {
138
+ y,
139
+ x: xOrigin,
140
+ height,
141
+ width: 0
142
+ });
143
+ const getInStyle = ({
144
+ x,
145
+ width,
146
+ y,
147
+ height
148
+ }) => ({
149
+ y,
150
+ x,
151
+ height,
152
+ width
153
+ });
154
+
155
+ /**
156
+ * Demos:
157
+ *
158
+ * - [Bars](https://mui.com/x/react-charts/bars/)
159
+ * - [Bar demonstration](https://mui.com/x/react-charts/bar-demo/)
160
+ * - [Stacking](https://mui.com/x/react-charts/stacking/)
161
+ *
162
+ * API:
163
+ *
164
+ * - [BarPlot API](https://mui.com/x/api/charts/bar-plot/)
165
+ */
166
+ function BarPlot(props) {
167
+ const completedData = useCompletedData();
168
+ const {
169
+ skipAnimation
170
+ } = props,
171
+ other = _objectWithoutPropertiesLoose(props, _excluded);
172
+ const transition = useTransition(completedData, {
173
+ keys: bar => `${bar.seriesId}-${bar.dataIndex}`,
174
+ from: getOutStyle,
175
+ leave: getOutStyle,
176
+ enter: getInStyle,
177
+ update: getInStyle,
178
+ immediate: skipAnimation
179
+ });
180
+ return /*#__PURE__*/_jsx(React.Fragment, {
181
+ children: transition((style, {
182
+ seriesId,
183
+ dataIndex,
184
+ color,
185
+ highlightScope
186
+ }) => /*#__PURE__*/_jsx(BarElement, _extends({
187
+ id: seriesId,
188
+ dataIndex: dataIndex,
189
+ highlightScope: highlightScope,
190
+ color: color
191
+ }, other, {
192
+ style: style
193
+ })))
115
194
  });
116
195
  }
117
196
  process.env.NODE_ENV !== "production" ? BarPlot.propTypes = {
@@ -119,6 +198,11 @@ process.env.NODE_ENV !== "production" ? BarPlot.propTypes = {
119
198
  // | These PropTypes are generated from the TypeScript type definitions |
120
199
  // | To update them edit the TypeScript types and run "yarn proptypes" |
121
200
  // ----------------------------------------------------------------------
201
+ /**
202
+ * If `true`, animations are skiped.
203
+ * @default false
204
+ */
205
+ skipAnimation: PropTypes.bool,
122
206
  /**
123
207
  * The props used for each component slot.
124
208
  * @default {}
@@ -3,6 +3,7 @@ import useForkRef from '@mui/utils/useForkRef';
3
3
  import { DrawingProvider } from '../context/DrawingProvider';
4
4
  import { SeriesContextProvider } from '../context/SeriesContextProvider';
5
5
  import { InteractionProvider } from '../context/InteractionProvider';
6
+ import { useReducedMotion } from '../hooks/useReducedMotion';
6
7
  import { ChartsSurface } from '../ChartsSurface';
7
8
  import { CartesianContextProvider } from '../context/CartesianContextProvider';
8
9
  import { HighlightProvider } from '../context/HighlightProvider';
@@ -25,6 +26,8 @@ export const ChartContainer = /*#__PURE__*/React.forwardRef(function ChartContai
25
26
  } = props;
26
27
  const svgRef = React.useRef(null);
27
28
  const handleRef = useForkRef(ref, svgRef);
29
+ useReducedMotion(); // a11y reduce motion (see: https://react-spring.dev/docs/utilities/use-reduced-motion)
30
+
28
31
  return /*#__PURE__*/_jsx(DrawingProvider, {
29
32
  width: width,
30
33
  height: height,
@@ -97,11 +97,15 @@ process.env.NODE_ENV !== "production" ? ChartsAxis.propTypes = {
97
97
  fill: PropTypes.string,
98
98
  label: PropTypes.string,
99
99
  labelFontSize: PropTypes.number,
100
+ labelStyle: PropTypes.object,
100
101
  position: PropTypes.oneOf(['bottom', 'top']),
101
102
  slotProps: PropTypes.object,
102
103
  slots: PropTypes.object,
103
104
  stroke: PropTypes.string,
104
105
  tickFontSize: PropTypes.number,
106
+ tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
107
+ tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
108
+ tickLabelStyle: PropTypes.object,
105
109
  tickMaxStep: PropTypes.number,
106
110
  tickMinStep: PropTypes.number,
107
111
  tickNumber: PropTypes.number,
@@ -120,11 +124,15 @@ process.env.NODE_ENV !== "production" ? ChartsAxis.propTypes = {
120
124
  fill: PropTypes.string,
121
125
  label: PropTypes.string,
122
126
  labelFontSize: PropTypes.number,
127
+ labelStyle: PropTypes.object,
123
128
  position: PropTypes.oneOf(['left', 'right']),
124
129
  slotProps: PropTypes.object,
125
130
  slots: PropTypes.object,
126
131
  stroke: PropTypes.string,
127
132
  tickFontSize: PropTypes.number,
133
+ tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
134
+ tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
135
+ tickLabelStyle: PropTypes.object,
128
136
  tickMaxStep: PropTypes.number,
129
137
  tickMinStep: PropTypes.number,
130
138
  tickNumber: PropTypes.number,
@@ -143,11 +151,15 @@ process.env.NODE_ENV !== "production" ? ChartsAxis.propTypes = {
143
151
  fill: PropTypes.string,
144
152
  label: PropTypes.string,
145
153
  labelFontSize: PropTypes.number,
154
+ labelStyle: PropTypes.object,
146
155
  position: PropTypes.oneOf(['left', 'right']),
147
156
  slotProps: PropTypes.object,
148
157
  slots: PropTypes.object,
149
158
  stroke: PropTypes.string,
150
159
  tickFontSize: PropTypes.number,
160
+ tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
161
+ tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
162
+ tickLabelStyle: PropTypes.object,
151
163
  tickMaxStep: PropTypes.number,
152
164
  tickMinStep: PropTypes.number,
153
165
  tickNumber: PropTypes.number,
@@ -176,11 +188,15 @@ process.env.NODE_ENV !== "production" ? ChartsAxis.propTypes = {
176
188
  fill: PropTypes.string,
177
189
  label: PropTypes.string,
178
190
  labelFontSize: PropTypes.number,
191
+ labelStyle: PropTypes.object,
179
192
  position: PropTypes.oneOf(['bottom', 'top']),
180
193
  slotProps: PropTypes.object,
181
194
  slots: PropTypes.object,
182
195
  stroke: PropTypes.string,
183
196
  tickFontSize: PropTypes.number,
197
+ tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
198
+ tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
199
+ tickLabelStyle: PropTypes.object,
184
200
  tickMaxStep: PropTypes.number,
185
201
  tickMinStep: PropTypes.number,
186
202
  tickNumber: PropTypes.number,
@@ -1,6 +1,7 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
- const _excluded = ["label"];
3
+ const _excluded = ["rotate", "dominantBaseline"],
4
+ _excluded2 = ["label"];
4
5
  import * as React from 'react';
5
6
  import { useSlotProps } from '@mui/base/utils';
6
7
  import { NoSsr } from '@mui/base/NoSsr';
@@ -75,11 +76,16 @@ function DefaultChartsLegend(props) {
75
76
  const theme = useTheme();
76
77
  const labelStyle = React.useMemo(() => _extends({}, theme.typography.subtitle1, {
77
78
  color: 'inherit',
79
+ dominantBaseline: 'central',
80
+ textAnchor: 'start',
78
81
  fill: (theme.vars || theme).palette.text.primary,
79
82
  lineHeight: 1
80
- }, inLabelStyle), [inLabelStyle, theme]);
83
+ }, inLabelStyle),
84
+ // To say to TS that the dominantBaseline and textAnchor are correct
85
+ [inLabelStyle, theme]);
81
86
  const padding = React.useMemo(() => getStandardizedPadding(paddingProps), [paddingProps]);
82
- const getItemSpace = React.useCallback((label, style) => {
87
+ const getItemSpace = React.useCallback((label, inStyle = {}) => {
88
+ const style = _objectWithoutPropertiesLoose(inStyle, _excluded);
83
89
  const linesSize = getWordsByLines({
84
90
  style,
85
91
  needsComputation: true,
@@ -112,7 +118,7 @@ function DefaultChartsLegend(props) {
112
118
  let {
113
119
  label
114
120
  } = _ref,
115
- other = _objectWithoutPropertiesLoose(_ref, _excluded);
121
+ other = _objectWithoutPropertiesLoose(_ref, _excluded2);
116
122
  const itemSpace = getItemSpace(label, labelStyle);
117
123
  const rep = _extends({}, other, {
118
124
  label,
@@ -219,8 +225,6 @@ function DefaultChartsLegend(props) {
219
225
  fill: color
220
226
  }), /*#__PURE__*/_jsx(ChartsText, {
221
227
  style: labelStyle,
222
- dominantBaseline: "central",
223
- textAnchor: "start",
224
228
  text: label,
225
229
  x: itemMarkWidth + markGap,
226
230
  y: 0
@@ -11,7 +11,9 @@ import { DrawingContext } from '../context/DrawingProvider';
11
11
  import useTicks from '../hooks/useTicks';
12
12
  import { getAxisUtilityClass } from '../ChartsAxis/axisClasses';
13
13
  import { AxisRoot } from '../internals/components/AxisSharedComponents';
14
- import { ChartsText } from '../internals/components/ChartsText';
14
+ import { ChartsText, getWordsByLines } from '../internals/components/ChartsText';
15
+ import { getMinXTranslation } from '../internals/geometry';
16
+ import { useMounted } from '../hooks/useMounted';
15
17
  import { jsx as _jsx } from "react/jsx-runtime";
16
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
17
19
  const useUtilityClasses = ownerState => {
@@ -29,12 +31,64 @@ const useUtilityClasses = ownerState => {
29
31
  };
30
32
  return composeClasses(slots, getAxisUtilityClass, classes);
31
33
  };
34
+ function addLabelDimension(xTicks, {
35
+ tickLabelStyle: style,
36
+ tickLabelInterval,
37
+ isMounted
38
+ }) {
39
+ const withDimension = xTicks.map(tick => {
40
+ if (!isMounted || tick.formattedValue === undefined) {
41
+ return _extends({}, tick, {
42
+ width: 0,
43
+ height: 0
44
+ });
45
+ }
46
+ const tickSizes = getWordsByLines({
47
+ style,
48
+ needsComputation: true,
49
+ text: tick.formattedValue
50
+ });
51
+ return _extends({}, tick, {
52
+ width: Math.max(...tickSizes.map(size => size.width)),
53
+ height: Math.max(tickSizes.length * tickSizes[0].height)
54
+ });
55
+ });
56
+ if (typeof tickLabelInterval === 'function') {
57
+ return withDimension.map((item, index) => _extends({}, item, {
58
+ skipLabel: !tickLabelInterval(item.value, index)
59
+ }));
60
+ }
61
+
62
+ // Filter label to avoid overlap
63
+ let textStart = 0;
64
+ let textEnd = 0;
65
+ return withDimension.map((item, labelIndex) => {
66
+ const {
67
+ width,
68
+ offset,
69
+ labelOffset,
70
+ height
71
+ } = item;
72
+ const distance = getMinXTranslation(width, height, style?.angle);
73
+ const textPosition = offset + labelOffset;
74
+ const gapRatio = 1.2; // Ratio applied to the minimal distance to add some margin.
75
+
76
+ textStart = textPosition - gapRatio * distance / 2;
77
+ if (labelIndex > 0 && textStart < textEnd) {
78
+ // Except for the first label, we skip all label that overlap with the last accepted.
79
+ // Notice that the early return prevents `textEnd` from being updated.
80
+ return _extends({}, item, {
81
+ skipLabel: true
82
+ });
83
+ }
84
+ textEnd = textPosition + gapRatio * distance / 2;
85
+ return item;
86
+ });
87
+ }
32
88
  const defaultProps = {
33
89
  position: 'bottom',
34
90
  disableLine: false,
35
91
  disableTicks: false,
36
- tickFontSize: 12,
37
- labelFontSize: 14,
38
92
  tickSize: 6
39
93
  };
40
94
  function ChartsXAxis(inProps) {
@@ -53,18 +107,23 @@ function ChartsXAxis(inProps) {
53
107
  }
54
108
  } = _React$useContext,
55
109
  settings = _objectWithoutPropertiesLoose(_React$useContext.xAxis[_props$axisId], _excluded);
110
+ const isMounted = useMounted();
56
111
  const defaultizedProps = _extends({}, defaultProps, settings, props);
57
112
  const {
58
113
  position,
59
114
  disableLine,
60
115
  disableTicks,
61
- tickFontSize,
116
+ tickLabelStyle,
62
117
  label,
118
+ labelStyle,
119
+ tickFontSize,
63
120
  labelFontSize,
64
121
  tickSize: tickSizeProp,
65
122
  valueFormatter,
66
123
  slots,
67
- slotProps
124
+ slotProps,
125
+ tickInterval,
126
+ tickLabelInterval
68
127
  } = defaultizedProps;
69
128
  const theme = useTheme();
70
129
  const classes = useUtilityClasses(_extends({}, defaultizedProps, {
@@ -77,16 +136,7 @@ function ChartsXAxis(inProps) {
77
136
  height
78
137
  } = React.useContext(DrawingContext);
79
138
  const tickSize = disableTicks ? 4 : tickSizeProp;
80
- const xTicks = useTicks({
81
- scale: xScale,
82
- tickNumber,
83
- valueFormatter
84
- });
85
- const positionSigne = position === 'bottom' ? 1 : -1;
86
- const labelRefPoint = {
87
- x: left + width / 2,
88
- y: positionSigne * (tickFontSize + tickSize + 10)
89
- };
139
+ const positionSign = position === 'bottom' ? 1 : -1;
90
140
  const Line = slots?.axisLine ?? 'line';
91
141
  const Tick = slots?.axisTick ?? 'line';
92
142
  const TickLabel = slots?.axisTickLabel ?? ChartsText;
@@ -95,27 +145,40 @@ function ChartsXAxis(inProps) {
95
145
  elementType: TickLabel,
96
146
  externalSlotProps: slotProps?.axisTickLabel,
97
147
  additionalProps: {
98
- textAnchor: 'middle',
99
- dominantBaseline: position === 'bottom' ? 'hanging' : 'auto',
100
- style: {
101
- fontSize: tickFontSize
102
- },
148
+ style: _extends({
149
+ textAnchor: 'middle',
150
+ dominantBaseline: position === 'bottom' ? 'hanging' : 'auto',
151
+ fontSize: tickFontSize ?? 12
152
+ }, tickLabelStyle),
103
153
  className: classes.tickLabel
104
154
  },
105
155
  className: classes.tickLabel,
106
156
  ownerState: {}
107
157
  });
158
+ const xTicks = useTicks({
159
+ scale: xScale,
160
+ tickNumber,
161
+ valueFormatter,
162
+ tickInterval
163
+ });
164
+ const xTicksWithDimension = addLabelDimension(xTicks, {
165
+ tickLabelStyle: axisTickLabelProps.style,
166
+ tickLabelInterval,
167
+ isMounted
168
+ });
169
+ const labelRefPoint = {
170
+ x: left + width / 2,
171
+ y: positionSign * (tickSize + 22)
172
+ };
108
173
  const axisLabelProps = useSlotProps({
109
174
  elementType: Label,
110
175
  externalSlotProps: slotProps?.axisLabel,
111
176
  additionalProps: {
112
- textAnchor: 'middle',
113
- dominantBaseline: position === 'bottom' ? 'hanging' : 'auto',
114
- style: {
115
- fontSize: labelFontSize,
116
- transformOrigin: `${labelRefPoint.x}px ${labelRefPoint.y}px`
117
- },
118
- className: classes.label
177
+ style: _extends({
178
+ fontSize: labelFontSize ?? 14,
179
+ textAnchor: 'middle',
180
+ dominantBaseline: position === 'bottom' ? 'hanging' : 'auto'
181
+ }, labelStyle)
119
182
  },
120
183
  ownerState: {}
121
184
  });
@@ -126,23 +189,23 @@ function ChartsXAxis(inProps) {
126
189
  x1: xScale.range()[0],
127
190
  x2: xScale.range()[1],
128
191
  className: classes.line
129
- }, slotProps?.axisLine)), xTicks.map(({
192
+ }, slotProps?.axisLine)), xTicksWithDimension.map(({
130
193
  formattedValue,
131
194
  offset,
132
- labelOffset
195
+ labelOffset,
196
+ skipLabel
133
197
  }, index) => {
134
198
  const xTickLabel = labelOffset ?? 0;
135
- const yTickLabel = positionSigne * (tickSize + 3);
199
+ const yTickLabel = positionSign * (tickSize + 3);
136
200
  return /*#__PURE__*/_jsxs("g", {
137
201
  transform: `translate(${offset}, 0)`,
138
202
  className: classes.tickContainer,
139
203
  children: [!disableTicks && /*#__PURE__*/_jsx(Tick, _extends({
140
- y2: positionSigne * tickSize,
204
+ y2: positionSign * tickSize,
141
205
  className: classes.tick
142
- }, slotProps?.axisTick)), formattedValue !== undefined && /*#__PURE__*/_jsx(TickLabel, _extends({
206
+ }, slotProps?.axisTick)), formattedValue !== undefined && !skipLabel && /*#__PURE__*/_jsx(TickLabel, _extends({
143
207
  x: xTickLabel,
144
- y: yTickLabel,
145
- "transform-origin": `${xTickLabel}px ${yTickLabel}px`
208
+ y: yTickLabel
146
209
  }, axisTickLabelProps, {
147
210
  text: formattedValue.toString()
148
211
  }))]
@@ -190,8 +253,13 @@ process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
190
253
  /**
191
254
  * The font size of the axis label.
192
255
  * @default 14
256
+ * @deprecated Consider using `labelStyle.fontSize` instead.
193
257
  */
194
258
  labelFontSize: PropTypes.number,
259
+ /**
260
+ * The style applied to the axis label.
261
+ */
262
+ labelStyle: PropTypes.object,
195
263
  /**
196
264
  * Position of the axis.
197
265
  */
@@ -214,8 +282,28 @@ process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
214
282
  /**
215
283
  * The font size of the axis ticks text.
216
284
  * @default 12
285
+ * @deprecated Consider using `tickLabelStyle.fontSize` instead.
217
286
  */
218
287
  tickFontSize: PropTypes.number,
288
+ /**
289
+ * Defines which ticks are displayed. Its value can be:
290
+ * - 'auto' In such case the ticks are computed based on axis scale and other parameters.
291
+ * - a filtering function of the form `(value, index) => boolean` which is available only if the axis has a data property.
292
+ * - an array containing the values where ticks should be displayed.
293
+ * @default 'auto'
294
+ */
295
+ tickInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.array, PropTypes.func]),
296
+ /**
297
+ * Defines which ticks get its label displayed. Its value can be:
298
+ * - 'auto' In such case, labels are displayed if they do not overlap with the previous one.
299
+ * - a filtering function of the form (value, index) => boolean. Warning: the index is tick index, not data ones.
300
+ * @default 'auto'
301
+ */
302
+ tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
303
+ /**
304
+ * The style applied to ticks text.
305
+ */
306
+ tickLabelStyle: PropTypes.object,
219
307
  /**
220
308
  * Maximal step between two ticks.
221
309
  * When using time data, the value is assumed to be in ms.