@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.
- package/Accordion/Accordion.d.mts +2 -2
- package/Accordion/Accordion.d.ts +2 -2
- package/Accordion/Accordion.js +3 -2
- package/Accordion/Accordion.mjs +3 -2
- package/AccordionSummary/AccordionSummary.js +27 -29
- package/AccordionSummary/AccordionSummary.mjs +27 -29
- package/Autocomplete/Autocomplete.js +73 -17
- package/Autocomplete/Autocomplete.mjs +73 -17
- package/Avatar/Avatar.js +4 -0
- package/Avatar/Avatar.mjs +4 -0
- package/Backdrop/Backdrop.d.mts +2 -2
- package/Backdrop/Backdrop.d.ts +2 -2
- package/Badge/Badge.js +31 -24
- package/Badge/Badge.mjs +31 -24
- package/BottomNavigationAction/BottomNavigationAction.js +6 -2
- package/BottomNavigationAction/BottomNavigationAction.mjs +6 -2
- package/Button/Button.js +19 -6
- package/Button/Button.mjs +19 -6
- package/ButtonBase/ButtonBase.d.mts +7 -0
- package/ButtonBase/ButtonBase.d.ts +7 -0
- package/ButtonBase/ButtonBase.js +5 -2
- package/ButtonBase/ButtonBase.mjs +5 -2
- package/ButtonBase/Ripple.js +21 -11
- package/ButtonBase/Ripple.mjs +21 -11
- package/ButtonBase/TouchRipple.js +252 -116
- package/ButtonBase/TouchRipple.mjs +253 -117
- package/CHANGELOG.md +216 -1245
- package/CardActionArea/CardActionArea.js +2 -1
- package/CardActionArea/CardActionArea.mjs +2 -1
- package/Checkbox/Checkbox.js +2 -1
- package/Checkbox/Checkbox.mjs +2 -1
- package/Chip/Chip.js +2 -1
- package/Chip/Chip.mjs +2 -1
- package/CircularProgress/CircularProgress.d.mts +12 -2
- package/CircularProgress/CircularProgress.d.ts +12 -2
- package/CircularProgress/CircularProgress.js +115 -58
- package/CircularProgress/CircularProgress.mjs +114 -58
- package/ClickAwayListener/ClickAwayListener.js +3 -6
- package/ClickAwayListener/ClickAwayListener.mjs +3 -6
- package/Collapse/Collapse.d.mts +15 -3
- package/Collapse/Collapse.d.ts +15 -3
- package/Collapse/Collapse.js +44 -31
- package/Collapse/Collapse.mjs +43 -30
- package/Dialog/Dialog.d.mts +2 -2
- package/Dialog/Dialog.d.ts +2 -2
- package/Dialog/Dialog.js +13 -6
- package/Dialog/Dialog.mjs +13 -6
- package/Drawer/Drawer.d.mts +2 -2
- package/Drawer/Drawer.d.ts +2 -2
- package/Drawer/Drawer.js +18 -4
- package/Drawer/Drawer.mjs +18 -4
- package/Fab/Fab.js +9 -2
- package/Fab/Fab.mjs +9 -2
- package/Fade/Fade.d.mts +15 -2
- package/Fade/Fade.d.ts +15 -2
- package/Fade/Fade.js +46 -19
- package/Fade/Fade.mjs +45 -18
- package/FilledInput/FilledInput.d.mts +4 -0
- package/FilledInput/FilledInput.d.ts +4 -0
- package/FilledInput/FilledInput.js +22 -23
- package/FilledInput/FilledInput.mjs +22 -23
- package/FormControl/useFormControl.d.mts +12 -2
- package/FormControl/useFormControl.d.ts +12 -2
- package/FormControl/useFormControl.js +13 -0
- package/FormControl/useFormControl.mjs +12 -0
- package/FormControlLabel/FormControlLabel.js +5 -8
- package/FormControlLabel/FormControlLabel.mjs +5 -8
- package/FormGroup/FormGroup.js +2 -5
- package/FormGroup/FormGroup.mjs +2 -5
- package/FormHelperText/FormHelperText.js +2 -5
- package/FormHelperText/FormHelperText.mjs +2 -5
- package/FormLabel/FormLabel.js +2 -5
- package/FormLabel/FormLabel.mjs +2 -5
- package/Grow/Grow.d.mts +15 -2
- package/Grow/Grow.d.ts +15 -2
- package/Grow/Grow.js +45 -28
- package/Grow/Grow.mjs +44 -27
- package/IconButton/IconButton.js +3 -9
- package/IconButton/IconButton.mjs +3 -9
- package/Input/Input.d.mts +4 -0
- package/Input/Input.d.ts +4 -0
- package/Input/Input.js +9 -2
- package/Input/Input.mjs +9 -2
- package/InputBase/InputBase.d.mts +2 -1
- package/InputBase/InputBase.d.ts +2 -1
- package/InputBase/InputBase.js +52 -16
- package/InputBase/InputBase.mjs +52 -16
- package/InputLabel/InputLabel.js +7 -9
- package/InputLabel/InputLabel.mjs +7 -9
- package/LICENSE +1 -1
- package/LinearProgress/LinearProgress.d.mts +12 -2
- package/LinearProgress/LinearProgress.d.ts +12 -2
- package/LinearProgress/LinearProgress.js +225 -126
- package/LinearProgress/LinearProgress.mjs +224 -126
- package/List/List.js +2 -1
- package/List/List.mjs +2 -1
- package/ListItem/ListItem.js +2 -1
- package/ListItem/ListItem.mjs +2 -1
- package/ListItemButton/ListItemButton.js +9 -2
- package/ListItemButton/ListItemButton.mjs +9 -2
- package/Menu/Menu.d.mts +1 -1
- package/Menu/Menu.d.ts +1 -1
- package/MenuItem/MenuItem.js +7 -1
- package/MenuItem/MenuItem.mjs +7 -1
- package/MenuList/MenuList.js +2 -1
- package/MenuList/MenuList.mjs +2 -1
- package/MobileStepper/MobileStepper.js +2 -1
- package/MobileStepper/MobileStepper.mjs +2 -1
- package/NativeSelect/NativeSelect.js +2 -5
- package/NativeSelect/NativeSelect.mjs +2 -5
- package/OutlinedInput/NotchedOutline.js +4 -3
- package/OutlinedInput/NotchedOutline.mjs +4 -3
- package/OutlinedInput/OutlinedInput.js +13 -23
- package/OutlinedInput/OutlinedInput.mjs +13 -23
- package/PaginationItem/PaginationItem.js +2 -1
- package/PaginationItem/PaginationItem.mjs +2 -1
- package/Paper/Paper.js +2 -1
- package/Paper/Paper.mjs +2 -1
- package/PigmentContainer/PigmentContainer.js +0 -1
- package/PigmentContainer/PigmentContainer.mjs +0 -1
- package/Popover/Popover.d.mts +1 -1
- package/Popover/Popover.d.ts +1 -1
- package/Popper/BasePopper.js +23 -1
- package/Popper/BasePopper.mjs +23 -1
- package/README.md +3 -2
- package/Radio/RadioButtonIcon.js +3 -2
- package/Radio/RadioButtonIcon.mjs +3 -2
- package/Rating/Rating.js +2 -1
- package/Rating/Rating.mjs +2 -1
- package/Select/Select.js +2 -5
- package/Select/Select.mjs +2 -5
- package/Select/SelectInput.js +276 -24
- package/Select/SelectInput.mjs +276 -24
- package/Select/utils/closedTypeahead.js +73 -0
- package/Select/utils/closedTypeahead.mjs +63 -0
- package/Skeleton/Skeleton.js +22 -2
- package/Skeleton/Skeleton.mjs +22 -2
- package/Slide/Slide.d.mts +15 -2
- package/Slide/Slide.d.ts +15 -2
- package/Slide/Slide.js +97 -47
- package/Slide/Slide.mjs +97 -47
- package/Slider/Slider.js +14 -4
- package/Slider/Slider.mjs +14 -4
- package/Slider/useSlider.js +4 -3
- package/Slider/useSlider.mjs +4 -3
- package/Snackbar/Snackbar.d.mts +2 -2
- package/Snackbar/Snackbar.d.ts +2 -2
- package/SpeedDial/SpeedDial.d.mts +1 -1
- package/SpeedDial/SpeedDial.d.ts +1 -1
- package/SpeedDial/SpeedDial.js +6 -2
- package/SpeedDial/SpeedDial.mjs +6 -2
- package/SpeedDialAction/SpeedDialAction.js +11 -2
- package/SpeedDialAction/SpeedDialAction.mjs +12 -3
- package/SpeedDialIcon/SpeedDialIcon.js +40 -37
- package/SpeedDialIcon/SpeedDialIcon.mjs +40 -37
- package/Step/Step.js +47 -15
- package/Step/Step.mjs +47 -15
- package/StepButton/StepButton.js +9 -3
- package/StepButton/StepButton.mjs +9 -3
- package/StepConnector/StepConnector.js +10 -0
- package/StepConnector/StepConnector.mjs +10 -0
- package/StepContent/StepContent.d.mts +2 -2
- package/StepContent/StepContent.d.ts +2 -2
- package/StepContent/StepContent.js +26 -2
- package/StepContent/StepContent.mjs +26 -2
- package/StepIcon/StepIcon.js +2 -1
- package/StepIcon/StepIcon.mjs +2 -1
- package/StepLabel/StepLabel.js +52 -7
- package/StepLabel/StepLabel.mjs +52 -7
- package/Stepper/Stepper.d.mts +2 -0
- package/Stepper/Stepper.d.ts +2 -0
- package/Stepper/Stepper.js +18 -0
- package/Stepper/Stepper.mjs +18 -0
- package/SvgIcon/SvgIcon.js +2 -1
- package/SvgIcon/SvgIcon.mjs +2 -1
- package/SwipeableDrawer/SwipeableDrawer.js +21 -6
- package/SwipeableDrawer/SwipeableDrawer.mjs +21 -6
- package/Switch/Switch.js +10 -8
- package/Switch/Switch.mjs +10 -8
- package/TableSortLabel/TableSortLabel.js +2 -1
- package/TableSortLabel/TableSortLabel.mjs +2 -1
- package/Tabs/ScrollbarSize.js +2 -1
- package/Tabs/ScrollbarSize.mjs +2 -1
- package/Tabs/Tabs.js +16 -4
- package/Tabs/Tabs.mjs +16 -4
- package/Tooltip/Tooltip.d.mts +2 -2
- package/Tooltip/Tooltip.d.ts +2 -2
- package/Tooltip/Tooltip.js +29 -108
- package/Tooltip/Tooltip.mjs +29 -108
- package/Unstable_TrapFocus/FocusTrap.js +60 -22
- package/Unstable_TrapFocus/FocusTrap.mjs +60 -22
- package/Zoom/Zoom.d.mts +15 -2
- package/Zoom/Zoom.d.ts +15 -2
- package/Zoom/Zoom.js +43 -16
- package/Zoom/Zoom.mjs +42 -15
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internal/Transition.d.mts +34 -0
- package/internal/Transition.d.ts +34 -0
- package/internal/Transition.js +444 -0
- package/internal/Transition.mjs +436 -0
- package/internal/react-transition-group.d.mts +8 -0
- package/internal/react-transition-group.d.ts +8 -0
- package/package.json +50 -50
- package/styles/createMotion.d.mts +8 -0
- package/styles/createMotion.d.ts +8 -0
- package/styles/createMotion.js +13 -0
- package/styles/createMotion.mjs +7 -0
- package/styles/createThemeFoundation.d.mts +2 -0
- package/styles/createThemeFoundation.d.ts +2 -0
- package/styles/createThemeNoVars.d.mts +3 -0
- package/styles/createThemeNoVars.d.ts +3 -0
- package/styles/createThemeNoVars.js +5 -0
- package/styles/createThemeNoVars.mjs +5 -0
- package/styles/createTransitions.d.mts +6 -2
- package/styles/createTransitions.d.ts +6 -2
- package/styles/createTransitions.js +12 -4
- package/styles/createTransitions.mjs +12 -4
- package/styles/enhanceHighContrast.d.mts +70 -0
- package/styles/enhanceHighContrast.d.ts +70 -0
- package/styles/enhanceHighContrast.js +502 -0
- package/styles/enhanceHighContrast.mjs +495 -0
- package/styles/index.d.mts +2 -0
- package/styles/index.d.ts +2 -0
- package/styles/index.js +8 -0
- package/styles/index.mjs +1 -0
- package/styles/reducedMotion.d.mts +7 -0
- package/styles/reducedMotion.d.ts +7 -0
- package/styles/reducedMotion.js +21 -0
- package/styles/reducedMotion.mjs +14 -0
- package/styles/responsiveFontSizes.js +19 -8
- package/styles/responsiveFontSizes.mjs +19 -8
- package/styles/shouldSkipGeneratingVar.js +1 -1
- package/styles/shouldSkipGeneratingVar.mjs +1 -1
- package/styles/stringifyTheme.js +1 -0
- package/styles/stringifyTheme.mjs +1 -0
- package/styles/useThemeProps.d.mts +3 -3
- package/styles/useThemeProps.d.ts +3 -3
- package/transitions/index.d.mts +1 -1
- package/transitions/index.d.ts +1 -1
- package/transitions/index.js +0 -11
- package/transitions/index.mjs +1 -1
- package/transitions/transition.d.mts +1 -12
- package/transitions/transition.d.ts +1 -12
- package/transitions/types.d.mts +73 -0
- package/transitions/types.d.ts +73 -0
- package/transitions/useReducedMotion.d.mts +14 -0
- package/transitions/useReducedMotion.d.ts +14 -0
- package/transitions/useReducedMotion.js +117 -0
- package/transitions/useReducedMotion.mjs +110 -0
- package/transitions/utils.d.mts +51 -2
- package/transitions/utils.d.ts +51 -2
- package/transitions/utils.js +97 -4
- package/transitions/utils.mjs +94 -4
- package/useAutocomplete/useAutocomplete.d.mts +12 -6
- package/useAutocomplete/useAutocomplete.d.ts +12 -6
- package/useAutocomplete/useAutocomplete.js +230 -55
- package/useAutocomplete/useAutocomplete.mjs +230 -55
- package/utils/contains.d.mts +2 -0
- package/utils/contains.d.ts +2 -0
- package/utils/contains.js +9 -0
- package/utils/contains.mjs +2 -0
- package/utils/focusable.d.mts +7 -0
- package/utils/focusable.d.ts +7 -0
- package/utils/focusable.js +20 -0
- package/utils/focusable.mjs +13 -0
- package/utils/getEventTarget.d.mts +2 -0
- package/utils/getEventTarget.d.ts +2 -0
- package/utils/getEventTarget.js +9 -0
- package/utils/getEventTarget.mjs +2 -0
- package/utils/mergeSlotProps.js +2 -8
- package/utils/mergeSlotProps.mjs +1 -8
- package/version/index.js +2 -2
- package/version/index.mjs +2 -2
- package/FormControl/formControlState.js +0 -21
- package/FormControl/formControlState.mjs +0 -15
- /package/transitions/{transition.js → types.js} +0 -0
- /package/transitions/{transition.mjs → types.mjs} +0 -0
package/Select/SelectInput.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
320
|
-
// The native select doesn't respond to
|
|
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
|
-
|
|
323
|
-
if (
|
|
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":
|
|
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
|