@mui/x-charts 6.0.0-alpha.14 → 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 (199) hide show
  1. package/BarChart/BarChart.d.ts +16 -2
  2. package/BarChart/BarChart.js +49 -11
  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 +169 -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 +44 -24
  14. package/ChartsLegend/ChartsLegend.js +191 -145
  15. package/ChartsLegend/utils.d.ts +1 -6
  16. package/ChartsSurface.js +5 -13
  17. package/ChartsTooltip/ChartsAxisTooltipContent.js +2 -2
  18. package/ChartsTooltip/ChartsItemTooltipContent.js +2 -2
  19. package/ChartsTooltip/ChartsTooltip.js +2 -2
  20. package/ChartsTooltip/utils.js +2 -2
  21. package/ChartsXAxis/ChartsXAxis.js +151 -40
  22. package/ChartsYAxis/ChartsYAxis.js +76 -33
  23. package/LineChart/AreaElement.d.ts +10 -0
  24. package/LineChart/AreaElement.js +12 -2
  25. package/LineChart/AreaPlot.d.ts +11 -0
  26. package/LineChart/AreaPlot.js +13 -2
  27. package/LineChart/LineChart.d.ts +13 -0
  28. package/LineChart/LineChart.js +40 -10
  29. package/LineChart/LineElement.d.ts +10 -0
  30. package/LineChart/LineElement.js +12 -2
  31. package/LineChart/LineHighlightElement.d.ts +10 -0
  32. package/LineChart/LineHighlightElement.js +12 -2
  33. package/LineChart/LineHighlightPlot.d.ts +10 -0
  34. package/LineChart/LineHighlightPlot.js +12 -2
  35. package/LineChart/LinePlot.d.ts +10 -0
  36. package/LineChart/LinePlot.js +12 -2
  37. package/LineChart/MarkElement.d.ts +10 -0
  38. package/LineChart/MarkElement.js +12 -2
  39. package/LineChart/MarkPlot.d.ts +10 -0
  40. package/LineChart/MarkPlot.js +12 -2
  41. package/PieChart/PieArc.js +2 -2
  42. package/PieChart/PieArcLabel.js +2 -2
  43. package/PieChart/PieChart.d.ts +13 -0
  44. package/PieChart/PieChart.js +41 -10
  45. package/PieChart/PiePlot.d.ts +10 -0
  46. package/PieChart/PiePlot.js +12 -2
  47. package/ResponsiveChartContainer/index.js +4 -4
  48. package/ScatterChart/Scatter.d.ts +10 -0
  49. package/ScatterChart/Scatter.js +12 -2
  50. package/ScatterChart/ScatterChart.d.ts +13 -0
  51. package/ScatterChart/ScatterChart.js +40 -10
  52. package/ScatterChart/ScatterPlot.d.ts +10 -0
  53. package/ScatterChart/ScatterPlot.js +12 -2
  54. package/SparkLineChart/SparkLineChart.d.ts +9 -0
  55. package/SparkLineChart/SparkLineChart.js +16 -2
  56. package/constants.js +1 -1
  57. package/context/CartesianContextProvider.js +20 -12
  58. package/context/DrawingProvider.d.ts +2 -0
  59. package/context/DrawingProvider.js +4 -2
  60. package/context/HighlightProvider.js +2 -2
  61. package/context/InteractionProvider.js +2 -2
  62. package/context/SeriesContextProvider.js +2 -2
  63. package/esm/BarChart/BarChart.js +47 -9
  64. package/esm/BarChart/BarElement.js +7 -4
  65. package/esm/BarChart/BarPlot.js +152 -67
  66. package/esm/ChartContainer/index.js +3 -0
  67. package/esm/ChartsAxis/ChartsAxis.js +16 -0
  68. package/esm/ChartsLegend/ChartsLegend.js +188 -142
  69. package/esm/ChartsSurface.js +3 -11
  70. package/esm/ChartsXAxis/ChartsXAxis.js +148 -37
  71. package/esm/ChartsYAxis/ChartsYAxis.js +73 -30
  72. package/esm/LineChart/AreaElement.js +10 -0
  73. package/esm/LineChart/AreaPlot.js +11 -0
  74. package/esm/LineChart/LineChart.js +38 -8
  75. package/esm/LineChart/LineElement.js +10 -0
  76. package/esm/LineChart/LineHighlightElement.js +10 -0
  77. package/esm/LineChart/LineHighlightPlot.js +10 -0
  78. package/esm/LineChart/LinePlot.js +10 -0
  79. package/esm/LineChart/MarkElement.js +10 -0
  80. package/esm/LineChart/MarkPlot.js +10 -0
  81. package/esm/PieChart/PieChart.js +39 -8
  82. package/esm/PieChart/PiePlot.js +10 -0
  83. package/esm/ResponsiveChartContainer/index.js +2 -2
  84. package/esm/ScatterChart/Scatter.js +10 -0
  85. package/esm/ScatterChart/ScatterChart.js +38 -8
  86. package/esm/ScatterChart/ScatterPlot.js +10 -0
  87. package/esm/SparkLineChart/SparkLineChart.js +14 -0
  88. package/esm/constants.js +1 -1
  89. package/esm/context/CartesianContextProvider.js +19 -11
  90. package/esm/context/DrawingProvider.js +2 -0
  91. package/esm/hooks/useChartDimensions.js +2 -0
  92. package/esm/hooks/useMounted.js +16 -0
  93. package/esm/hooks/useReducedMotion.js +27 -0
  94. package/esm/hooks/useTicks.js +15 -9
  95. package/esm/internals/components/AxisSharedComponents.js +15 -70
  96. package/esm/internals/components/ChartsText.js +75 -0
  97. package/esm/internals/domUtils.js +113 -0
  98. package/esm/internals/geometry.js +36 -0
  99. package/hooks/useAxisEvents.js +2 -2
  100. package/hooks/useChartDimensions.d.ts +2 -0
  101. package/hooks/useChartDimensions.js +4 -2
  102. package/hooks/useDrawingArea.js +2 -2
  103. package/hooks/useInteractionItemProps.js +2 -2
  104. package/hooks/useMounted.d.ts +1 -0
  105. package/hooks/useMounted.js +25 -0
  106. package/hooks/useReducedMotion.d.ts +8 -0
  107. package/hooks/useReducedMotion.js +33 -0
  108. package/hooks/useScale.d.ts +2 -2
  109. package/hooks/useScale.js +2 -2
  110. package/hooks/useTicks.d.ts +19 -11
  111. package/hooks/useTicks.js +18 -12
  112. package/index.js +1 -1
  113. package/internals/components/AxisSharedComponents.d.ts +0 -4
  114. package/internals/components/AxisSharedComponents.js +16 -71
  115. package/internals/components/ChartsText.d.ts +35 -0
  116. package/internals/components/ChartsText.js +85 -0
  117. package/internals/defaultizeColor.d.ts +1 -1
  118. package/internals/domUtils.d.ts +13 -0
  119. package/internals/domUtils.js +122 -0
  120. package/internals/geometry.d.ts +9 -0
  121. package/internals/geometry.js +42 -0
  122. package/legacy/BarChart/BarChart.js +47 -9
  123. package/legacy/BarChart/BarElement.js +6 -3
  124. package/legacy/BarChart/BarPlot.js +151 -63
  125. package/legacy/ChartContainer/index.js +3 -0
  126. package/legacy/ChartsAxis/ChartsAxis.js +16 -0
  127. package/legacy/ChartsLegend/ChartsLegend.js +203 -140
  128. package/legacy/ChartsSurface.js +2 -11
  129. package/legacy/ChartsXAxis/ChartsXAxis.js +152 -39
  130. package/legacy/ChartsYAxis/ChartsYAxis.js +73 -30
  131. package/legacy/LineChart/AreaElement.js +10 -0
  132. package/legacy/LineChart/AreaPlot.js +11 -0
  133. package/legacy/LineChart/LineChart.js +38 -8
  134. package/legacy/LineChart/LineElement.js +10 -0
  135. package/legacy/LineChart/LineHighlightElement.js +10 -0
  136. package/legacy/LineChart/LineHighlightPlot.js +10 -0
  137. package/legacy/LineChart/LinePlot.js +10 -0
  138. package/legacy/LineChart/MarkElement.js +10 -0
  139. package/legacy/LineChart/MarkPlot.js +10 -0
  140. package/legacy/PieChart/PieChart.js +39 -8
  141. package/legacy/PieChart/PiePlot.js +10 -0
  142. package/legacy/ResponsiveChartContainer/index.js +2 -2
  143. package/legacy/ScatterChart/Scatter.js +10 -0
  144. package/legacy/ScatterChart/ScatterChart.js +38 -8
  145. package/legacy/ScatterChart/ScatterPlot.js +10 -0
  146. package/legacy/SparkLineChart/SparkLineChart.js +14 -0
  147. package/legacy/constants.js +1 -1
  148. package/legacy/context/CartesianContextProvider.js +19 -11
  149. package/legacy/context/DrawingProvider.js +2 -0
  150. package/legacy/hooks/useChartDimensions.js +2 -0
  151. package/legacy/hooks/useMounted.js +21 -0
  152. package/legacy/hooks/useReducedMotion.js +27 -0
  153. package/legacy/hooks/useTicks.js +16 -9
  154. package/legacy/index.js +1 -1
  155. package/legacy/internals/components/AxisSharedComponents.js +9 -63
  156. package/legacy/internals/components/ChartsText.js +77 -0
  157. package/legacy/internals/domUtils.js +121 -0
  158. package/legacy/internals/geometry.js +37 -0
  159. package/models/axis.d.ts +25 -7
  160. package/models/layout.d.ts +7 -6
  161. package/models/seriesType/line.d.ts +2 -2
  162. package/modern/BarChart/BarChart.js +47 -9
  163. package/modern/BarChart/BarElement.js +7 -4
  164. package/modern/BarChart/BarPlot.js +149 -65
  165. package/modern/ChartContainer/index.js +3 -0
  166. package/modern/ChartsAxis/ChartsAxis.js +16 -0
  167. package/modern/ChartsLegend/ChartsLegend.js +188 -142
  168. package/modern/ChartsSurface.js +3 -11
  169. package/modern/ChartsXAxis/ChartsXAxis.js +148 -37
  170. package/modern/ChartsYAxis/ChartsYAxis.js +73 -30
  171. package/modern/LineChart/AreaElement.js +10 -0
  172. package/modern/LineChart/AreaPlot.js +11 -0
  173. package/modern/LineChart/LineChart.js +38 -8
  174. package/modern/LineChart/LineElement.js +10 -0
  175. package/modern/LineChart/LineHighlightElement.js +10 -0
  176. package/modern/LineChart/LineHighlightPlot.js +10 -0
  177. package/modern/LineChart/LinePlot.js +10 -0
  178. package/modern/LineChart/MarkElement.js +10 -0
  179. package/modern/LineChart/MarkPlot.js +10 -0
  180. package/modern/PieChart/PieChart.js +39 -8
  181. package/modern/PieChart/PiePlot.js +10 -0
  182. package/modern/ResponsiveChartContainer/index.js +2 -2
  183. package/modern/ScatterChart/Scatter.js +10 -0
  184. package/modern/ScatterChart/ScatterChart.js +38 -8
  185. package/modern/ScatterChart/ScatterPlot.js +10 -0
  186. package/modern/SparkLineChart/SparkLineChart.js +14 -0
  187. package/modern/constants.js +1 -1
  188. package/modern/context/CartesianContextProvider.js +19 -11
  189. package/modern/context/DrawingProvider.js +2 -0
  190. package/modern/hooks/useChartDimensions.js +2 -0
  191. package/modern/hooks/useMounted.js +16 -0
  192. package/modern/hooks/useReducedMotion.js +27 -0
  193. package/modern/hooks/useTicks.js +15 -9
  194. package/modern/index.js +1 -1
  195. package/modern/internals/components/AxisSharedComponents.js +15 -70
  196. package/modern/internals/components/ChartsText.js +75 -0
  197. package/modern/internals/domUtils.js +113 -0
  198. package/modern/internals/geometry.js +36 -0
  199. package/package.json +5 -3
@@ -1,12 +1,17 @@
1
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
1
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
+ const _excluded = ["rotate", "dominantBaseline"],
4
+ _excluded2 = ["label"];
2
5
  import * as React from 'react';
3
6
  import { useSlotProps } from '@mui/base/utils';
7
+ import { NoSsr } from '@mui/base/NoSsr';
4
8
  import { unstable_composeClasses as composeClasses } from '@mui/utils';
5
9
  import { useThemeProps, useTheme, styled } from '@mui/material/styles';
6
10
  import { DrawingContext } from '../context/DrawingProvider';
7
11
  import { getSeriesToDisplay } from './utils';
8
12
  import { SeriesContext } from '../context/SeriesContextProvider';
9
13
  import { getChartsLegendUtilityClass } from './chartsLegendClasses';
14
+ import { ChartsText, getWordsByLines } from '../internals/components/ChartsText';
10
15
  import { jsx as _jsx } from "react/jsx-runtime";
11
16
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
17
  const useUtilityClasses = ownerState => {
@@ -22,167 +27,210 @@ const useUtilityClasses = ownerState => {
22
27
  };
23
28
  return composeClasses(slots, getChartsLegendUtilityClass, classes);
24
29
  };
25
- function getTranslePosition({
26
- position,
27
- drawingArea
28
- }) {
29
- let xValue;
30
- switch (position.horizontal) {
31
- case 'left':
32
- xValue = `calc(var(--ChartsLegend-rootOffsetX, 0px) + ${drawingArea.left}px - var(--ChartsLegend-rootWidth))`;
33
- break;
34
- case 'middle':
35
- xValue = `calc(var(--ChartsLegend-rootOffsetX, 0px) + ${drawingArea.left + drawingArea.width / 2}px - 0.5 * var(--ChartsLegend-rootWidth))`;
36
- break;
37
- default:
38
- xValue = `calc(var(--ChartsLegend-rootOffsetX, 0px) + ${drawingArea.left + drawingArea.width}px)`;
39
- break;
40
- }
41
- let yValue;
42
- switch (position.vertical) {
43
- case 'top':
44
- yValue = `calc(var(--ChartsLegend-rootOffsetY, 0px) + ${drawingArea.top}px - var(--ChartsLegend-rootHeight))`;
45
- break;
46
- case 'middle':
47
- yValue = `calc(var(--ChartsLegend-rootOffsetY, 0px) + ${drawingArea.top + drawingArea.height / 2}px - 0.5 * var(--ChartsLegend-rootHeight))`;
48
- break;
49
- default:
50
- yValue = `calc(var(--ChartsLegend-rootOffsetY, 0px) + ${drawingArea.top + drawingArea.height}px)`;
51
- break;
52
- }
53
- return {
54
- transform: `translate(${xValue}, ${yValue})`
55
- };
56
- }
57
30
  export const ChartsLegendRoot = styled('g', {
58
31
  name: 'MuiChartsLegend',
59
32
  slot: 'Root',
60
33
  overridesResolver: (props, styles) => styles.root
61
- })(({
62
- ownerState
63
- }) => {
64
- const {
65
- direction,
66
- drawingArea,
67
- offsetX,
68
- offsetY,
69
- seriesNumber,
70
- position
71
- } = ownerState;
72
- return _extends({
73
- '--ChartsLegend-rootOffsetX': typeof offsetX === 'number' ? `${offsetX}px` : undefined,
74
- '--ChartsLegend-rootOffsetY': typeof offsetY === 'number' ? `${offsetY}px` : undefined,
75
- '--ChartsLegend-rootWidth': direction === 'row' ? `calc(var(--ChartsLegend-itemWidth) * ${seriesNumber} + var(--ChartsLegend-rootSpacing) * ${seriesNumber - 1} )` : 'var(--ChartsLegend-itemWidth)',
76
- '--ChartsLegend-rootHeight': direction === 'row' ? 'var(--ChartsLegend-itemMarkSize)' : `calc(var(--ChartsLegend-itemMarkSize) * ${seriesNumber} + var(--ChartsLegend-rootSpacing) * ${seriesNumber - 1} )`
77
- }, getTranslePosition({
78
- position,
79
- drawingArea,
80
- offsetX,
81
- offsetY
82
- }));
83
- });
84
- export const ChartsSeriesLegendGroup = styled('g', {
85
- name: 'MuiChartsLegend',
86
- slot: 'ChartsSeriesLegendGroup',
87
- overridesResolver: (props, styles) => styles.series
88
- })(({
89
- ownerState
90
- }) => {
91
- const {
92
- direction,
93
- seriesIndex
94
- } = ownerState;
95
- if (direction === 'row') {
96
- return {
97
- transform: `translate(calc(${seriesIndex} * (var(--ChartsLegend-itemWidth) + var(--ChartsLegend-rootSpacing))), 0)`
98
- };
99
- }
100
- return {
101
- transform: `translate(0, calc(${seriesIndex} * (var(--ChartsLegend-itemMarkSize) + var(--ChartsLegend-rootSpacing))))`
102
- };
103
- });
104
- export const ChartsLegendMark = styled('rect', {
105
- name: 'MuiChartsLegend',
106
- slot: 'Mark',
107
- overridesResolver: (props, styles) => styles.mark
108
- })(({
109
- ownerState
110
- }) => ({
111
- x: 0,
112
- y: 0,
113
- width: 'var(--ChartsLegend-itemMarkSize)',
114
- height: 'var(--ChartsLegend-itemMarkSize)',
115
- fill: ownerState.color
116
- }));
117
- export const ChartsLegendLabel = styled('text', {
118
- name: 'MuiChartsLegend',
119
- slot: 'Label',
120
- overridesResolver: (props, styles) => styles.label
121
- })(({
122
- theme
123
- }) => _extends({}, theme.typography.body1, {
124
- color: 'inherit',
125
- transform: `translate(
126
- calc(var(--ChartsLegend-itemMarkSize) + var(--ChartsLegend-labelSpacing)),
127
- calc(0.5 * var(--ChartsLegend-itemMarkSize))
128
- )`,
129
- fill: (theme.vars || theme).palette.text.primary,
130
- dominantBaseline: 'central'
131
- }));
34
+ })({});
132
35
  const defaultProps = {
133
36
  position: {
134
37
  horizontal: 'middle',
135
38
  vertical: 'top'
136
39
  },
137
- direction: 'row',
138
- markSize: 20,
139
- itemWidth: 100,
140
- spacing: 2
40
+ direction: 'row'
41
+ };
42
+ /**
43
+ * Transforms number or partial padding object to a defaultized padding object.
44
+ */
45
+ const getStandardizedPadding = padding => {
46
+ if (typeof padding === 'number') {
47
+ return {
48
+ left: padding,
49
+ right: padding,
50
+ top: padding,
51
+ bottom: padding
52
+ };
53
+ }
54
+ return _extends({
55
+ left: 0,
56
+ right: 0,
57
+ top: 0,
58
+ bottom: 0
59
+ }, padding);
141
60
  };
142
61
  function DefaultChartsLegend(props) {
143
62
  const {
144
63
  hidden,
145
64
  position,
146
65
  direction,
147
- offset,
148
- series,
149
66
  seriesToDisplay,
150
67
  drawingArea,
151
- classes
68
+ classes,
69
+ itemMarkWidth = 20,
70
+ itemMarkHeight = 20,
71
+ markGap = 5,
72
+ itemGap = 10,
73
+ padding: paddingProps = 10,
74
+ labelStyle: inLabelStyle
152
75
  } = props;
76
+ const theme = useTheme();
77
+ const labelStyle = React.useMemo(() => _extends({}, theme.typography.subtitle1, {
78
+ color: 'inherit',
79
+ dominantBaseline: 'central',
80
+ textAnchor: 'start',
81
+ fill: (theme.vars || theme).palette.text.primary,
82
+ lineHeight: 1
83
+ }, inLabelStyle),
84
+ // To say to TS that the dominantBaseline and textAnchor are correct
85
+ [inLabelStyle, theme]);
86
+ const padding = React.useMemo(() => getStandardizedPadding(paddingProps), [paddingProps]);
87
+ const getItemSpace = React.useCallback((label, inStyle = {}) => {
88
+ const style = _objectWithoutPropertiesLoose(inStyle, _excluded);
89
+ const linesSize = getWordsByLines({
90
+ style,
91
+ needsComputation: true,
92
+ text: label
93
+ });
94
+ const innerSize = {
95
+ innerWidth: itemMarkWidth + markGap + Math.max(...linesSize.map(size => size.width)),
96
+ innerHeight: Math.max(itemMarkHeight, linesSize.length * linesSize[0].height)
97
+ };
98
+ return _extends({}, innerSize, {
99
+ outerWidth: innerSize.innerWidth + itemGap,
100
+ outerHeight: innerSize.innerHeight + itemGap
101
+ });
102
+ }, [itemGap, itemMarkHeight, itemMarkWidth, markGap]);
103
+ const totalWidth = drawingArea.left + drawingArea.width + drawingArea.right;
104
+ const totalHeight = drawingArea.top + drawingArea.height + drawingArea.bottom;
105
+ const availableWidth = totalWidth - padding.left - padding.right;
106
+ const availableHeight = totalHeight - padding.top - padding.bottom;
107
+ const seriesWithPosition = React.useMemo(() => {
108
+ // Start at 0, 0. Will be modified later by padding and position.
109
+ let x = 0;
110
+ let y = 0;
111
+
112
+ // total values used to align legend later.
113
+ let totalWidthUsed = 0;
114
+ let totalHeightUsed = 0;
115
+ let rowIndex = 0;
116
+ const rowMaxHeight = [0];
117
+ const seriesWithRawPosition = seriesToDisplay.map(_ref => {
118
+ let {
119
+ label
120
+ } = _ref,
121
+ other = _objectWithoutPropertiesLoose(_ref, _excluded2);
122
+ const itemSpace = getItemSpace(label, labelStyle);
123
+ const rep = _extends({}, other, {
124
+ label,
125
+ positionX: x,
126
+ positionY: y,
127
+ innerHeight: itemSpace.innerHeight,
128
+ innerWidth: itemSpace.innerWidth,
129
+ outerHeight: itemSpace.outerHeight,
130
+ outerWidth: itemSpace.outerWidth,
131
+ rowIndex
132
+ });
133
+ if (direction === 'row') {
134
+ if (x + itemSpace.innerWidth > availableWidth) {
135
+ // This legend item would create overflow along the x-axis, so we start a new row.
136
+ x = 0;
137
+ y += rowMaxHeight[rowIndex];
138
+ rowIndex += 1;
139
+ if (rowMaxHeight.length <= rowIndex) {
140
+ rowMaxHeight.push(0);
141
+ }
142
+ rep.positionX = x;
143
+ rep.positionY = y;
144
+ rep.rowIndex = rowIndex;
145
+ }
146
+ totalWidthUsed = Math.max(totalWidthUsed, x + itemSpace.outerWidth);
147
+ totalHeightUsed = Math.max(totalHeightUsed, y + itemSpace.outerHeight);
148
+ rowMaxHeight[rowIndex] = Math.max(rowMaxHeight[rowIndex], itemSpace.outerHeight);
149
+ x += itemSpace.outerWidth;
150
+ }
151
+ if (direction === 'column') {
152
+ if (y + itemSpace.innerHeight > availableHeight) {
153
+ // This legend item would create overflow along the y-axis, so we start a new column.
154
+ x = totalWidthUsed + itemGap;
155
+ y = 0;
156
+ rowIndex = 0;
157
+ rep.positionX = x;
158
+ rep.positionY = y;
159
+ rep.rowIndex = rowIndex;
160
+ }
161
+ if (rowMaxHeight.length <= rowIndex) {
162
+ rowMaxHeight.push(0);
163
+ }
164
+ totalWidthUsed = Math.max(totalWidthUsed, x + itemSpace.outerWidth);
165
+ totalHeightUsed = Math.max(totalHeightUsed, y + itemSpace.outerHeight);
166
+ rowIndex += 1;
167
+ y += itemSpace.outerHeight;
168
+ }
169
+ return rep;
170
+ });
171
+
172
+ // Move the legend according to padding and position
173
+ let gapX = 0;
174
+ let gapY = 0;
175
+ switch (position.horizontal) {
176
+ case 'left':
177
+ gapX = padding.left;
178
+ break;
179
+ case 'right':
180
+ gapX = totalWidth - padding.right - totalWidthUsed;
181
+ break;
182
+ default:
183
+ gapX = (totalWidth - totalWidthUsed) / 2;
184
+ break;
185
+ }
186
+ switch (position.vertical) {
187
+ case 'top':
188
+ gapY = padding.top;
189
+ break;
190
+ case 'bottom':
191
+ gapY = totalHeight - padding.bottom - totalHeightUsed;
192
+ break;
193
+ default:
194
+ gapY = (totalHeight - totalHeightUsed) / 2;
195
+ break;
196
+ }
197
+ return seriesWithRawPosition.map(item => _extends({}, item, {
198
+ // Add the gap due to the position
199
+ positionX: item.positionX + gapX,
200
+ // Add the gap due to the position
201
+ positionY: item.positionY + gapY + (direction === 'row' ? rowMaxHeight[item.rowIndex] / 2 // Get the center of the entire row
202
+ : item.outerHeight / 2) // Get the center of the item
203
+ }));
204
+ }, [seriesToDisplay, position.horizontal, position.vertical, getItemSpace, labelStyle, direction, availableWidth, availableHeight, itemGap, padding.left, padding.right, padding.top, padding.bottom, totalWidth, totalHeight]);
153
205
  if (hidden) {
154
206
  return null;
155
207
  }
156
- return /*#__PURE__*/_jsx(ChartsLegendRoot, {
157
- ownerState: {
158
- direction,
159
- offsetX: offset?.x,
160
- offsetY: offset?.y,
161
- seriesNumber: seriesToDisplay.length,
162
- position,
163
- drawingArea
164
- },
165
- className: classes.root,
166
- children: seriesToDisplay.map(({
167
- id,
168
- label,
169
- color
170
- }, seriesIndex) => /*#__PURE__*/_jsxs(ChartsSeriesLegendGroup, {
171
- ownerState: _extends({
172
- direction,
173
- seriesIndex
174
- }, series),
175
- className: classes.series,
176
- children: [/*#__PURE__*/_jsx(ChartsLegendMark, {
177
- ownerState: {
178
- color
179
- },
180
- className: classes.mark
181
- }), /*#__PURE__*/_jsx(ChartsLegendLabel, {
182
- className: classes.label,
183
- children: label
184
- })]
185
- }, id))
208
+ return /*#__PURE__*/_jsx(NoSsr, {
209
+ children: /*#__PURE__*/_jsx(ChartsLegendRoot, {
210
+ className: classes.root,
211
+ children: seriesWithPosition.map(({
212
+ id,
213
+ label,
214
+ color,
215
+ positionX,
216
+ positionY
217
+ }) => /*#__PURE__*/_jsxs("g", {
218
+ className: classes.series,
219
+ transform: `translate(${positionX} ${positionY})`,
220
+ children: [/*#__PURE__*/_jsx("rect", {
221
+ className: classes.mark,
222
+ y: -itemMarkHeight / 2,
223
+ width: itemMarkWidth,
224
+ height: itemMarkHeight,
225
+ fill: color
226
+ }), /*#__PURE__*/_jsx(ChartsText, {
227
+ style: labelStyle,
228
+ text: label,
229
+ x: itemMarkWidth + markGap,
230
+ y: 0
231
+ })]
232
+ }, id))
233
+ })
186
234
  });
187
235
  }
188
236
  export function ChartsLegend(inProps) {
@@ -193,7 +241,6 @@ export function ChartsLegend(inProps) {
193
241
  const {
194
242
  position,
195
243
  direction,
196
- offset,
197
244
  hidden,
198
245
  slots,
199
246
  slotProps
@@ -212,7 +259,6 @@ export function ChartsLegend(inProps) {
212
259
  additionalProps: {
213
260
  position,
214
261
  direction,
215
- offset,
216
262
  classes,
217
263
  drawingArea,
218
264
  series,
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["children", "width", "height", "viewBox", "disableAxisListener", "className", "sx"];
3
+ const _excluded = ["children", "width", "height", "viewBox", "disableAxisListener", "className"];
4
4
  import { styled } from '@mui/material/styles';
5
5
  import * as React from 'react';
6
6
  import { useAxisEvents } from './hooks/useAxisEvents';
@@ -16,8 +16,7 @@ export const ChartsSurface = /*#__PURE__*/React.forwardRef(function ChartsSurfac
16
16
  width,
17
17
  height,
18
18
  viewBox,
19
- disableAxisListener = false,
20
- sx
19
+ disableAxisListener = false
21
20
  } = props,
22
21
  other = _objectWithoutPropertiesLoose(props, _excluded);
23
22
  const svgView = _extends({
@@ -31,14 +30,7 @@ export const ChartsSurface = /*#__PURE__*/React.forwardRef(function ChartsSurfac
31
30
  width: width,
32
31
  height: height,
33
32
  viewBox: `${svgView.x} ${svgView.y} ${svgView.width} ${svgView.height}`,
34
- ref: ref,
35
- sx: [{
36
- '--ChartsLegend-itemWidth': '100px',
37
- '--ChartsLegend-itemMarkSize': '20px',
38
- '--ChartsLegend-rootSpacing': '5px',
39
- '--ChartsLegend-labelSpacing': '5px',
40
- '--ChartsLegend-rootOffsetY': '-20px'
41
- }, ...(Array.isArray(sx) ? sx : [sx])]
33
+ ref: ref
42
34
  }, other, {
43
35
  children: [/*#__PURE__*/_jsx("title", {
44
36
  children: props.title
@@ -1,15 +1,19 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
- const _excluded = ["scale", "ticksNumber"];
3
+ const _excluded = ["scale", "tickNumber"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
+ import { useSlotProps } from '@mui/base/utils';
6
7
  import { unstable_composeClasses as composeClasses } from '@mui/utils';
7
8
  import { useThemeProps, useTheme } from '@mui/material/styles';
8
9
  import { CartesianContext } from '../context/CartesianContextProvider';
9
10
  import { DrawingContext } from '../context/DrawingProvider';
10
11
  import useTicks from '../hooks/useTicks';
11
12
  import { getAxisUtilityClass } from '../ChartsAxis/axisClasses';
12
- import { ChartsLine, ChartsTick, ChartsTickLabel, ChartsLabel, AxisRoot } from '../internals/components/AxisSharedComponents';
13
+ import { AxisRoot } from '../internals/components/AxisSharedComponents';
14
+ import { ChartsText, getWordsByLines } from '../internals/components/ChartsText';
15
+ import { getMinXTranslation } from '../internals/geometry';
16
+ import { useMounted } from '../hooks/useMounted';
13
17
  import { jsx as _jsx } from "react/jsx-runtime";
14
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
15
19
  const useUtilityClasses = ownerState => {
@@ -27,12 +31,64 @@ const useUtilityClasses = ownerState => {
27
31
  };
28
32
  return composeClasses(slots, getAxisUtilityClass, classes);
29
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
+ }
30
88
  const defaultProps = {
31
89
  position: 'bottom',
32
90
  disableLine: false,
33
91
  disableTicks: false,
34
- tickFontSize: 12,
35
- labelFontSize: 14,
36
92
  tickSize: 6
37
93
  };
38
94
  function ChartsXAxis(inProps) {
@@ -46,23 +102,28 @@ function ChartsXAxis(inProps) {
46
102
  xAxis: {
47
103
  [_props$axisId]: {
48
104
  scale: xScale,
49
- ticksNumber
105
+ tickNumber
50
106
  }
51
107
  }
52
108
  } = _React$useContext,
53
109
  settings = _objectWithoutPropertiesLoose(_React$useContext.xAxis[_props$axisId], _excluded);
110
+ const isMounted = useMounted();
54
111
  const defaultizedProps = _extends({}, defaultProps, settings, props);
55
112
  const {
56
113
  position,
57
114
  disableLine,
58
115
  disableTicks,
59
- tickFontSize,
116
+ tickLabelStyle,
60
117
  label,
118
+ labelStyle,
119
+ tickFontSize,
61
120
  labelFontSize,
62
121
  tickSize: tickSizeProp,
63
122
  valueFormatter,
64
123
  slots,
65
- slotProps
124
+ slotProps,
125
+ tickInterval,
126
+ tickLabelInterval
66
127
  } = defaultizedProps;
67
128
  const theme = useTheme();
68
129
  const classes = useUtilityClasses(_extends({}, defaultizedProps, {
@@ -75,20 +136,52 @@ function ChartsXAxis(inProps) {
75
136
  height
76
137
  } = React.useContext(DrawingContext);
77
138
  const tickSize = disableTicks ? 4 : tickSizeProp;
139
+ const positionSign = position === 'bottom' ? 1 : -1;
140
+ const Line = slots?.axisLine ?? 'line';
141
+ const Tick = slots?.axisTick ?? 'line';
142
+ const TickLabel = slots?.axisTickLabel ?? ChartsText;
143
+ const Label = slots?.axisLabel ?? ChartsText;
144
+ const axisTickLabelProps = useSlotProps({
145
+ elementType: TickLabel,
146
+ externalSlotProps: slotProps?.axisTickLabel,
147
+ additionalProps: {
148
+ style: _extends({
149
+ textAnchor: 'middle',
150
+ dominantBaseline: position === 'bottom' ? 'hanging' : 'auto',
151
+ fontSize: tickFontSize ?? 12
152
+ }, tickLabelStyle),
153
+ className: classes.tickLabel
154
+ },
155
+ className: classes.tickLabel,
156
+ ownerState: {}
157
+ });
78
158
  const xTicks = useTicks({
79
159
  scale: xScale,
80
- ticksNumber,
81
- valueFormatter
160
+ tickNumber,
161
+ valueFormatter,
162
+ tickInterval
163
+ });
164
+ const xTicksWithDimension = addLabelDimension(xTicks, {
165
+ tickLabelStyle: axisTickLabelProps.style,
166
+ tickLabelInterval,
167
+ isMounted
82
168
  });
83
- const positionSigne = position === 'bottom' ? 1 : -1;
84
169
  const labelRefPoint = {
85
170
  x: left + width / 2,
86
- y: positionSigne * (tickFontSize + tickSize + 10)
171
+ y: positionSign * (tickSize + 22)
87
172
  };
88
- const Line = slots?.axisLine ?? ChartsLine;
89
- const Tick = slots?.axisTick ?? ChartsTick;
90
- const TickLabel = slots?.axisTickLabel ?? ChartsTickLabel;
91
- const Label = slots?.axisLabel ?? ChartsLabel;
173
+ const axisLabelProps = useSlotProps({
174
+ elementType: Label,
175
+ externalSlotProps: slotProps?.axisLabel,
176
+ additionalProps: {
177
+ style: _extends({
178
+ fontSize: labelFontSize ?? 14,
179
+ textAnchor: 'middle',
180
+ dominantBaseline: position === 'bottom' ? 'hanging' : 'auto'
181
+ }, labelStyle)
182
+ },
183
+ ownerState: {}
184
+ });
92
185
  return /*#__PURE__*/_jsxs(AxisRoot, {
93
186
  transform: `translate(0, ${position === 'bottom' ? top + height : top})`,
94
187
  className: classes.root,
@@ -96,40 +189,33 @@ function ChartsXAxis(inProps) {
96
189
  x1: xScale.range()[0],
97
190
  x2: xScale.range()[1],
98
191
  className: classes.line
99
- }, slotProps?.axisLine)), xTicks.map(({
192
+ }, slotProps?.axisLine)), xTicksWithDimension.map(({
100
193
  formattedValue,
101
194
  offset,
102
- labelOffset
195
+ labelOffset,
196
+ skipLabel
103
197
  }, index) => {
104
198
  const xTickLabel = labelOffset ?? 0;
105
- const yTickLabel = positionSigne * (tickSize + 3);
199
+ const yTickLabel = positionSign * (tickSize + 3);
106
200
  return /*#__PURE__*/_jsxs("g", {
107
201
  transform: `translate(${offset}, 0)`,
108
202
  className: classes.tickContainer,
109
203
  children: [!disableTicks && /*#__PURE__*/_jsx(Tick, _extends({
110
- y2: positionSigne * tickSize,
204
+ y2: positionSign * tickSize,
111
205
  className: classes.tick
112
- }, slotProps?.axisTick)), formattedValue !== undefined && /*#__PURE__*/_jsx(TickLabel, _extends({
206
+ }, slotProps?.axisTick)), formattedValue !== undefined && !skipLabel && /*#__PURE__*/_jsx(TickLabel, _extends({
113
207
  x: xTickLabel,
114
- y: yTickLabel,
115
- "transform-origin": `${xTickLabel}px ${yTickLabel}px`,
116
- sx: {
117
- fontSize: tickFontSize
118
- },
119
- className: classes.tickLabel
120
- }, slotProps?.axisTickLabel, {
121
- children: formattedValue
208
+ y: yTickLabel
209
+ }, axisTickLabelProps, {
210
+ text: formattedValue.toString()
122
211
  }))]
123
212
  }, index);
124
- }), label && /*#__PURE__*/_jsx(Label, _extends({}, labelRefPoint, {
125
- sx: {
126
- fontSize: labelFontSize,
127
- transformOrigin: `${labelRefPoint.x}px ${labelRefPoint.y}px`
128
- },
129
- className: classes.label
130
- }, slotProps?.axisLabel, {
131
- children: label
132
- }))]
213
+ }), label && /*#__PURE__*/_jsx("g", {
214
+ className: classes.label,
215
+ children: /*#__PURE__*/_jsx(Label, _extends({}, labelRefPoint, axisLabelProps, {
216
+ text: label
217
+ }))
218
+ })]
133
219
  });
134
220
  }
135
221
  process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
@@ -167,8 +253,13 @@ process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
167
253
  /**
168
254
  * The font size of the axis label.
169
255
  * @default 14
256
+ * @deprecated Consider using `labelStyle.fontSize` instead.
170
257
  */
171
258
  labelFontSize: PropTypes.number,
259
+ /**
260
+ * The style applied to the axis label.
261
+ */
262
+ labelStyle: PropTypes.object,
172
263
  /**
173
264
  * Position of the axis.
174
265
  */
@@ -191,8 +282,28 @@ process.env.NODE_ENV !== "production" ? ChartsXAxis.propTypes = {
191
282
  /**
192
283
  * The font size of the axis ticks text.
193
284
  * @default 12
285
+ * @deprecated Consider using `tickLabelStyle.fontSize` instead.
194
286
  */
195
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,
196
307
  /**
197
308
  * Maximal step between two ticks.
198
309
  * When using time data, the value is assumed to be in ms.