@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
@@ -15,19 +15,59 @@ var _clsx = _interopRequireDefault(require("clsx"));
15
15
  var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
16
16
  var _useId = _interopRequireDefault(require("@mui/utils/useId"));
17
17
  var _refType = _interopRequireDefault(require("@mui/utils/refType"));
18
+ var _useTimeout = _interopRequireDefault(require("@mui/utils/useTimeout"));
18
19
  var _ownerDocument = _interopRequireDefault(require("../utils/ownerDocument"));
19
20
  var _Menu = _interopRequireDefault(require("../Menu/Menu"));
20
21
  var _NativeSelectInput = require("../NativeSelect/NativeSelectInput");
21
22
  var _utils = require("../InputBase/utils");
22
23
  var _zeroStyled = require("../zero-styled");
23
24
  var _slotShouldForwardProp = _interopRequireDefault(require("../styles/slotShouldForwardProp"));
25
+ var _useEnhancedEffect = _interopRequireDefault(require("../utils/useEnhancedEffect"));
26
+ var _useEventCallback = _interopRequireDefault(require("../utils/useEventCallback"));
24
27
  var _useForkRef = _interopRequireDefault(require("../utils/useForkRef"));
25
28
  var _useControlled = _interopRequireDefault(require("../utils/useControlled"));
26
29
  var _selectClasses = _interopRequireWildcard(require("./selectClasses"));
27
30
  var _utils2 = require("./utils");
31
+ var _closedTypeahead = require("./utils/closedTypeahead");
28
32
  var _SelectFocusSourceContext = require("./utils/SelectFocusSourceContext");
29
33
  var _jsxRuntime = require("react/jsx-runtime");
30
34
  var _span;
35
+ const OPENING_MOUSE_UP_BOUNDARY_OFFSET = 2;
36
+ // The initial mouseup may land on an item when the menu opens over the trigger.
37
+ const SELECTED_MOUSE_UP_DELAY = 400;
38
+ const UNSELECTED_MOUSE_UP_DELAY = 200;
39
+ const TYPEAHEAD_RESET_MS = 750;
40
+ const SPACE = ' ';
41
+ const ARROW_UP = 'ArrowUp';
42
+ const ARROW_DOWN = 'ArrowDown';
43
+ const ENTER = 'Enter';
44
+
45
+ /**
46
+ * Returns true when a native mouse event should be treated as happening inside
47
+ * the element, even if a portal or backdrop retargeted the event away from it.
48
+ *
49
+ * Select uses this for the opening mouseup: when the menu opens over the
50
+ * trigger, the release can target the backdrop or portaled menu even though the
51
+ * pointer is still inside the trigger or menu bounds.
52
+ */
53
+ function isMouseEventInsideElement(event, element) {
54
+ if (!element) {
55
+ return false;
56
+ }
57
+ const eventPath = event.composedPath();
58
+ if (eventPath.includes(element)) {
59
+ return true;
60
+ }
61
+ if (event.target?.nodeType && element.contains(event.target)) {
62
+ return true;
63
+ }
64
+ const rect = element.getBoundingClientRect();
65
+ if (rect.width === 0 && rect.height === 0) {
66
+ // Hidden or transition-mounted elements do not have useful bounds to hit-test.
67
+ return false;
68
+ }
69
+ return event.clientX >= rect.left - OPENING_MOUSE_UP_BOUNDARY_OFFSET && event.clientX <= rect.right + OPENING_MOUSE_UP_BOUNDARY_OFFSET && event.clientY >= rect.top - OPENING_MOUSE_UP_BOUNDARY_OFFSET && event.clientY <= rect.bottom + OPENING_MOUSE_UP_BOUNDARY_OFFSET;
70
+ }
31
71
  const SelectSelect = (0, _zeroStyled.styled)(_NativeSelectInput.StyledSelectSelect, {
32
72
  name: 'MuiSelect',
33
73
  slot: 'Select',
@@ -154,6 +194,23 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
154
194
  });
155
195
  const inputRef = React.useRef(null);
156
196
  const displayRef = React.useRef(null);
197
+ const paperRef = React.useRef(null);
198
+ const openRef = React.useRef(false);
199
+ const hasSelectedItemInListRef = React.useRef(false);
200
+ const openingMouseUpListenerCleanupRef = React.useRef(null);
201
+ const didPointerDownOnItemRef = React.useRef(false);
202
+ const selectionRef = React.useRef({
203
+ allowSelectedMouseUp: false,
204
+ allowUnselectedMouseUp: false
205
+ });
206
+ const closedTypeaheadRef = React.useRef({
207
+ buffer: '',
208
+ previousSearchIndex: null,
209
+ matchedIndex: null
210
+ });
211
+ const selectedMouseUpTimer = (0, _useTimeout.default)();
212
+ const unselectedMouseUpTimer = (0, _useTimeout.default)();
213
+ const typeaheadResetTimer = (0, _useTimeout.default)();
157
214
  const [displayNode, setDisplayNode] = React.useState(null);
158
215
  const {
159
216
  current: isOpenControlled
@@ -176,6 +233,52 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
176
233
  value
177
234
  }), [value]);
178
235
  const open = displayNode !== null && openState;
236
+ const resetClosedTypeahead = React.useCallback(() => {
237
+ typeaheadResetTimer.clear();
238
+ closedTypeaheadRef.current.buffer = '';
239
+ closedTypeaheadRef.current.previousSearchIndex = null;
240
+ closedTypeaheadRef.current.matchedIndex = null;
241
+ }, [typeaheadResetTimer]);
242
+ (0, _useEnhancedEffect.default)(() => {
243
+ openRef.current = open;
244
+ if (open) {
245
+ resetClosedTypeahead();
246
+ }
247
+ }, [open, resetClosedTypeahead]);
248
+ const clearSelectionTimers = React.useCallback(() => {
249
+ selectedMouseUpTimer.clear();
250
+ unselectedMouseUpTimer.clear();
251
+ }, [selectedMouseUpTimer, unselectedMouseUpTimer]);
252
+ const resetMouseUpSelection = React.useCallback(() => {
253
+ clearSelectionTimers();
254
+ didPointerDownOnItemRef.current = false;
255
+ selectionRef.current = {
256
+ allowSelectedMouseUp: false,
257
+ allowUnselectedMouseUp: false
258
+ };
259
+ }, [clearSelectionTimers]);
260
+ const clearOpeningMouseUpListener = React.useCallback(() => {
261
+ if (openingMouseUpListenerCleanupRef.current) {
262
+ openingMouseUpListenerCleanupRef.current();
263
+ openingMouseUpListenerCleanupRef.current = null;
264
+ }
265
+ }, []);
266
+ React.useEffect(() => {
267
+ if (!open) {
268
+ resetMouseUpSelection();
269
+ clearOpeningMouseUpListener();
270
+ }
271
+ }, [open, resetMouseUpSelection, clearOpeningMouseUpListener]);
272
+
273
+ // Keep unmount cleanup separate from the `open` effect. Effect cleanups also run
274
+ // before the next effect, which would clear the opening mouseup listener while opening.
275
+ React.useEffect(() => {
276
+ return () => {
277
+ resetMouseUpSelection();
278
+ clearOpeningMouseUpListener();
279
+ resetClosedTypeahead();
280
+ };
281
+ }, [resetMouseUpSelection, clearOpeningMouseUpListener, resetClosedTypeahead]);
179
282
  React.useEffect(() => {
180
283
  if (!open || !anchorElement || autoWidth) {
181
284
  return undefined;
@@ -226,8 +329,13 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
226
329
  }
227
330
  return undefined;
228
331
  }, [labelId]);
229
- const update = (openParam, event) => {
332
+ const update = (0, _useEventCallback.default)((openParam, event) => {
333
+ if (!openParam) {
334
+ resetMouseUpSelection();
335
+ clearOpeningMouseUpListener();
336
+ }
230
337
  if (openParam) {
338
+ resetClosedTypeahead();
231
339
  setOpenInteractionType((0, _utils2.getOpenInteractionType)(event));
232
340
  if (onOpen) {
233
341
  onOpen(event);
@@ -239,9 +347,33 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
239
347
  }
240
348
  }
241
349
  if (!isOpenControlled) {
350
+ openRef.current = openParam;
242
351
  setMenuMinWidthState(autoWidth ? null : anchorElement.clientWidth);
243
352
  setOpenState(openParam);
244
353
  }
354
+ });
355
+ const scheduleMouseUpSelection = () => {
356
+ resetMouseUpSelection();
357
+
358
+ // When there is no selected item in the list, a mousedown
359
+ // on the trigger followed by a quick mouseup over the first option can accidentally select
360
+ // within 200ms. Delay unselected mouseup to match the safer 400ms window.
361
+ if (!hasSelectedItemInListRef.current) {
362
+ selectedMouseUpTimer.start(SELECTED_MOUSE_UP_DELAY, () => {
363
+ selectionRef.current.allowSelectedMouseUp = true;
364
+ selectionRef.current.allowUnselectedMouseUp = true;
365
+ });
366
+ } else {
367
+ // mousedown -> move to unselected item -> mouseup should not select within 200ms.
368
+ unselectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
369
+ selectionRef.current.allowUnselectedMouseUp = true;
370
+
371
+ // mousedown -> mouseup on selected item should not select within 400ms.
372
+ selectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
373
+ selectionRef.current.allowSelectedMouseUp = true;
374
+ });
375
+ });
376
+ }
245
377
  };
246
378
  const handleMouseDown = event => {
247
379
  onMouseDown?.(event);
@@ -252,6 +384,29 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
252
384
  // Hijack the default focus behavior.
253
385
  event.preventDefault();
254
386
  displayRef.current.focus();
387
+ const doc = (0, _ownerDocument.default)(event.currentTarget);
388
+ scheduleMouseUpSelection();
389
+ clearOpeningMouseUpListener();
390
+ const handleMouseUp = mouseEvent => {
391
+ openingMouseUpListenerCleanupRef.current = null;
392
+ if (!displayRef.current) {
393
+ return;
394
+ }
395
+ if (isMouseEventInsideElement(mouseEvent, displayRef.current) || isMouseEventInsideElement(mouseEvent, paperRef.current)) {
396
+ return;
397
+ }
398
+ if (!openRef.current && isOpenControlled) {
399
+ return;
400
+ }
401
+ update(false, mouseEvent);
402
+ };
403
+ doc.addEventListener('mouseup', handleMouseUp, {
404
+ capture: true,
405
+ once: true
406
+ });
407
+ openingMouseUpListenerCleanupRef.current = () => {
408
+ doc.removeEventListener('mouseup', handleMouseUp, true);
409
+ };
255
410
  update(true, event);
256
411
  };
257
412
  const handleClose = event => {
@@ -270,7 +425,27 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
270
425
  onChange(event, child);
271
426
  }
272
427
  };
428
+ const handleValueChange = (event, child, newValue) => {
429
+ setValueState(newValue);
430
+ if (onChange) {
431
+ // Redefine target to allow name and value to be read.
432
+ // This allows seamless integration with the most popular form libraries.
433
+ // https://github.com/mui/material-ui/issues/13485#issuecomment-676048492
434
+ // Clone the event to not override `target` of the original event.
435
+ const nativeEvent = event.nativeEvent || event;
436
+ const clonedEvent = new nativeEvent.constructor(nativeEvent.type, nativeEvent);
437
+ Object.defineProperty(clonedEvent, 'target', {
438
+ writable: true,
439
+ value: {
440
+ value: newValue,
441
+ name
442
+ }
443
+ });
444
+ onChange(clonedEvent, child);
445
+ }
446
+ };
273
447
  const handleItemClick = child => event => {
448
+ didPointerDownOnItemRef.current = false;
274
449
  let newValue;
275
450
 
276
451
  // We use the tabindex attribute to signal the available options.
@@ -292,35 +467,76 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
292
467
  child.props.onClick(event);
293
468
  }
294
469
  if (value !== newValue) {
295
- setValueState(newValue);
296
- if (onChange) {
297
- // Redefine target to allow name and value to be read.
298
- // This allows seamless integration with the most popular form libraries.
299
- // https://github.com/mui/material-ui/issues/13485#issuecomment-676048492
300
- // Clone the event to not override `target` of the original event.
301
- const nativeEvent = event.nativeEvent || event;
302
- const clonedEvent = new nativeEvent.constructor(nativeEvent.type, nativeEvent);
303
- Object.defineProperty(clonedEvent, 'target', {
304
- writable: true,
305
- value: {
306
- value: newValue,
307
- name
308
- }
309
- });
310
- onChange(clonedEvent, child);
311
- }
470
+ handleValueChange(event, child, newValue);
312
471
  }
313
472
  if (!multiple) {
314
473
  update(false, event);
315
474
  }
316
475
  };
476
+ const handleItemMouseUp = (child, selected) => event => {
477
+ child.props.onMouseUp?.(event);
478
+ if (didPointerDownOnItemRef.current) {
479
+ didPointerDownOnItemRef.current = false;
480
+ return;
481
+ }
482
+ const disallowSelectedMouseUp = !selectionRef.current.allowSelectedMouseUp && selected;
483
+ const disallowUnselectedMouseUp = !selectionRef.current.allowUnselectedMouseUp && !selected;
484
+ if (disallowSelectedMouseUp || disallowUnselectedMouseUp) {
485
+ return;
486
+ }
487
+ event.currentTarget.click();
488
+ };
489
+ const handleClosedTypeahead = event => {
490
+ const state = closedTypeaheadRef.current;
491
+ const hasActiveBuffer = state.buffer !== '';
492
+ if (open || multiple || disabled || event.defaultPrevented || event.nativeEvent?.isComposing || event.key.length !== 1 || event.ctrlKey || event.metaKey || event.altKey || event.key === SPACE && !hasActiveBuffer) {
493
+ return false;
494
+ }
495
+ if (event.key === SPACE) {
496
+ event.preventDefault();
497
+ }
498
+ const isNewSession = state.buffer === '';
499
+ const {
500
+ options: searchableOptions,
501
+ selectedIndex
502
+ } = (0, _closedTypeahead.getTypeaheadOptions)(childrenArray, value);
503
+ if (searchableOptions.length === 0) {
504
+ if (event.key !== SPACE) {
505
+ resetClosedTypeahead();
506
+ }
507
+ return true;
508
+ }
509
+ if (isNewSession) {
510
+ state.previousSearchIndex = selectedIndex;
511
+ }
512
+ const key = event.key.toLowerCase();
513
+ if (state.buffer === key && (0, _closedTypeahead.canCycleRepeatedCharacter)(searchableOptions, key)) {
514
+ state.buffer = '';
515
+ state.previousSearchIndex = state.matchedIndex;
516
+ }
517
+ state.buffer += key;
518
+ typeaheadResetTimer.start(TYPEAHEAD_RESET_MS, resetClosedTypeahead);
519
+ const matchingIndex = (0, _closedTypeahead.getMatchingOptionIndex)(searchableOptions, state.buffer, (state.previousSearchIndex ?? -1) + 1);
520
+ if (matchingIndex !== -1) {
521
+ const matchedOption = searchableOptions[matchingIndex];
522
+ state.matchedIndex = matchingIndex;
523
+ if (!(0, _utils2.areEqualValues)(value, matchedOption.value)) {
524
+ handleValueChange(event, matchedOption.child, matchedOption.value);
525
+ }
526
+ return true;
527
+ }
528
+ if (event.key !== SPACE) {
529
+ resetClosedTypeahead();
530
+ }
531
+ return true;
532
+ };
317
533
  const handleKeyDown = event => {
318
534
  if (!readOnly) {
319
- const validKeys = [' ', 'ArrowUp', 'ArrowDown',
320
- // The native select doesn't respond to enter on macOS, but it's recommended by
535
+ const isClosedTypeaheadHandled = handleClosedTypeahead(event);
536
+ // The native select doesn't respond to Enter on macOS, but it's recommended by
321
537
  // https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
322
- 'Enter'];
323
- if (validKeys.includes(event.key)) {
538
+ const isOpenKey = event.key === SPACE || event.key === ARROW_UP || event.key === ARROW_DOWN || event.key === ENTER;
539
+ if (!isClosedTypeaheadHandled && isOpenKey) {
324
540
  event.preventDefault();
325
541
  update(true, event);
326
542
  }
@@ -328,6 +544,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
328
544
  }
329
545
  };
330
546
  const handleBlur = event => {
547
+ resetClosedTypeahead();
331
548
  // if open event.stopImmediatePropagation
332
549
  if (!open && onBlur) {
333
550
  // Preact support, target is read only property on a native event.
@@ -341,6 +558,19 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
341
558
  onBlur(event);
342
559
  }
343
560
  };
561
+ const handleItemKeyDown = child => event => {
562
+ child?.props?.onKeyDown?.(event);
563
+ if (event.key === SPACE && event.target === event.currentTarget && !event.defaultPrevented) {
564
+ // Prevent the browser from scrolling the page
565
+ event.preventDefault();
566
+ // Ignore auto-repeated keydowns to avoid toggling multiple times
567
+ if (!event.repeat) {
568
+ // Trigger via click so that onClick receives a click event,
569
+ // consistent with Enter and pointer interactions.
570
+ event.currentTarget.click();
571
+ }
572
+ }
573
+ };
344
574
  delete other['aria-invalid'];
345
575
  let display;
346
576
  let displaySingle;
@@ -387,9 +617,18 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
387
617
  }
388
618
  return /*#__PURE__*/React.cloneElement(child, {
389
619
  'aria-selected': selected ? 'true' : 'false',
620
+ onMouseDown: event => {
621
+ didPointerDownOnItemRef.current = true;
622
+ child.props.onMouseDown?.(event);
623
+ },
624
+ onPointerDown: event => {
625
+ didPointerDownOnItemRef.current = true;
626
+ child.props.onPointerDown?.(event);
627
+ },
390
628
  onClick: handleItemClick(child),
629
+ onMouseUp: handleItemMouseUp(child, selected),
391
630
  onKeyUp: event => {
392
- if (event.key === ' ') {
631
+ if (event.key === SPACE) {
393
632
  // otherwise our MenuItems dispatches a click event
394
633
  // it's not behavior of the native <option> and causes
395
634
  // the select to close immediately since we open on space keydown
@@ -399,6 +638,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
399
638
  child.props.onKeyUp(event);
400
639
  }
401
640
  },
641
+ onKeyDown: handleItemKeyDown(child),
402
642
  role: 'option',
403
643
  selected,
404
644
  value: undefined,
@@ -406,6 +646,14 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
406
646
  'data-value': child.props.value // Instead, we provide it as a data attribute.
407
647
  });
408
648
  });
649
+
650
+ // Keep the opening mouseup guard current without mutating refs during render.
651
+ (0, _useEnhancedEffect.default)(() => {
652
+ hasSelectedItemInListRef.current = foundMatch;
653
+ if (!open && !multiple && !foundMatch) {
654
+ resetClosedTypeahead();
655
+ }
656
+ }, [foundMatch, multiple, open, resetClosedTypeahead]);
409
657
  if (process.env.NODE_ENV !== 'production') {
410
658
  // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
411
659
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -455,6 +703,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
455
703
  };
456
704
  const classes = useUtilityClasses(ownerState);
457
705
  const menuPaperSlotProps = typeof MenuProps.slotProps?.paper === 'function' ? MenuProps.slotProps.paper(ownerState) : MenuProps.slotProps?.paper;
706
+ const handlePaperRef = (0, _useForkRef.default)(menuPaperSlotProps?.ref, paperRef);
458
707
  const menuListSlotProps = typeof MenuProps.slotProps?.list === 'function' ? MenuProps.slotProps.list(ownerState) : MenuProps.slotProps?.list;
459
708
  const listboxId = (0, _useId.default)();
460
709
  const nativeInputId = (0, _useId.default)();
@@ -468,8 +717,9 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
468
717
  "aria-disabled": disabled ? 'true' : undefined,
469
718
  "aria-expanded": open ? 'true' : 'false',
470
719
  "aria-haspopup": "listbox",
720
+ "aria-readonly": readOnly ? 'true' : undefined,
471
721
  "aria-label": ariaLabel,
472
- "aria-labelledby": [labelId, buttonId].filter(Boolean).join(' ') || undefined,
722
+ "aria-labelledby": labelId,
473
723
  "aria-describedby": ariaDescribedby,
474
724
  "aria-required": required ? 'true' : undefined,
475
725
  "aria-invalid": error ? 'true' : undefined,
@@ -498,6 +748,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
498
748
  onChange: handleChange,
499
749
  tabIndex: -1,
500
750
  disabled: disabled,
751
+ readOnly: readOnly,
501
752
  className: classes.nativeInput,
502
753
  autoFocus: autoFocus,
503
754
  required: required,
@@ -536,6 +787,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
536
787
  },
537
788
  paper: {
538
789
  ...menuPaperSlotProps,
790
+ ref: handlePaperRef,
539
791
  style: {
540
792
  minWidth: menuMinWidth,
541
793
  ...menuPaperSlotProps?.style