@mui/material 9.0.0 → 9.1.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 (278) hide show
  1. package/Accordion/Accordion.d.mts +2 -2
  2. package/Accordion/Accordion.d.ts +2 -2
  3. package/Accordion/Accordion.js +3 -2
  4. package/Accordion/Accordion.mjs +3 -2
  5. package/AccordionSummary/AccordionSummary.js +27 -29
  6. package/AccordionSummary/AccordionSummary.mjs +27 -29
  7. package/Autocomplete/Autocomplete.js +73 -17
  8. package/Autocomplete/Autocomplete.mjs +73 -17
  9. package/Avatar/Avatar.js +4 -0
  10. package/Avatar/Avatar.mjs +4 -0
  11. package/Backdrop/Backdrop.d.mts +2 -2
  12. package/Backdrop/Backdrop.d.ts +2 -2
  13. package/Badge/Badge.js +31 -24
  14. package/Badge/Badge.mjs +31 -24
  15. package/BottomNavigationAction/BottomNavigationAction.js +6 -2
  16. package/BottomNavigationAction/BottomNavigationAction.mjs +6 -2
  17. package/Button/Button.js +19 -6
  18. package/Button/Button.mjs +19 -6
  19. package/ButtonBase/ButtonBase.d.mts +7 -0
  20. package/ButtonBase/ButtonBase.d.ts +7 -0
  21. package/ButtonBase/ButtonBase.js +5 -2
  22. package/ButtonBase/ButtonBase.mjs +5 -2
  23. package/ButtonBase/Ripple.js +21 -11
  24. package/ButtonBase/Ripple.mjs +21 -11
  25. package/ButtonBase/TouchRipple.js +252 -116
  26. package/ButtonBase/TouchRipple.mjs +253 -117
  27. package/CHANGELOG.md +216 -1245
  28. package/CardActionArea/CardActionArea.js +2 -1
  29. package/CardActionArea/CardActionArea.mjs +2 -1
  30. package/Checkbox/Checkbox.js +2 -1
  31. package/Checkbox/Checkbox.mjs +2 -1
  32. package/Chip/Chip.js +2 -1
  33. package/Chip/Chip.mjs +2 -1
  34. package/CircularProgress/CircularProgress.d.mts +12 -2
  35. package/CircularProgress/CircularProgress.d.ts +12 -2
  36. package/CircularProgress/CircularProgress.js +115 -58
  37. package/CircularProgress/CircularProgress.mjs +114 -58
  38. package/ClickAwayListener/ClickAwayListener.js +3 -6
  39. package/ClickAwayListener/ClickAwayListener.mjs +3 -6
  40. package/Collapse/Collapse.d.mts +15 -3
  41. package/Collapse/Collapse.d.ts +15 -3
  42. package/Collapse/Collapse.js +44 -31
  43. package/Collapse/Collapse.mjs +43 -30
  44. package/Dialog/Dialog.d.mts +2 -2
  45. package/Dialog/Dialog.d.ts +2 -2
  46. package/Dialog/Dialog.js +13 -6
  47. package/Dialog/Dialog.mjs +13 -6
  48. package/Drawer/Drawer.d.mts +2 -2
  49. package/Drawer/Drawer.d.ts +2 -2
  50. package/Drawer/Drawer.js +18 -4
  51. package/Drawer/Drawer.mjs +18 -4
  52. package/Fab/Fab.js +9 -2
  53. package/Fab/Fab.mjs +9 -2
  54. package/Fade/Fade.d.mts +15 -2
  55. package/Fade/Fade.d.ts +15 -2
  56. package/Fade/Fade.js +46 -19
  57. package/Fade/Fade.mjs +45 -18
  58. package/FilledInput/FilledInput.d.mts +4 -0
  59. package/FilledInput/FilledInput.d.ts +4 -0
  60. package/FilledInput/FilledInput.js +22 -23
  61. package/FilledInput/FilledInput.mjs +22 -23
  62. package/FormControl/useFormControl.d.mts +12 -2
  63. package/FormControl/useFormControl.d.ts +12 -2
  64. package/FormControl/useFormControl.js +13 -0
  65. package/FormControl/useFormControl.mjs +12 -0
  66. package/FormControlLabel/FormControlLabel.js +5 -8
  67. package/FormControlLabel/FormControlLabel.mjs +5 -8
  68. package/FormGroup/FormGroup.js +2 -5
  69. package/FormGroup/FormGroup.mjs +2 -5
  70. package/FormHelperText/FormHelperText.js +2 -5
  71. package/FormHelperText/FormHelperText.mjs +2 -5
  72. package/FormLabel/FormLabel.js +2 -5
  73. package/FormLabel/FormLabel.mjs +2 -5
  74. package/Grow/Grow.d.mts +15 -2
  75. package/Grow/Grow.d.ts +15 -2
  76. package/Grow/Grow.js +45 -28
  77. package/Grow/Grow.mjs +44 -27
  78. package/IconButton/IconButton.js +3 -9
  79. package/IconButton/IconButton.mjs +3 -9
  80. package/Input/Input.d.mts +4 -0
  81. package/Input/Input.d.ts +4 -0
  82. package/Input/Input.js +9 -2
  83. package/Input/Input.mjs +9 -2
  84. package/InputBase/InputBase.d.mts +2 -1
  85. package/InputBase/InputBase.d.ts +2 -1
  86. package/InputBase/InputBase.js +52 -16
  87. package/InputBase/InputBase.mjs +52 -16
  88. package/InputLabel/InputLabel.js +7 -9
  89. package/InputLabel/InputLabel.mjs +7 -9
  90. package/LICENSE +1 -1
  91. package/LinearProgress/LinearProgress.d.mts +12 -2
  92. package/LinearProgress/LinearProgress.d.ts +12 -2
  93. package/LinearProgress/LinearProgress.js +225 -126
  94. package/LinearProgress/LinearProgress.mjs +224 -126
  95. package/List/List.js +2 -1
  96. package/List/List.mjs +2 -1
  97. package/ListItem/ListItem.js +2 -1
  98. package/ListItem/ListItem.mjs +2 -1
  99. package/ListItemButton/ListItemButton.js +9 -2
  100. package/ListItemButton/ListItemButton.mjs +9 -2
  101. package/Menu/Menu.d.mts +1 -1
  102. package/Menu/Menu.d.ts +1 -1
  103. package/MenuItem/MenuItem.js +7 -1
  104. package/MenuItem/MenuItem.mjs +7 -1
  105. package/MenuList/MenuList.js +2 -1
  106. package/MenuList/MenuList.mjs +2 -1
  107. package/MobileStepper/MobileStepper.js +2 -1
  108. package/MobileStepper/MobileStepper.mjs +2 -1
  109. package/NativeSelect/NativeSelect.js +2 -5
  110. package/NativeSelect/NativeSelect.mjs +2 -5
  111. package/OutlinedInput/NotchedOutline.js +4 -3
  112. package/OutlinedInput/NotchedOutline.mjs +4 -3
  113. package/OutlinedInput/OutlinedInput.js +13 -23
  114. package/OutlinedInput/OutlinedInput.mjs +13 -23
  115. package/PaginationItem/PaginationItem.js +2 -1
  116. package/PaginationItem/PaginationItem.mjs +2 -1
  117. package/Paper/Paper.js +2 -1
  118. package/Paper/Paper.mjs +2 -1
  119. package/PigmentContainer/PigmentContainer.js +0 -1
  120. package/PigmentContainer/PigmentContainer.mjs +0 -1
  121. package/Popover/Popover.d.mts +1 -1
  122. package/Popover/Popover.d.ts +1 -1
  123. package/Popper/BasePopper.js +23 -1
  124. package/Popper/BasePopper.mjs +23 -1
  125. package/README.md +3 -2
  126. package/Radio/RadioButtonIcon.js +3 -2
  127. package/Radio/RadioButtonIcon.mjs +3 -2
  128. package/Rating/Rating.js +2 -1
  129. package/Rating/Rating.mjs +2 -1
  130. package/Select/Select.js +2 -5
  131. package/Select/Select.mjs +2 -5
  132. package/Select/SelectInput.js +276 -24
  133. package/Select/SelectInput.mjs +276 -24
  134. package/Select/utils/closedTypeahead.js +73 -0
  135. package/Select/utils/closedTypeahead.mjs +63 -0
  136. package/Skeleton/Skeleton.js +22 -2
  137. package/Skeleton/Skeleton.mjs +22 -2
  138. package/Slide/Slide.d.mts +15 -2
  139. package/Slide/Slide.d.ts +15 -2
  140. package/Slide/Slide.js +97 -47
  141. package/Slide/Slide.mjs +97 -47
  142. package/Slider/Slider.js +14 -4
  143. package/Slider/Slider.mjs +14 -4
  144. package/Slider/useSlider.js +4 -3
  145. package/Slider/useSlider.mjs +4 -3
  146. package/Snackbar/Snackbar.d.mts +2 -2
  147. package/Snackbar/Snackbar.d.ts +2 -2
  148. package/SpeedDial/SpeedDial.d.mts +1 -1
  149. package/SpeedDial/SpeedDial.d.ts +1 -1
  150. package/SpeedDial/SpeedDial.js +6 -2
  151. package/SpeedDial/SpeedDial.mjs +6 -2
  152. package/SpeedDialAction/SpeedDialAction.js +11 -2
  153. package/SpeedDialAction/SpeedDialAction.mjs +12 -3
  154. package/SpeedDialIcon/SpeedDialIcon.js +40 -37
  155. package/SpeedDialIcon/SpeedDialIcon.mjs +40 -37
  156. package/Step/Step.js +47 -15
  157. package/Step/Step.mjs +47 -15
  158. package/StepButton/StepButton.js +9 -3
  159. package/StepButton/StepButton.mjs +9 -3
  160. package/StepConnector/StepConnector.js +10 -0
  161. package/StepConnector/StepConnector.mjs +10 -0
  162. package/StepContent/StepContent.d.mts +2 -2
  163. package/StepContent/StepContent.d.ts +2 -2
  164. package/StepContent/StepContent.js +26 -2
  165. package/StepContent/StepContent.mjs +26 -2
  166. package/StepIcon/StepIcon.js +2 -1
  167. package/StepIcon/StepIcon.mjs +2 -1
  168. package/StepLabel/StepLabel.js +52 -7
  169. package/StepLabel/StepLabel.mjs +52 -7
  170. package/Stepper/Stepper.d.mts +2 -0
  171. package/Stepper/Stepper.d.ts +2 -0
  172. package/Stepper/Stepper.js +18 -0
  173. package/Stepper/Stepper.mjs +18 -0
  174. package/SvgIcon/SvgIcon.js +2 -1
  175. package/SvgIcon/SvgIcon.mjs +2 -1
  176. package/SwipeableDrawer/SwipeableDrawer.js +21 -6
  177. package/SwipeableDrawer/SwipeableDrawer.mjs +21 -6
  178. package/Switch/Switch.js +10 -8
  179. package/Switch/Switch.mjs +10 -8
  180. package/TableSortLabel/TableSortLabel.js +2 -1
  181. package/TableSortLabel/TableSortLabel.mjs +2 -1
  182. package/Tabs/ScrollbarSize.js +2 -1
  183. package/Tabs/ScrollbarSize.mjs +2 -1
  184. package/Tabs/Tabs.js +16 -4
  185. package/Tabs/Tabs.mjs +16 -4
  186. package/Tooltip/Tooltip.d.mts +2 -2
  187. package/Tooltip/Tooltip.d.ts +2 -2
  188. package/Tooltip/Tooltip.js +29 -108
  189. package/Tooltip/Tooltip.mjs +29 -108
  190. package/Unstable_TrapFocus/FocusTrap.js +60 -22
  191. package/Unstable_TrapFocus/FocusTrap.mjs +60 -22
  192. package/Zoom/Zoom.d.mts +15 -2
  193. package/Zoom/Zoom.d.ts +15 -2
  194. package/Zoom/Zoom.js +43 -16
  195. package/Zoom/Zoom.mjs +42 -15
  196. package/index.js +1 -1
  197. package/index.mjs +1 -1
  198. package/internal/Transition.d.mts +34 -0
  199. package/internal/Transition.d.ts +34 -0
  200. package/internal/Transition.js +444 -0
  201. package/internal/Transition.mjs +436 -0
  202. package/internal/react-transition-group.d.mts +8 -0
  203. package/internal/react-transition-group.d.ts +8 -0
  204. package/package.json +50 -50
  205. package/styles/createMotion.d.mts +8 -0
  206. package/styles/createMotion.d.ts +8 -0
  207. package/styles/createMotion.js +13 -0
  208. package/styles/createMotion.mjs +7 -0
  209. package/styles/createThemeFoundation.d.mts +2 -0
  210. package/styles/createThemeFoundation.d.ts +2 -0
  211. package/styles/createThemeNoVars.d.mts +3 -0
  212. package/styles/createThemeNoVars.d.ts +3 -0
  213. package/styles/createThemeNoVars.js +5 -0
  214. package/styles/createThemeNoVars.mjs +5 -0
  215. package/styles/createTransitions.d.mts +6 -2
  216. package/styles/createTransitions.d.ts +6 -2
  217. package/styles/createTransitions.js +12 -4
  218. package/styles/createTransitions.mjs +12 -4
  219. package/styles/enhanceHighContrast.d.mts +70 -0
  220. package/styles/enhanceHighContrast.d.ts +70 -0
  221. package/styles/enhanceHighContrast.js +502 -0
  222. package/styles/enhanceHighContrast.mjs +495 -0
  223. package/styles/index.d.mts +2 -0
  224. package/styles/index.d.ts +2 -0
  225. package/styles/index.js +8 -0
  226. package/styles/index.mjs +1 -0
  227. package/styles/reducedMotion.d.mts +7 -0
  228. package/styles/reducedMotion.d.ts +7 -0
  229. package/styles/reducedMotion.js +21 -0
  230. package/styles/reducedMotion.mjs +14 -0
  231. package/styles/responsiveFontSizes.js +19 -8
  232. package/styles/responsiveFontSizes.mjs +19 -8
  233. package/styles/shouldSkipGeneratingVar.js +1 -1
  234. package/styles/shouldSkipGeneratingVar.mjs +1 -1
  235. package/styles/stringifyTheme.js +1 -0
  236. package/styles/stringifyTheme.mjs +1 -0
  237. package/styles/useThemeProps.d.mts +3 -3
  238. package/styles/useThemeProps.d.ts +3 -3
  239. package/transitions/index.d.mts +1 -1
  240. package/transitions/index.d.ts +1 -1
  241. package/transitions/index.js +0 -11
  242. package/transitions/index.mjs +1 -1
  243. package/transitions/transition.d.mts +1 -12
  244. package/transitions/transition.d.ts +1 -12
  245. package/transitions/types.d.mts +73 -0
  246. package/transitions/types.d.ts +73 -0
  247. package/transitions/useReducedMotion.d.mts +14 -0
  248. package/transitions/useReducedMotion.d.ts +14 -0
  249. package/transitions/useReducedMotion.js +117 -0
  250. package/transitions/useReducedMotion.mjs +110 -0
  251. package/transitions/utils.d.mts +51 -2
  252. package/transitions/utils.d.ts +51 -2
  253. package/transitions/utils.js +97 -4
  254. package/transitions/utils.mjs +94 -4
  255. package/useAutocomplete/useAutocomplete.d.mts +12 -6
  256. package/useAutocomplete/useAutocomplete.d.ts +12 -6
  257. package/useAutocomplete/useAutocomplete.js +230 -55
  258. package/useAutocomplete/useAutocomplete.mjs +230 -55
  259. package/utils/contains.d.mts +2 -0
  260. package/utils/contains.d.ts +2 -0
  261. package/utils/contains.js +9 -0
  262. package/utils/contains.mjs +2 -0
  263. package/utils/focusable.d.mts +7 -0
  264. package/utils/focusable.d.ts +7 -0
  265. package/utils/focusable.js +20 -0
  266. package/utils/focusable.mjs +13 -0
  267. package/utils/getEventTarget.d.mts +2 -0
  268. package/utils/getEventTarget.d.ts +2 -0
  269. package/utils/getEventTarget.js +9 -0
  270. package/utils/getEventTarget.mjs +2 -0
  271. package/utils/mergeSlotProps.js +2 -8
  272. package/utils/mergeSlotProps.mjs +1 -8
  273. package/version/index.js +2 -2
  274. package/version/index.mjs +2 -2
  275. package/FormControl/formControlState.js +0 -21
  276. package/FormControl/formControlState.mjs +0 -15
  277. /package/transitions/{transition.js → types.js} +0 -0
  278. /package/transitions/{transition.mjs → types.mjs} +0 -0
@@ -9,16 +9,109 @@ Object.defineProperty(exports, "__esModule", {
9
9
  exports.default = exports.TouchRippleRoot = exports.TouchRippleRipple = exports.DELAY_RIPPLE = void 0;
10
10
  var React = _interopRequireWildcard(require("react"));
11
11
  var _propTypes = _interopRequireDefault(require("prop-types"));
12
- var _reactTransitionGroup = require("react-transition-group");
13
12
  var _clsx = _interopRequireDefault(require("clsx"));
13
+ var _useOnMount = _interopRequireDefault(require("@mui/utils/useOnMount"));
14
14
  var _useTimeout = _interopRequireDefault(require("@mui/utils/useTimeout"));
15
15
  var _zeroStyled = require("../zero-styled");
16
16
  var _DefaultPropsProvider = require("../DefaultPropsProvider");
17
17
  var _Ripple = _interopRequireDefault(require("./Ripple"));
18
18
  var _touchRippleClasses = _interopRequireDefault(require("./touchRippleClasses"));
19
+ var _useEventCallback = _interopRequireDefault(require("../utils/useEventCallback"));
20
+ var _useReducedMotion = _interopRequireDefault(require("../transitions/useReducedMotion"));
19
21
  var _jsxRuntime = require("react/jsx-runtime");
20
22
  const DURATION = 550;
21
23
  const DELAY_RIPPLE = exports.DELAY_RIPPLE = 80;
24
+ const EMPTY_OBJ = {};
25
+ const EMPTY_ARRAY = [];
26
+ const NOOP = () => {};
27
+
28
+ /**
29
+ * Keep the same DOM order TouchRipple had when it used react-transition-group:
30
+ * exiting ripples stay in place, and new ripples are inserted before the final
31
+ * group of ripples that are waiting for their exit animation to finish.
32
+ *
33
+ * @param {number[]} prevOrder The previous DOM order, including ripples that may be exiting.
34
+ * @param {number[]} nextActiveKeys The ripples that should still be treated as active.
35
+ * @returns {number[]} The next DOM order, preserving the position of exiting ripples where possible.
36
+ */
37
+ function mergeRippleOrder(prevOrder, nextActiveKeys) {
38
+ const nextKeySet = new Set(nextActiveKeys);
39
+ const nextKeysPending = new Map();
40
+ let pendingKeys = [];
41
+ for (const prevKey of prevOrder) {
42
+ if (nextKeySet.has(prevKey)) {
43
+ if (pendingKeys.length > 0) {
44
+ nextKeysPending.set(prevKey, pendingKeys);
45
+ pendingKeys = [];
46
+ }
47
+ } else {
48
+ pendingKeys.push(prevKey);
49
+ }
50
+ }
51
+ const nextOrder = [];
52
+ for (const nextKey of nextActiveKeys) {
53
+ const pendingBefore = nextKeysPending.get(nextKey);
54
+ if (pendingBefore) {
55
+ nextOrder.push(...pendingBefore);
56
+ }
57
+ nextOrder.push(nextKey);
58
+ }
59
+ nextOrder.push(...pendingKeys);
60
+ return nextOrder;
61
+ }
62
+
63
+ /**
64
+ * Calculate where the ripple should start and how large it must be to cover the host element.
65
+ *
66
+ * @param {object} params
67
+ * @param {object} params.event The mouse or touch event that started the ripple.
68
+ * @param {HTMLElement | null} params.element The host element used for measurements. Tests pass `null`.
69
+ * @param {boolean} params.center If `true`, start the ripple from the center of the host element.
70
+ * @returns {{ rippleX: number, rippleY: number, rippleSize: number }} The ripple position and size.
71
+ */
72
+ function computeRippleState({
73
+ event,
74
+ element,
75
+ center
76
+ }) {
77
+ const rect = element ? element.getBoundingClientRect() : {
78
+ width: 0,
79
+ height: 0,
80
+ left: 0,
81
+ top: 0
82
+ };
83
+ let rippleX;
84
+ let rippleY;
85
+ if (center || event === undefined || event.clientX === 0 && event.clientY === 0 || !event.clientX && !event.touches) {
86
+ rippleX = Math.round(rect.width / 2);
87
+ rippleY = Math.round(rect.height / 2);
88
+ } else {
89
+ const {
90
+ clientX,
91
+ clientY
92
+ } = event.touches && event.touches.length > 0 ? event.touches[0] : event;
93
+ rippleX = Math.round(clientX - rect.left);
94
+ rippleY = Math.round(clientY - rect.top);
95
+ }
96
+ let rippleSize;
97
+ if (center) {
98
+ rippleSize = Math.sqrt((2 * rect.width ** 2 + rect.height ** 2) / 3);
99
+
100
+ // Mobile Chrome can skip this animation for even pixel sizes.
101
+ if (rippleSize % 2 === 0) {
102
+ rippleSize += 1;
103
+ }
104
+ } else {
105
+ const sizeX = Math.max(Math.abs((element ? element.clientWidth : 0) - rippleX), rippleX) * 2 + 2;
106
+ const sizeY = Math.max(Math.abs((element ? element.clientHeight : 0) - rippleY), rippleY) * 2 + 2;
107
+ rippleSize = Math.sqrt(sizeX ** 2 + sizeY ** 2);
108
+ }
109
+ return {
110
+ rippleX,
111
+ rippleY,
112
+ rippleSize
113
+ };
114
+ }
22
115
  const enterKeyframe = (0, _zeroStyled.keyframes)`
23
116
  0% {
24
117
  transform: scale(0);
@@ -52,6 +145,44 @@ const pulsateKeyframe = (0, _zeroStyled.keyframes)`
52
145
  transform: scale(1);
53
146
  }
54
147
  `;
148
+ function getAnimationStyles(theme) {
149
+ if (theme.motion.reducedMotion === 'always') {
150
+ return null;
151
+ }
152
+ const styles = (0, _zeroStyled.css)`
153
+ &.${_touchRippleClasses.default.rippleVisible} {
154
+ animation-name: ${enterKeyframe};
155
+ animation-duration: ${DURATION}ms;
156
+ animation-timing-function: ${theme.transitions.easing.easeInOut};
157
+ }
158
+
159
+ &.${_touchRippleClasses.default.ripplePulsate} {
160
+ animation-duration: ${theme.transitions.duration.shorter}ms;
161
+ }
162
+
163
+ & .${_touchRippleClasses.default.childLeaving} {
164
+ animation-name: ${exitKeyframe};
165
+ animation-duration: ${DURATION}ms;
166
+ animation-timing-function: ${theme.transitions.easing.easeInOut};
167
+ }
168
+
169
+ & .${_touchRippleClasses.default.childPulsate} {
170
+ animation-name: ${pulsateKeyframe};
171
+ animation-duration: 2500ms;
172
+ animation-timing-function: ${theme.transitions.easing.easeInOut};
173
+ animation-iteration-count: infinite;
174
+ animation-delay: 200ms;
175
+ }
176
+ `;
177
+ if (theme.motion.reducedMotion === 'system') {
178
+ return (0, _zeroStyled.css)`
179
+ @media (prefers-reduced-motion: no-preference) {
180
+ ${styles}
181
+ }
182
+ `;
183
+ }
184
+ return styles;
185
+ }
55
186
  const TouchRippleRoot = exports.TouchRippleRoot = (0, _zeroStyled.styled)('span', {
56
187
  name: 'MuiTouchRipple',
57
188
  slot: 'Root'
@@ -67,8 +198,8 @@ const TouchRippleRoot = exports.TouchRippleRoot = (0, _zeroStyled.styled)('span'
67
198
  borderRadius: 'inherit'
68
199
  });
69
200
 
70
- // This `styled()` function invokes keyframes. `styled-components` only supports keyframes
71
- // in string templates. Do not convert these styles in JS object as it will break.
201
+ // This `styled()` call uses keyframes. styled-components only supports keyframes
202
+ // in template strings, so do not convert these styles to a JS object.
72
203
  const TouchRippleRipple = exports.TouchRippleRipple = (0, _zeroStyled.styled)(_Ripple.default, {
73
204
  name: 'MuiTouchRipple',
74
205
  slot: 'Ripple'
@@ -79,35 +210,10 @@ const TouchRippleRipple = exports.TouchRippleRipple = (0, _zeroStyled.styled)(_R
79
210
  &.${_touchRippleClasses.default.rippleVisible} {
80
211
  opacity: 0.3;
81
212
  transform: scale(1);
82
- animation-name: ${enterKeyframe};
83
- animation-duration: ${DURATION}ms;
84
- animation-timing-function: ${({
85
- theme
86
- }) => theme.transitions.easing.easeInOut};
87
- }
88
-
89
- &.${_touchRippleClasses.default.ripplePulsate} {
90
- animation-duration: ${({
91
- theme
92
- }) => theme.transitions.duration.shorter}ms;
93
- }
94
-
95
- & .${_touchRippleClasses.default.child} {
96
- opacity: 1;
97
- display: block;
98
- width: 100%;
99
- height: 100%;
100
- border-radius: 50%;
101
- background-color: currentColor;
102
213
  }
103
214
 
104
215
  & .${_touchRippleClasses.default.childLeaving} {
105
216
  opacity: 0;
106
- animation-name: ${exitKeyframe};
107
- animation-duration: ${DURATION}ms;
108
- animation-timing-function: ${({
109
- theme
110
- }) => theme.transitions.easing.easeInOut};
111
217
  }
112
218
 
113
219
  & .${_touchRippleClasses.default.childPulsate} {
@@ -115,35 +221,54 @@ const TouchRippleRipple = exports.TouchRippleRipple = (0, _zeroStyled.styled)(_R
115
221
  /* @noflip */
116
222
  left: 0px;
117
223
  top: 0;
118
- animation-name: ${pulsateKeyframe};
119
- animation-duration: 2500ms;
120
- animation-timing-function: ${({
224
+ }
225
+
226
+ ${({
121
227
  theme
122
- }) => theme.transitions.easing.easeInOut};
123
- animation-iteration-count: infinite;
124
- animation-delay: 200ms;
228
+ }) => getAnimationStyles(theme)}
229
+
230
+ & .${_touchRippleClasses.default.child} {
231
+ opacity: 1;
232
+ display: block;
233
+ width: 100%;
234
+ height: 100%;
235
+ border-radius: 50%;
236
+ background-color: currentColor;
125
237
  }
126
238
  `;
127
239
 
128
240
  /**
129
241
  * @ignore - internal component.
130
- *
131
- * TODO v5: Make private
132
242
  */
133
243
  const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps, ref) {
134
244
  const props = (0, _DefaultPropsProvider.useDefaultProps)({
135
245
  props: inProps,
136
246
  name: 'MuiTouchRipple'
137
247
  });
248
+ const theme = (0, _zeroStyled.useTheme)();
249
+ const reducedMotion = (0, _useReducedMotion.default)(theme.motion.reducedMotion, false);
138
250
  const {
139
251
  center: centerProp = false,
140
- classes = {},
252
+ classes = EMPTY_OBJ,
141
253
  className,
142
254
  ...other
143
255
  } = props;
144
- const [ripples, setRipples] = React.useState([]);
256
+ // Store ripples as data so we can keep exiting ripples mounted until their
257
+ // exit animation ends. Ripple calls onExited when it is safe to remove one.
258
+ const [rippleState, setRippleState] = React.useState({
259
+ items: EMPTY_ARRAY,
260
+ order: EMPTY_ARRAY
261
+ });
262
+ const ripples = rippleState.items;
145
263
  const nextKey = React.useRef(0);
146
264
  const rippleCallback = React.useRef(null);
265
+ const mountedRef = React.useRef(false);
266
+ (0, _useOnMount.default)(() => {
267
+ mountedRef.current = true;
268
+ return () => {
269
+ mountedRef.current = false;
270
+ };
271
+ });
147
272
  React.useEffect(() => {
148
273
  if (rippleCallback.current) {
149
274
  rippleCallback.current();
@@ -157,10 +282,23 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
157
282
  // We don't want to display the ripple for touch scroll events.
158
283
  const startTimer = (0, _useTimeout.default)();
159
284
 
160
- // This is the hook called once the previous timeout is ready.
285
+ // Holds delayed touch-start work until the delay expires or touchend forces it to run.
161
286
  const startTimerCommit = React.useRef(null);
162
287
  const container = React.useRef(null);
163
- const startCommit = React.useCallback(params => {
288
+ const handleExited = (0, _useEventCallback.default)(key => {
289
+ if (!mountedRef.current) {
290
+ return;
291
+ }
292
+ setRippleState(prevState => {
293
+ const nextItems = prevState.items.filter(ripple => ripple.key !== key);
294
+ const nextOrder = mergeRippleOrder(prevState.order.filter(rippleKey => rippleKey !== key), nextItems.filter(ripple => !ripple.exiting).map(ripple => ripple.key));
295
+ return {
296
+ items: nextItems,
297
+ order: nextOrder
298
+ };
299
+ });
300
+ });
301
+ const startCommit = (0, _useEventCallback.default)(params => {
164
302
  const {
165
303
  pulsate,
166
304
  rippleX,
@@ -168,29 +306,29 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
168
306
  rippleSize,
169
307
  cb
170
308
  } = params;
171
- setRipples(oldRipples => [...oldRipples, /*#__PURE__*/(0, _jsxRuntime.jsx)(TouchRippleRipple, {
172
- classes: {
173
- ripple: (0, _clsx.default)(classes.ripple, _touchRippleClasses.default.ripple),
174
- rippleVisible: (0, _clsx.default)(classes.rippleVisible, _touchRippleClasses.default.rippleVisible),
175
- ripplePulsate: (0, _clsx.default)(classes.ripplePulsate, _touchRippleClasses.default.ripplePulsate),
176
- child: (0, _clsx.default)(classes.child, _touchRippleClasses.default.child),
177
- childLeaving: (0, _clsx.default)(classes.childLeaving, _touchRippleClasses.default.childLeaving),
178
- childPulsate: (0, _clsx.default)(classes.childPulsate, _touchRippleClasses.default.childPulsate)
179
- },
180
- timeout: DURATION,
181
- pulsate: pulsate,
182
- rippleX: rippleX,
183
- rippleY: rippleY,
184
- rippleSize: rippleSize
185
- }, nextKey.current)]);
309
+ const key = nextKey.current;
186
310
  nextKey.current += 1;
311
+ setRippleState(prevState => {
312
+ const nextItems = [...prevState.items, {
313
+ key,
314
+ pulsate,
315
+ rippleX,
316
+ rippleY,
317
+ rippleSize,
318
+ exiting: false
319
+ }];
320
+ return {
321
+ items: nextItems,
322
+ order: mergeRippleOrder(prevState.order, nextItems.filter(ripple => !ripple.exiting).map(ripple => ripple.key))
323
+ };
324
+ });
187
325
  rippleCallback.current = cb;
188
- }, [classes]);
189
- const start = React.useCallback((event = {}, options = {}, cb = () => {}) => {
326
+ });
327
+ const start = (0, _useEventCallback.default)((event = EMPTY_OBJ, options = EMPTY_OBJ, cb = NOOP) => {
190
328
  const {
191
329
  pulsate = false,
192
330
  center = centerProp || options.pulsate,
193
- fakeElement = false // For test purposes
331
+ fakeElement = false // Used only by tests.
194
332
  } = options;
195
333
  if (event?.type === 'mousedown' && ignoringMouseDown.current) {
196
334
  ignoringMouseDown.current = false;
@@ -200,48 +338,21 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
200
338
  ignoringMouseDown.current = true;
201
339
  }
202
340
  const element = fakeElement ? null : container.current;
203
- const rect = element ? element.getBoundingClientRect() : {
204
- width: 0,
205
- height: 0,
206
- left: 0,
207
- top: 0
208
- };
209
-
210
- // Get the size of the ripple
211
- let rippleX;
212
- let rippleY;
213
- let rippleSize;
214
- if (center || event === undefined || event.clientX === 0 && event.clientY === 0 || !event.clientX && !event.touches) {
215
- rippleX = Math.round(rect.width / 2);
216
- rippleY = Math.round(rect.height / 2);
217
- } else {
218
- const {
219
- clientX,
220
- clientY
221
- } = event.touches && event.touches.length > 0 ? event.touches[0] : event;
222
- rippleX = Math.round(clientX - rect.left);
223
- rippleY = Math.round(clientY - rect.top);
224
- }
225
- if (center) {
226
- rippleSize = Math.sqrt((2 * rect.width ** 2 + rect.height ** 2) / 3);
227
-
228
- // For some reason the animation is broken on Mobile Chrome if the size is even.
229
- if (rippleSize % 2 === 0) {
230
- rippleSize += 1;
231
- }
232
- } else {
233
- const sizeX = Math.max(Math.abs((element ? element.clientWidth : 0) - rippleX), rippleX) * 2 + 2;
234
- const sizeY = Math.max(Math.abs((element ? element.clientHeight : 0) - rippleY), rippleY) * 2 + 2;
235
- rippleSize = Math.sqrt(sizeX ** 2 + sizeY ** 2);
236
- }
341
+ const {
342
+ rippleX,
343
+ rippleY,
344
+ rippleSize
345
+ } = computeRippleState({
346
+ event,
347
+ element,
348
+ center
349
+ });
237
350
 
238
- // Touch devices
351
+ // Delay touch ripples so scroll gestures do not flash a ripple.
239
352
  if (event?.touches) {
240
- // check that this isn't another touchstart due to multitouch
241
- // otherwise we will only clear a single timer when unmounting while two
242
- // are running
353
+ // Ignore extra touchstart events from multi-touch. There is only one
354
+ // delayed start callback to clear on unmount.
243
355
  if (startTimerCommit.current === null) {
244
- // Prepare the ripple effect.
245
356
  startTimerCommit.current = () => {
246
357
  startCommit({
247
358
  pulsate,
@@ -251,8 +362,6 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
251
362
  cb
252
363
  });
253
364
  };
254
- // Delay the execution of the ripple effect.
255
- // We have to make a tradeoff with this delay value.
256
365
  startTimer.start(DELAY_RIPPLE, () => {
257
366
  if (startTimerCommit.current) {
258
367
  startTimerCommit.current();
@@ -269,17 +378,17 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
269
378
  cb
270
379
  });
271
380
  }
272
- }, [centerProp, startCommit, startTimer]);
273
- const pulsate = React.useCallback(() => {
274
- start({}, {
381
+ });
382
+ const pulsate = (0, _useEventCallback.default)(() => {
383
+ start(EMPTY_OBJ, {
275
384
  pulsate: true
276
385
  });
277
- }, [start]);
278
- const stop = React.useCallback((event, cb) => {
386
+ });
387
+ const stop = (0, _useEventCallback.default)((event, cb) => {
279
388
  startTimer.clear();
280
389
 
281
- // The touch interaction occurs too quickly.
282
- // We still want to show ripple effect.
390
+ // If touch ends before the delay finishes, show the ripple now and stop it
391
+ // on the next tick so the user still gets feedback.
283
392
  if (event?.type === 'touchend' && startTimerCommit.current) {
284
393
  startTimerCommit.current();
285
394
  startTimerCommit.current = null;
@@ -289,28 +398,55 @@ const TouchRipple = /*#__PURE__*/React.forwardRef(function TouchRipple(inProps,
289
398
  return;
290
399
  }
291
400
  startTimerCommit.current = null;
292
- setRipples(oldRipples => {
293
- if (oldRipples.length > 0) {
294
- return oldRipples.slice(1);
401
+ setRippleState(prevState => {
402
+ const firstActiveIndex = prevState.items.findIndex(ripple => !ripple.exiting);
403
+ if (firstActiveIndex === -1) {
404
+ return prevState;
295
405
  }
296
- return oldRipples;
406
+ const nextItems = prevState.items.slice();
407
+ nextItems[firstActiveIndex] = {
408
+ ...nextItems[firstActiveIndex],
409
+ exiting: true
410
+ };
411
+ return {
412
+ items: nextItems,
413
+ order: mergeRippleOrder(prevState.order, nextItems.filter(ripple => !ripple.exiting).map(ripple => ripple.key))
414
+ };
297
415
  });
298
416
  rippleCallback.current = cb;
299
- }, [startTimer]);
417
+ });
300
418
  React.useImperativeHandle(ref, () => ({
301
419
  pulsate,
302
420
  start,
303
421
  stop
304
422
  }), [pulsate, start, stop]);
423
+ const rippleByKey = new Map(ripples.map(ripple => [ripple.key, ripple]));
424
+ const orderedRipples = rippleState.order.map(rippleKey => rippleByKey.get(rippleKey)).filter(Boolean);
425
+
426
+ // Keep the old react-transition-group DOM order:
427
+ // exiting ripples stay in place, and new ripples are inserted before the
428
+ // final group waiting for its exit animation to finish.
305
429
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(TouchRippleRoot, {
306
430
  className: (0, _clsx.default)(_touchRippleClasses.default.root, classes.root, className),
307
431
  ref: container,
308
432
  ...other,
309
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactTransitionGroup.TransitionGroup, {
310
- component: null,
311
- exit: true,
312
- children: ripples
313
- })
433
+ children: orderedRipples.map(ripple => /*#__PURE__*/(0, _jsxRuntime.jsx)(TouchRippleRipple, {
434
+ classes: {
435
+ ripple: (0, _clsx.default)(classes.ripple, _touchRippleClasses.default.ripple),
436
+ rippleVisible: (0, _clsx.default)(classes.rippleVisible, _touchRippleClasses.default.rippleVisible),
437
+ ripplePulsate: (0, _clsx.default)(classes.ripplePulsate, _touchRippleClasses.default.ripplePulsate),
438
+ child: (0, _clsx.default)(classes.child, _touchRippleClasses.default.child),
439
+ childLeaving: (0, _clsx.default)(classes.childLeaving, _touchRippleClasses.default.childLeaving),
440
+ childPulsate: (0, _clsx.default)(classes.childPulsate, _touchRippleClasses.default.childPulsate)
441
+ },
442
+ timeout: reducedMotion.shouldReduceMotion ? 0 : DURATION,
443
+ pulsate: ripple.pulsate,
444
+ rippleX: ripple.rippleX,
445
+ rippleY: ripple.rippleY,
446
+ rippleSize: ripple.rippleSize,
447
+ in: !ripple.exiting,
448
+ onExited: () => handleExited(ripple.key)
449
+ }, ripple.key))
314
450
  });
315
451
  });
316
452
  process.env.NODE_ENV !== "production" ? TouchRipple.propTypes /* remove-proptypes */ = {