@mui/material 9.0.0 → 9.0.1
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/Autocomplete/Autocomplete.js +65 -11
- package/Autocomplete/Autocomplete.mjs +65 -11
- package/Avatar/Avatar.js +4 -0
- package/Avatar/Avatar.mjs +4 -0
- package/Badge/Badge.js +3 -0
- package/Badge/Badge.mjs +3 -0
- package/Button/Button.js +19 -2
- package/Button/Button.mjs +19 -2
- 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/CHANGELOG.md +132 -1245
- package/Checkbox/Checkbox.js +2 -1
- package/Checkbox/Checkbox.mjs +2 -1
- package/CircularProgress/CircularProgress.d.mts +12 -2
- package/CircularProgress/CircularProgress.d.ts +12 -2
- package/CircularProgress/CircularProgress.js +33 -6
- package/CircularProgress/CircularProgress.mjs +33 -6
- package/ClickAwayListener/ClickAwayListener.js +3 -6
- package/ClickAwayListener/ClickAwayListener.mjs +3 -6
- package/Dialog/Dialog.js +11 -6
- package/Dialog/Dialog.mjs +11 -6
- package/Drawer/Drawer.js +18 -4
- package/Drawer/Drawer.mjs +18 -4
- package/Fab/Fab.js +7 -1
- package/Fab/Fab.mjs +7 -1
- package/FilledInput/FilledInput.d.mts +4 -0
- package/FilledInput/FilledInput.d.ts +4 -0
- package/FilledInput/FilledInput.js +18 -20
- package/FilledInput/FilledInput.mjs +18 -20
- 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/IconButton/IconButton.js +1 -8
- package/IconButton/IconButton.mjs +1 -8
- package/Input/Input.d.mts +4 -0
- package/Input/Input.d.ts +4 -0
- package/Input/Input.js +6 -0
- package/Input/Input.mjs +6 -0
- package/InputBase/InputBase.d.mts +2 -1
- package/InputBase/InputBase.d.ts +2 -1
- package/InputBase/InputBase.js +50 -15
- package/InputBase/InputBase.mjs +50 -15
- package/InputLabel/InputLabel.js +5 -8
- package/InputLabel/InputLabel.mjs +5 -8
- package/LinearProgress/LinearProgress.d.mts +12 -2
- package/LinearProgress/LinearProgress.d.ts +12 -2
- package/LinearProgress/LinearProgress.js +42 -10
- package/LinearProgress/LinearProgress.mjs +42 -10
- package/List/List.js +2 -1
- package/List/List.mjs +2 -1
- package/ListItemButton/ListItemButton.js +7 -1
- package/ListItemButton/ListItemButton.mjs +7 -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/NativeSelect/NativeSelect.js +2 -5
- package/NativeSelect/NativeSelect.mjs +2 -5
- package/OutlinedInput/OutlinedInput.js +13 -23
- package/OutlinedInput/OutlinedInput.mjs +13 -23
- package/PigmentContainer/PigmentContainer.js +0 -1
- package/PigmentContainer/PigmentContainer.mjs +0 -1
- package/Popper/BasePopper.js +23 -1
- package/Popper/BasePopper.mjs +23 -1
- package/Select/Select.js +2 -5
- package/Select/Select.mjs +2 -5
- package/Select/SelectInput.js +164 -2
- package/Select/SelectInput.mjs +164 -2
- package/Slide/Slide.js +48 -26
- package/Slide/Slide.mjs +49 -27
- package/Slider/Slider.js +10 -1
- package/Slider/Slider.mjs +10 -1
- package/Slider/useSlider.js +3 -2
- package/Slider/useSlider.mjs +3 -2
- package/SwipeableDrawer/SwipeableDrawer.js +7 -3
- package/SwipeableDrawer/SwipeableDrawer.mjs +7 -3
- package/Switch/Switch.js +7 -6
- package/Switch/Switch.mjs +7 -6
- package/Tabs/ScrollbarSize.js +2 -1
- package/Tabs/ScrollbarSize.mjs +2 -1
- package/Tabs/Tabs.js +2 -1
- package/Tabs/Tabs.mjs +2 -1
- package/Tooltip/Tooltip.js +26 -108
- package/Tooltip/Tooltip.mjs +26 -108
- package/Unstable_TrapFocus/FocusTrap.js +18 -14
- package/Unstable_TrapFocus/FocusTrap.mjs +18 -14
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +49 -49
- package/styles/responsiveFontSizes.js +19 -8
- package/styles/responsiveFontSizes.mjs +19 -8
- package/styles/useThemeProps.d.mts +3 -3
- package/styles/useThemeProps.d.ts +3 -3
- package/transitions/utils.d.mts +17 -0
- package/transitions/utils.d.ts +17 -0
- package/transitions/utils.js +64 -0
- package/transitions/utils.mjs +63 -0
- package/useAutocomplete/useAutocomplete.d.mts +4 -5
- package/useAutocomplete/useAutocomplete.d.ts +4 -5
- package/useAutocomplete/useAutocomplete.js +166 -53
- package/useAutocomplete/useAutocomplete.mjs +166 -53
- 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
|
@@ -5,8 +5,7 @@ import clsx from 'clsx';
|
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import composeClasses from '@mui/utils/composeClasses';
|
|
7
7
|
import NativeSelectInput from "./NativeSelectInput.mjs";
|
|
8
|
-
import
|
|
9
|
-
import useFormControl from "../FormControl/useFormControl.mjs";
|
|
8
|
+
import { useFormControlState } from "../FormControl/useFormControl.mjs";
|
|
10
9
|
import ArrowDropDownIcon from "../internal/svg-icons/ArrowDropDown.mjs";
|
|
11
10
|
import Input from "../Input/index.mjs";
|
|
12
11
|
import { useDefaultProps } from "../DefaultPropsProvider/index.mjs";
|
|
@@ -40,10 +39,8 @@ const NativeSelect = /*#__PURE__*/React.forwardRef(function NativeSelect(inProps
|
|
|
40
39
|
variant,
|
|
41
40
|
...other
|
|
42
41
|
} = props;
|
|
43
|
-
const
|
|
44
|
-
const fcs = formControlState({
|
|
42
|
+
const [fcs] = useFormControlState({
|
|
45
43
|
props,
|
|
46
|
-
muiFormControl,
|
|
47
44
|
states: ['variant']
|
|
48
45
|
});
|
|
49
46
|
const ownerState = {
|
|
@@ -12,8 +12,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
12
12
|
var _refType = _interopRequireDefault(require("@mui/utils/refType"));
|
|
13
13
|
var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
|
|
14
14
|
var _NotchedOutline = _interopRequireDefault(require("./NotchedOutline"));
|
|
15
|
-
var _useFormControl =
|
|
16
|
-
var _formControlState = _interopRequireDefault(require("../FormControl/formControlState"));
|
|
15
|
+
var _useFormControl = require("../FormControl/useFormControl");
|
|
17
16
|
var _rootShouldForwardProp = _interopRequireDefault(require("../styles/rootShouldForwardProp"));
|
|
18
17
|
var _zeroStyled = require("../zero-styled");
|
|
19
18
|
var _memoTheme = _interopRequireDefault(require("../utils/memoTheme"));
|
|
@@ -134,26 +133,19 @@ const OutlinedInputInput = (0, _zeroStyled.styled)(_InputBase.InputBaseInput, {
|
|
|
134
133
|
theme
|
|
135
134
|
}) => ({
|
|
136
135
|
padding: '16.5px 14px',
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
'&:-webkit-autofill': {
|
|
137
|
+
...(!theme.vars && {
|
|
139
138
|
WebkitBoxShadow: theme.palette.mode === 'light' ? null : '0 0 0 100px #266798 inset',
|
|
140
139
|
WebkitTextFillColor: theme.palette.mode === 'light' ? null : '#fff',
|
|
141
|
-
caretColor: theme.palette.mode === 'light' ? null : '#fff'
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
'&:-webkit-autofill': {
|
|
151
|
-
WebkitBoxShadow: '0 0 0 100px #266798 inset',
|
|
152
|
-
WebkitTextFillColor: '#fff',
|
|
153
|
-
caretColor: '#fff'
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}),
|
|
140
|
+
caretColor: theme.palette.mode === 'light' ? null : '#fff'
|
|
141
|
+
}),
|
|
142
|
+
borderRadius: 'inherit',
|
|
143
|
+
...(theme.vars && theme.applyStyles('dark', {
|
|
144
|
+
WebkitBoxShadow: '0 0 0 100px #266798 inset',
|
|
145
|
+
WebkitTextFillColor: '#fff',
|
|
146
|
+
caretColor: '#fff'
|
|
147
|
+
}))
|
|
148
|
+
},
|
|
157
149
|
variants: [{
|
|
158
150
|
props: {
|
|
159
151
|
size: 'small'
|
|
@@ -201,10 +193,8 @@ const OutlinedInput = /*#__PURE__*/React.forwardRef(function OutlinedInput(inPro
|
|
|
201
193
|
...other
|
|
202
194
|
} = props;
|
|
203
195
|
const classes = useUtilityClasses(props);
|
|
204
|
-
const muiFormControl = (0, _useFormControl.
|
|
205
|
-
const fcs = (0, _formControlState.default)({
|
|
196
|
+
const [fcs, muiFormControl] = (0, _useFormControl.useFormControlState)({
|
|
206
197
|
props,
|
|
207
|
-
muiFormControl,
|
|
208
198
|
states: ['color', 'disabled', 'error', 'focused', 'hiddenLabel', 'size', 'required']
|
|
209
199
|
});
|
|
210
200
|
const ownerState = {
|
|
@@ -5,8 +5,7 @@ import PropTypes from 'prop-types';
|
|
|
5
5
|
import refType from '@mui/utils/refType';
|
|
6
6
|
import composeClasses from '@mui/utils/composeClasses';
|
|
7
7
|
import NotchedOutline from "./NotchedOutline.mjs";
|
|
8
|
-
import
|
|
9
|
-
import formControlState from "../FormControl/formControlState.mjs";
|
|
8
|
+
import { useFormControlState } from "../FormControl/useFormControl.mjs";
|
|
10
9
|
import rootShouldForwardProp from "../styles/rootShouldForwardProp.mjs";
|
|
11
10
|
import { styled } from "../zero-styled/index.mjs";
|
|
12
11
|
import memoTheme from "../utils/memoTheme.mjs";
|
|
@@ -127,26 +126,19 @@ const OutlinedInputInput = styled(InputBaseInput, {
|
|
|
127
126
|
theme
|
|
128
127
|
}) => ({
|
|
129
128
|
padding: '16.5px 14px',
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
'&:-webkit-autofill': {
|
|
130
|
+
...(!theme.vars && {
|
|
132
131
|
WebkitBoxShadow: theme.palette.mode === 'light' ? null : '0 0 0 100px #266798 inset',
|
|
133
132
|
WebkitTextFillColor: theme.palette.mode === 'light' ? null : '#fff',
|
|
134
|
-
caretColor: theme.palette.mode === 'light' ? null : '#fff'
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
'&:-webkit-autofill': {
|
|
144
|
-
WebkitBoxShadow: '0 0 0 100px #266798 inset',
|
|
145
|
-
WebkitTextFillColor: '#fff',
|
|
146
|
-
caretColor: '#fff'
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}),
|
|
133
|
+
caretColor: theme.palette.mode === 'light' ? null : '#fff'
|
|
134
|
+
}),
|
|
135
|
+
borderRadius: 'inherit',
|
|
136
|
+
...(theme.vars && theme.applyStyles('dark', {
|
|
137
|
+
WebkitBoxShadow: '0 0 0 100px #266798 inset',
|
|
138
|
+
WebkitTextFillColor: '#fff',
|
|
139
|
+
caretColor: '#fff'
|
|
140
|
+
}))
|
|
141
|
+
},
|
|
150
142
|
variants: [{
|
|
151
143
|
props: {
|
|
152
144
|
size: 'small'
|
|
@@ -194,10 +186,8 @@ const OutlinedInput = /*#__PURE__*/React.forwardRef(function OutlinedInput(inPro
|
|
|
194
186
|
...other
|
|
195
187
|
} = props;
|
|
196
188
|
const classes = useUtilityClasses(props);
|
|
197
|
-
const muiFormControl =
|
|
198
|
-
const fcs = formControlState({
|
|
189
|
+
const [fcs, muiFormControl] = useFormControlState({
|
|
199
190
|
props,
|
|
200
|
-
muiFormControl,
|
|
201
191
|
states: ['color', 'disabled', 'error', 'focused', 'hiddenLabel', 'size', 'required']
|
|
202
192
|
});
|
|
203
193
|
const ownerState = {
|
package/Popper/BasePopper.js
CHANGED
|
@@ -150,8 +150,30 @@ const PopperTooltip = /*#__PURE__*/React.forwardRef(function PopperTooltip(props
|
|
|
150
150
|
modifiers: popperModifiers
|
|
151
151
|
});
|
|
152
152
|
handlePopperRefRef.current(popper);
|
|
153
|
+
const popperElement = tooltipRef.current;
|
|
153
154
|
return () => {
|
|
154
|
-
popper.destroy()
|
|
155
|
+
// popper.destroy() clears all inline positioning via the applyStyles
|
|
156
|
+
// modifier cleanup, which causes the element to jump to its static
|
|
157
|
+
// position. Snapshot and restore only the positioning properties so the
|
|
158
|
+
// element stays in place during the destroy/recreate gap (prevents scroll
|
|
159
|
+
// jumps when a child focuses between the two).
|
|
160
|
+
// https://github.com/mui/mui-x/issues/21839
|
|
161
|
+
if (popperElement) {
|
|
162
|
+
const {
|
|
163
|
+
style
|
|
164
|
+
} = popperElement;
|
|
165
|
+
const position = style.position;
|
|
166
|
+
const top = style.top;
|
|
167
|
+
const left = style.left;
|
|
168
|
+
const transform = style.transform;
|
|
169
|
+
popper.destroy();
|
|
170
|
+
style.position = position;
|
|
171
|
+
style.top = top;
|
|
172
|
+
style.left = left;
|
|
173
|
+
style.transform = transform;
|
|
174
|
+
} else {
|
|
175
|
+
popper.destroy();
|
|
176
|
+
}
|
|
155
177
|
handlePopperRefRef.current(null);
|
|
156
178
|
};
|
|
157
179
|
}, [resolvedAnchorElement, disablePortal, modifiers, open, popperOptions, rtlPlacement]);
|
package/Popper/BasePopper.mjs
CHANGED
|
@@ -143,8 +143,30 @@ const PopperTooltip = /*#__PURE__*/React.forwardRef(function PopperTooltip(props
|
|
|
143
143
|
modifiers: popperModifiers
|
|
144
144
|
});
|
|
145
145
|
handlePopperRefRef.current(popper);
|
|
146
|
+
const popperElement = tooltipRef.current;
|
|
146
147
|
return () => {
|
|
147
|
-
popper.destroy()
|
|
148
|
+
// popper.destroy() clears all inline positioning via the applyStyles
|
|
149
|
+
// modifier cleanup, which causes the element to jump to its static
|
|
150
|
+
// position. Snapshot and restore only the positioning properties so the
|
|
151
|
+
// element stays in place during the destroy/recreate gap (prevents scroll
|
|
152
|
+
// jumps when a child focuses between the two).
|
|
153
|
+
// https://github.com/mui/mui-x/issues/21839
|
|
154
|
+
if (popperElement) {
|
|
155
|
+
const {
|
|
156
|
+
style
|
|
157
|
+
} = popperElement;
|
|
158
|
+
const position = style.position;
|
|
159
|
+
const top = style.top;
|
|
160
|
+
const left = style.left;
|
|
161
|
+
const transform = style.transform;
|
|
162
|
+
popper.destroy();
|
|
163
|
+
style.position = position;
|
|
164
|
+
style.top = top;
|
|
165
|
+
style.left = left;
|
|
166
|
+
style.transform = transform;
|
|
167
|
+
} else {
|
|
168
|
+
popper.destroy();
|
|
169
|
+
}
|
|
148
170
|
handlePopperRefRef.current(null);
|
|
149
171
|
};
|
|
150
172
|
}, [resolvedAnchorElement, disablePortal, modifiers, open, popperOptions, rtlPlacement]);
|
package/Select/Select.js
CHANGED
|
@@ -14,8 +14,7 @@ var _deepmerge = _interopRequireDefault(require("@mui/utils/deepmerge"));
|
|
|
14
14
|
var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
|
|
15
15
|
var _getReactElementRef = _interopRequireDefault(require("@mui/utils/getReactElementRef"));
|
|
16
16
|
var _SelectInput = _interopRequireDefault(require("./SelectInput"));
|
|
17
|
-
var
|
|
18
|
-
var _useFormControl = _interopRequireDefault(require("../FormControl/useFormControl"));
|
|
17
|
+
var _useFormControl = require("../FormControl/useFormControl");
|
|
19
18
|
var _ArrowDropDown = _interopRequireDefault(require("../internal/svg-icons/ArrowDropDown"));
|
|
20
19
|
var _Input = _interopRequireDefault(require("../Input"));
|
|
21
20
|
var _NativeSelectInput = _interopRequireDefault(require("../NativeSelect/NativeSelectInput"));
|
|
@@ -78,10 +77,8 @@ const Select = /*#__PURE__*/React.forwardRef(function Select(inProps, ref) {
|
|
|
78
77
|
...other
|
|
79
78
|
} = props;
|
|
80
79
|
const inputComponent = native ? _NativeSelectInput.default : _SelectInput.default;
|
|
81
|
-
const
|
|
82
|
-
const fcs = (0, _formControlState.default)({
|
|
80
|
+
const [fcs] = (0, _useFormControl.useFormControlState)({
|
|
83
81
|
props,
|
|
84
|
-
muiFormControl,
|
|
85
82
|
states: ['variant', 'error']
|
|
86
83
|
});
|
|
87
84
|
const variant = fcs.variant || variantProp;
|
package/Select/Select.mjs
CHANGED
|
@@ -7,8 +7,7 @@ import deepmerge from '@mui/utils/deepmerge';
|
|
|
7
7
|
import composeClasses from '@mui/utils/composeClasses';
|
|
8
8
|
import getReactElementRef from '@mui/utils/getReactElementRef';
|
|
9
9
|
import SelectInput from "./SelectInput.mjs";
|
|
10
|
-
import
|
|
11
|
-
import useFormControl from "../FormControl/useFormControl.mjs";
|
|
10
|
+
import { useFormControlState } from "../FormControl/useFormControl.mjs";
|
|
12
11
|
import ArrowDropDownIcon from "../internal/svg-icons/ArrowDropDown.mjs";
|
|
13
12
|
import Input from "../Input/index.mjs";
|
|
14
13
|
import NativeSelectInput from "../NativeSelect/NativeSelectInput.mjs";
|
|
@@ -71,10 +70,8 @@ const Select = /*#__PURE__*/React.forwardRef(function Select(inProps, ref) {
|
|
|
71
70
|
...other
|
|
72
71
|
} = props;
|
|
73
72
|
const inputComponent = native ? NativeSelectInput : SelectInput;
|
|
74
|
-
const
|
|
75
|
-
const fcs = formControlState({
|
|
73
|
+
const [fcs] = useFormControlState({
|
|
76
74
|
props,
|
|
77
|
-
muiFormControl,
|
|
78
75
|
states: ['variant', 'error']
|
|
79
76
|
});
|
|
80
77
|
const variant = fcs.variant || variantProp;
|
package/Select/SelectInput.js
CHANGED
|
@@ -15,12 +15,15 @@ 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"));
|
|
@@ -28,6 +31,37 @@ var _utils2 = require("./utils");
|
|
|
28
31
|
var _SelectFocusSourceContext = require("./utils/SelectFocusSourceContext");
|
|
29
32
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
30
33
|
var _span;
|
|
34
|
+
const OPENING_MOUSE_UP_BOUNDARY_OFFSET = 2;
|
|
35
|
+
// The initial mouseup may land on an item when the menu opens over the trigger.
|
|
36
|
+
const SELECTED_MOUSE_UP_DELAY = 400;
|
|
37
|
+
const UNSELECTED_MOUSE_UP_DELAY = 200;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns true when a native mouse event should be treated as happening inside
|
|
41
|
+
* the element, even if a portal or backdrop retargeted the event away from it.
|
|
42
|
+
*
|
|
43
|
+
* Select uses this for the opening mouseup: when the menu opens over the
|
|
44
|
+
* trigger, the release can target the backdrop or portaled menu even though the
|
|
45
|
+
* pointer is still inside the trigger or menu bounds.
|
|
46
|
+
*/
|
|
47
|
+
function isMouseEventInsideElement(event, element) {
|
|
48
|
+
if (!element) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const eventPath = event.composedPath();
|
|
52
|
+
if (eventPath.includes(element)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (event.target?.nodeType && element.contains(event.target)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
const rect = element.getBoundingClientRect();
|
|
59
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
60
|
+
// Hidden or transition-mounted elements do not have useful bounds to hit-test.
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
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;
|
|
64
|
+
}
|
|
31
65
|
const SelectSelect = (0, _zeroStyled.styled)(_NativeSelectInput.StyledSelectSelect, {
|
|
32
66
|
name: 'MuiSelect',
|
|
33
67
|
slot: 'Select',
|
|
@@ -154,6 +188,17 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
154
188
|
});
|
|
155
189
|
const inputRef = React.useRef(null);
|
|
156
190
|
const displayRef = React.useRef(null);
|
|
191
|
+
const paperRef = React.useRef(null);
|
|
192
|
+
const openRef = React.useRef(false);
|
|
193
|
+
const hasSelectedItemInListRef = React.useRef(false);
|
|
194
|
+
const openingMouseUpListenerCleanupRef = React.useRef(null);
|
|
195
|
+
const didPointerDownOnItemRef = React.useRef(false);
|
|
196
|
+
const selectionRef = React.useRef({
|
|
197
|
+
allowSelectedMouseUp: false,
|
|
198
|
+
allowUnselectedMouseUp: false
|
|
199
|
+
});
|
|
200
|
+
const selectedMouseUpTimer = (0, _useTimeout.default)();
|
|
201
|
+
const unselectedMouseUpTimer = (0, _useTimeout.default)();
|
|
157
202
|
const [displayNode, setDisplayNode] = React.useState(null);
|
|
158
203
|
const {
|
|
159
204
|
current: isOpenControlled
|
|
@@ -176,6 +221,42 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
176
221
|
value
|
|
177
222
|
}), [value]);
|
|
178
223
|
const open = displayNode !== null && openState;
|
|
224
|
+
(0, _useEnhancedEffect.default)(() => {
|
|
225
|
+
openRef.current = open;
|
|
226
|
+
}, [open]);
|
|
227
|
+
const clearSelectionTimers = React.useCallback(() => {
|
|
228
|
+
selectedMouseUpTimer.clear();
|
|
229
|
+
unselectedMouseUpTimer.clear();
|
|
230
|
+
}, [selectedMouseUpTimer, unselectedMouseUpTimer]);
|
|
231
|
+
const resetMouseUpSelection = React.useCallback(() => {
|
|
232
|
+
clearSelectionTimers();
|
|
233
|
+
didPointerDownOnItemRef.current = false;
|
|
234
|
+
selectionRef.current = {
|
|
235
|
+
allowSelectedMouseUp: false,
|
|
236
|
+
allowUnselectedMouseUp: false
|
|
237
|
+
};
|
|
238
|
+
}, [clearSelectionTimers]);
|
|
239
|
+
const clearOpeningMouseUpListener = React.useCallback(() => {
|
|
240
|
+
if (openingMouseUpListenerCleanupRef.current) {
|
|
241
|
+
openingMouseUpListenerCleanupRef.current();
|
|
242
|
+
openingMouseUpListenerCleanupRef.current = null;
|
|
243
|
+
}
|
|
244
|
+
}, []);
|
|
245
|
+
React.useEffect(() => {
|
|
246
|
+
if (!open) {
|
|
247
|
+
resetMouseUpSelection();
|
|
248
|
+
clearOpeningMouseUpListener();
|
|
249
|
+
}
|
|
250
|
+
}, [open, resetMouseUpSelection, clearOpeningMouseUpListener]);
|
|
251
|
+
|
|
252
|
+
// Keep unmount cleanup separate from the `open` effect. Effect cleanups also run
|
|
253
|
+
// before the next effect, which would clear the opening mouseup listener while opening.
|
|
254
|
+
React.useEffect(() => {
|
|
255
|
+
return () => {
|
|
256
|
+
resetMouseUpSelection();
|
|
257
|
+
clearOpeningMouseUpListener();
|
|
258
|
+
};
|
|
259
|
+
}, [resetMouseUpSelection, clearOpeningMouseUpListener]);
|
|
179
260
|
React.useEffect(() => {
|
|
180
261
|
if (!open || !anchorElement || autoWidth) {
|
|
181
262
|
return undefined;
|
|
@@ -226,7 +307,11 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
226
307
|
}
|
|
227
308
|
return undefined;
|
|
228
309
|
}, [labelId]);
|
|
229
|
-
const update = (openParam, event) => {
|
|
310
|
+
const update = (0, _useEventCallback.default)((openParam, event) => {
|
|
311
|
+
if (!openParam) {
|
|
312
|
+
resetMouseUpSelection();
|
|
313
|
+
clearOpeningMouseUpListener();
|
|
314
|
+
}
|
|
230
315
|
if (openParam) {
|
|
231
316
|
setOpenInteractionType((0, _utils2.getOpenInteractionType)(event));
|
|
232
317
|
if (onOpen) {
|
|
@@ -239,9 +324,33 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
239
324
|
}
|
|
240
325
|
}
|
|
241
326
|
if (!isOpenControlled) {
|
|
327
|
+
openRef.current = openParam;
|
|
242
328
|
setMenuMinWidthState(autoWidth ? null : anchorElement.clientWidth);
|
|
243
329
|
setOpenState(openParam);
|
|
244
330
|
}
|
|
331
|
+
});
|
|
332
|
+
const scheduleMouseUpSelection = () => {
|
|
333
|
+
resetMouseUpSelection();
|
|
334
|
+
|
|
335
|
+
// When there is no selected item in the list, a mousedown
|
|
336
|
+
// on the trigger followed by a quick mouseup over the first option can accidentally select
|
|
337
|
+
// within 200ms. Delay unselected mouseup to match the safer 400ms window.
|
|
338
|
+
if (!hasSelectedItemInListRef.current) {
|
|
339
|
+
selectedMouseUpTimer.start(SELECTED_MOUSE_UP_DELAY, () => {
|
|
340
|
+
selectionRef.current.allowSelectedMouseUp = true;
|
|
341
|
+
selectionRef.current.allowUnselectedMouseUp = true;
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
// mousedown -> move to unselected item -> mouseup should not select within 200ms.
|
|
345
|
+
unselectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
|
|
346
|
+
selectionRef.current.allowUnselectedMouseUp = true;
|
|
347
|
+
|
|
348
|
+
// mousedown -> mouseup on selected item should not select within 400ms.
|
|
349
|
+
selectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
|
|
350
|
+
selectionRef.current.allowSelectedMouseUp = true;
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
}
|
|
245
354
|
};
|
|
246
355
|
const handleMouseDown = event => {
|
|
247
356
|
onMouseDown?.(event);
|
|
@@ -252,6 +361,29 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
252
361
|
// Hijack the default focus behavior.
|
|
253
362
|
event.preventDefault();
|
|
254
363
|
displayRef.current.focus();
|
|
364
|
+
const doc = (0, _ownerDocument.default)(event.currentTarget);
|
|
365
|
+
scheduleMouseUpSelection();
|
|
366
|
+
clearOpeningMouseUpListener();
|
|
367
|
+
const handleMouseUp = mouseEvent => {
|
|
368
|
+
openingMouseUpListenerCleanupRef.current = null;
|
|
369
|
+
if (!displayRef.current) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (isMouseEventInsideElement(mouseEvent, displayRef.current) || isMouseEventInsideElement(mouseEvent, paperRef.current)) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (!openRef.current && isOpenControlled) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
update(false, mouseEvent);
|
|
379
|
+
};
|
|
380
|
+
doc.addEventListener('mouseup', handleMouseUp, {
|
|
381
|
+
capture: true,
|
|
382
|
+
once: true
|
|
383
|
+
});
|
|
384
|
+
openingMouseUpListenerCleanupRef.current = () => {
|
|
385
|
+
doc.removeEventListener('mouseup', handleMouseUp, true);
|
|
386
|
+
};
|
|
255
387
|
update(true, event);
|
|
256
388
|
};
|
|
257
389
|
const handleClose = event => {
|
|
@@ -271,6 +403,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
271
403
|
}
|
|
272
404
|
};
|
|
273
405
|
const handleItemClick = child => event => {
|
|
406
|
+
didPointerDownOnItemRef.current = false;
|
|
274
407
|
let newValue;
|
|
275
408
|
|
|
276
409
|
// We use the tabindex attribute to signal the available options.
|
|
@@ -314,6 +447,19 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
314
447
|
update(false, event);
|
|
315
448
|
}
|
|
316
449
|
};
|
|
450
|
+
const handleItemMouseUp = (child, selected) => event => {
|
|
451
|
+
child.props.onMouseUp?.(event);
|
|
452
|
+
if (didPointerDownOnItemRef.current) {
|
|
453
|
+
didPointerDownOnItemRef.current = false;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const disallowSelectedMouseUp = !selectionRef.current.allowSelectedMouseUp && selected;
|
|
457
|
+
const disallowUnselectedMouseUp = !selectionRef.current.allowUnselectedMouseUp && !selected;
|
|
458
|
+
if (disallowSelectedMouseUp || disallowUnselectedMouseUp) {
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
event.currentTarget.click();
|
|
462
|
+
};
|
|
317
463
|
const handleKeyDown = event => {
|
|
318
464
|
if (!readOnly) {
|
|
319
465
|
const validKeys = [' ', 'ArrowUp', 'ArrowDown',
|
|
@@ -387,7 +533,16 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
387
533
|
}
|
|
388
534
|
return /*#__PURE__*/React.cloneElement(child, {
|
|
389
535
|
'aria-selected': selected ? 'true' : 'false',
|
|
536
|
+
onMouseDown: event => {
|
|
537
|
+
didPointerDownOnItemRef.current = true;
|
|
538
|
+
child.props.onMouseDown?.(event);
|
|
539
|
+
},
|
|
540
|
+
onPointerDown: event => {
|
|
541
|
+
didPointerDownOnItemRef.current = true;
|
|
542
|
+
child.props.onPointerDown?.(event);
|
|
543
|
+
},
|
|
390
544
|
onClick: handleItemClick(child),
|
|
545
|
+
onMouseUp: handleItemMouseUp(child, selected),
|
|
391
546
|
onKeyUp: event => {
|
|
392
547
|
if (event.key === ' ') {
|
|
393
548
|
// otherwise our MenuItems dispatches a click event
|
|
@@ -406,6 +561,11 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
406
561
|
'data-value': child.props.value // Instead, we provide it as a data attribute.
|
|
407
562
|
});
|
|
408
563
|
});
|
|
564
|
+
|
|
565
|
+
// Keep the opening mouseup guard current without mutating refs during render.
|
|
566
|
+
(0, _useEnhancedEffect.default)(() => {
|
|
567
|
+
hasSelectedItemInListRef.current = foundMatch;
|
|
568
|
+
}, [foundMatch]);
|
|
409
569
|
if (process.env.NODE_ENV !== 'production') {
|
|
410
570
|
// TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
|
|
411
571
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -455,6 +615,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
455
615
|
};
|
|
456
616
|
const classes = useUtilityClasses(ownerState);
|
|
457
617
|
const menuPaperSlotProps = typeof MenuProps.slotProps?.paper === 'function' ? MenuProps.slotProps.paper(ownerState) : MenuProps.slotProps?.paper;
|
|
618
|
+
const handlePaperRef = (0, _useForkRef.default)(menuPaperSlotProps?.ref, paperRef);
|
|
458
619
|
const menuListSlotProps = typeof MenuProps.slotProps?.list === 'function' ? MenuProps.slotProps.list(ownerState) : MenuProps.slotProps?.list;
|
|
459
620
|
const listboxId = (0, _useId.default)();
|
|
460
621
|
const nativeInputId = (0, _useId.default)();
|
|
@@ -469,7 +630,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
469
630
|
"aria-expanded": open ? 'true' : 'false',
|
|
470
631
|
"aria-haspopup": "listbox",
|
|
471
632
|
"aria-label": ariaLabel,
|
|
472
|
-
"aria-labelledby":
|
|
633
|
+
"aria-labelledby": labelId,
|
|
473
634
|
"aria-describedby": ariaDescribedby,
|
|
474
635
|
"aria-required": required ? 'true' : undefined,
|
|
475
636
|
"aria-invalid": error ? 'true' : undefined,
|
|
@@ -536,6 +697,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
536
697
|
},
|
|
537
698
|
paper: {
|
|
538
699
|
...menuPaperSlotProps,
|
|
700
|
+
ref: handlePaperRef,
|
|
539
701
|
style: {
|
|
540
702
|
minWidth: menuMinWidth,
|
|
541
703
|
...menuPaperSlotProps?.style
|