@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
import contains from '@mui/utils/contains';
|
|
4
5
|
import setRef from '@mui/utils/setRef';
|
|
5
6
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
6
7
|
import useControlled from '@mui/utils/useControlled';
|
|
@@ -55,7 +56,7 @@ const defaultFilterOptions = createFilterOptions();
|
|
|
55
56
|
|
|
56
57
|
// Number of options to jump in list box when `Page Up` and `Page Down` keys are used.
|
|
57
58
|
const pageSize = 5;
|
|
58
|
-
const defaultIsActiveElementInListbox = listboxRef => listboxRef.current !== null && listboxRef.current.parentElement
|
|
59
|
+
const defaultIsActiveElementInListbox = listboxRef => listboxRef.current !== null && contains(listboxRef.current.parentElement, document.activeElement);
|
|
59
60
|
const defaultIsOptionEqualToValue = (option, value) => option === value;
|
|
60
61
|
const MULTIPLE_DEFAULT_VALUE = [];
|
|
61
62
|
function getInputValue(value, multiple, getOptionLabel, renderValue) {
|
|
@@ -107,6 +108,7 @@ function useAutocomplete(props) {
|
|
|
107
108
|
options,
|
|
108
109
|
readOnly = false,
|
|
109
110
|
renderValue,
|
|
111
|
+
resetHighlightOnMouseLeave = false,
|
|
110
112
|
selectOnFocus = !props.freeSolo,
|
|
111
113
|
value: valueProp
|
|
112
114
|
} = props;
|
|
@@ -127,12 +129,29 @@ function useAutocomplete(props) {
|
|
|
127
129
|
const firstFocus = React.useRef(true);
|
|
128
130
|
const inputRef = React.useRef(null);
|
|
129
131
|
const listboxRef = React.useRef(null);
|
|
132
|
+
// VoiceOver synthesises a spurious Backspace on the input after a chip
|
|
133
|
+
// deletion moves DOM focus back to it. This flag suppresses that one event.
|
|
134
|
+
const ignoreNextBackspaceRef = React.useRef(false);
|
|
130
135
|
const windowLostFocus = React.useRef(false);
|
|
131
136
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
132
137
|
const [focusedItem, setFocusedItem] = React.useState(-1);
|
|
133
138
|
const defaultHighlighted = autoHighlight ? 0 : -1;
|
|
134
139
|
const highlightedIndexRef = React.useRef(defaultHighlighted);
|
|
135
140
|
|
|
141
|
+
// Tracks how the current highlight was set:
|
|
142
|
+
// - 'keyboard' — arrow keys, Home/End, PageUp/PageDown
|
|
143
|
+
// - 'mouse' — handleOptionMouseMove
|
|
144
|
+
// - 'touch' — handleOptionTouchStart
|
|
145
|
+
// - null — programmatic (autoHighlight, value sync)
|
|
146
|
+
//
|
|
147
|
+
// This lets handleBlur and the Enter handler distinguish intentional
|
|
148
|
+
// interactions from incidental ones — e.g. autoSelect should not commit
|
|
149
|
+
// a highlight that came from a casual mouse hover.
|
|
150
|
+
/** @type {React.RefObject<AutocompleteHighlightChangeReason | null>} */
|
|
151
|
+
const highlightReasonRef = React.useRef(null);
|
|
152
|
+
const touchScrolledRef = React.useRef(false);
|
|
153
|
+
const isTouchRef = React.useRef(false);
|
|
154
|
+
|
|
136
155
|
// Calculate the initial inputValue on mount only.
|
|
137
156
|
// useRef ensures it doesn't update dynamically with defaultValue or value props.
|
|
138
157
|
const initialInputValue = React.useRef(getInputValue(defaultValue ?? valueProp, multiple, getOptionLabel)).current;
|
|
@@ -149,10 +168,12 @@ function useAutocomplete(props) {
|
|
|
149
168
|
});
|
|
150
169
|
const [focused, setFocused] = React.useState(false);
|
|
151
170
|
const resetInputValue = React.useCallback((event, newValue, reason) => {
|
|
152
|
-
//
|
|
153
|
-
//
|
|
171
|
+
// Retain the current `inputValue` when no new option is selected and `clearOnBlur` is false.
|
|
172
|
+
// In `multiple` mode, `newValue` is the next value array, so only length growth counts as a selection.
|
|
154
173
|
const isOptionSelected = multiple ? value.length < newValue.length : newValue !== null;
|
|
155
|
-
|
|
174
|
+
// A controlled single-value `freeSolo` reset to `null` should still clear the input.
|
|
175
|
+
const shouldClearOnReset = reason === 'reset' && freeSolo && !multiple && newValue === null;
|
|
176
|
+
if (!isOptionSelected && !clearOnBlur && !shouldClearOnReset) {
|
|
156
177
|
return;
|
|
157
178
|
}
|
|
158
179
|
const newInputValue = getInputValue(newValue, multiple, getOptionLabel, renderValue);
|
|
@@ -163,7 +184,7 @@ function useAutocomplete(props) {
|
|
|
163
184
|
if (onInputChange) {
|
|
164
185
|
onInputChange(event, newInputValue, reason);
|
|
165
186
|
}
|
|
166
|
-
}, [getOptionLabel, inputValue, multiple, onInputChange, setInputValueState, clearOnBlur, value, renderValue]);
|
|
187
|
+
}, [getOptionLabel, inputValue, multiple, onInputChange, setInputValueState, clearOnBlur, freeSolo, value, renderValue]);
|
|
167
188
|
const [open, setOpenState] = useControlled({
|
|
168
189
|
controlled: openProp,
|
|
169
190
|
default: false,
|
|
@@ -218,8 +239,10 @@ function useAutocomplete(props) {
|
|
|
218
239
|
return;
|
|
219
240
|
}
|
|
220
241
|
|
|
221
|
-
//
|
|
222
|
-
|
|
242
|
+
// In freeSolo mode, only reset the input after a real value change.
|
|
243
|
+
// Also prevent the initial default value of `null` from clearing controlled values.
|
|
244
|
+
const shouldSkipFreeSoloReset = freeSolo && (!valueChange || value == null && previousProps.value === undefined);
|
|
245
|
+
if (shouldSkipFreeSoloReset) {
|
|
223
246
|
return;
|
|
224
247
|
}
|
|
225
248
|
resetInputValue(null, value, 'reset');
|
|
@@ -270,12 +293,16 @@ function useAutocomplete(props) {
|
|
|
270
293
|
}
|
|
271
294
|
}
|
|
272
295
|
}
|
|
273
|
-
const
|
|
274
|
-
event,
|
|
296
|
+
const syncHighlightedIndexToDOM = useEventCallback(({
|
|
275
297
|
index,
|
|
276
|
-
reason
|
|
298
|
+
reason,
|
|
299
|
+
preserveScroll = false
|
|
277
300
|
}) => {
|
|
278
|
-
|
|
301
|
+
// React can clear refs before pending passive effects run during unmount.
|
|
302
|
+
// If both refs are gone, there is no DOM left to sync.
|
|
303
|
+
if (inputRef.current == null && listboxRef.current == null) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
279
306
|
|
|
280
307
|
// does the index exist?
|
|
281
308
|
if (index === -1) {
|
|
@@ -283,9 +310,6 @@ function useAutocomplete(props) {
|
|
|
283
310
|
} else {
|
|
284
311
|
inputRef.current.setAttribute('aria-activedescendant', `${id}-option-${index}`);
|
|
285
312
|
}
|
|
286
|
-
if (onHighlightChange && ['mouse', 'keyboard', 'touch'].includes(reason)) {
|
|
287
|
-
onHighlightChange(event, index === -1 ? null : filteredOptions[index], reason);
|
|
288
|
-
}
|
|
289
313
|
if (!listboxRef.current) {
|
|
290
314
|
return;
|
|
291
315
|
}
|
|
@@ -304,7 +328,9 @@ function useAutocomplete(props) {
|
|
|
304
328
|
return;
|
|
305
329
|
}
|
|
306
330
|
if (index === -1) {
|
|
307
|
-
|
|
331
|
+
if (!preserveScroll) {
|
|
332
|
+
listboxNode.scrollTop = 0;
|
|
333
|
+
}
|
|
308
334
|
return;
|
|
309
335
|
}
|
|
310
336
|
const option = listboxRef.current.querySelector(`[data-option-index="${index}"]`);
|
|
@@ -332,15 +358,46 @@ function useAutocomplete(props) {
|
|
|
332
358
|
}
|
|
333
359
|
}
|
|
334
360
|
});
|
|
361
|
+
const setHighlightedIndex = useEventCallback(({
|
|
362
|
+
event,
|
|
363
|
+
index,
|
|
364
|
+
reason,
|
|
365
|
+
preserveScroll = false
|
|
366
|
+
}) => {
|
|
367
|
+
highlightedIndexRef.current = index;
|
|
368
|
+
highlightReasonRef.current = reason ?? null;
|
|
369
|
+
if (onHighlightChange && ['mouse', 'keyboard', 'touch'].includes(reason)) {
|
|
370
|
+
onHighlightChange(event, index === -1 ? null : filteredOptions[index], reason);
|
|
371
|
+
}
|
|
372
|
+
syncHighlightedIndexToDOM({
|
|
373
|
+
index,
|
|
374
|
+
reason,
|
|
375
|
+
preserveScroll
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
const setHighlightedIndexFromSync = useEventCallback(({
|
|
379
|
+
index
|
|
380
|
+
}) => {
|
|
381
|
+
highlightedIndexRef.current = index;
|
|
382
|
+
syncHighlightedIndexToDOM({
|
|
383
|
+
index,
|
|
384
|
+
reason: highlightReasonRef.current
|
|
385
|
+
});
|
|
386
|
+
});
|
|
335
387
|
const changeHighlightedIndex = useEventCallback(({
|
|
336
388
|
event,
|
|
337
389
|
diff,
|
|
338
390
|
direction = 'next',
|
|
339
|
-
reason
|
|
391
|
+
reason,
|
|
392
|
+
preserveScroll
|
|
340
393
|
}) => {
|
|
341
394
|
if (!popupOpen) {
|
|
342
395
|
return;
|
|
343
396
|
}
|
|
397
|
+
if (reason === 'keyboard') {
|
|
398
|
+
touchScrolledRef.current = false;
|
|
399
|
+
isTouchRef.current = false;
|
|
400
|
+
}
|
|
344
401
|
const getNextIndex = () => {
|
|
345
402
|
const maxIndex = filteredOptions.length - 1;
|
|
346
403
|
if (diff === 'reset') {
|
|
@@ -377,7 +434,8 @@ function useAutocomplete(props) {
|
|
|
377
434
|
setHighlightedIndex({
|
|
378
435
|
index: nextIndex,
|
|
379
436
|
reason,
|
|
380
|
-
event
|
|
437
|
+
event,
|
|
438
|
+
preserveScroll
|
|
381
439
|
});
|
|
382
440
|
|
|
383
441
|
// Sync the content of the input with the highlighted option.
|
|
@@ -431,15 +489,24 @@ function useAutocomplete(props) {
|
|
|
431
489
|
// If it exists and the value and the inputValue haven't changed, just update its index, otherwise continue execution
|
|
432
490
|
const previousHighlightedOptionIndex = getPreviousHighlightedOptionIndex();
|
|
433
491
|
if (previousHighlightedOptionIndex !== -1) {
|
|
434
|
-
|
|
492
|
+
// Keep the original highlight reason while re-syncing the DOM state.
|
|
493
|
+
// The highlighted option still exists after the filteredOptions array changed
|
|
494
|
+
// (e.g. async fetch returns new options while the user is mid-navigation),
|
|
495
|
+
// so the original interaction reason (keyboard, mouse, etc.) still applies.
|
|
496
|
+
setHighlightedIndexFromSync({
|
|
497
|
+
index: previousHighlightedOptionIndex
|
|
498
|
+
});
|
|
435
499
|
return;
|
|
436
500
|
}
|
|
437
501
|
const valueItem = multiple ? value[0] : value;
|
|
438
502
|
|
|
439
503
|
// The popup is empty, reset
|
|
440
504
|
if (filteredOptions.length === 0 || valueItem == null) {
|
|
505
|
+
// Preserve scroll when new options are appended without changing the current filter.
|
|
506
|
+
const isAppendOnly = filteredOptionsChanged && previousProps.inputValue === inputValue && previousProps.filteredOptions?.length > 0 && filteredOptions.length > previousProps.filteredOptions.length && previousProps.filteredOptions.every((option, index) => getOptionLabel(option) === getOptionLabel(filteredOptions[index]));
|
|
441
507
|
changeHighlightedIndex({
|
|
442
|
-
diff: 'reset'
|
|
508
|
+
diff: 'reset',
|
|
509
|
+
preserveScroll: isAppendOnly
|
|
443
510
|
});
|
|
444
511
|
return;
|
|
445
512
|
}
|
|
@@ -451,8 +518,12 @@ function useAutocomplete(props) {
|
|
|
451
518
|
if (valueItem != null) {
|
|
452
519
|
const currentOption = filteredOptions[highlightedIndexRef.current];
|
|
453
520
|
|
|
454
|
-
// Keep the current
|
|
455
|
-
|
|
521
|
+
// Keep the current selected highlight while the popup stays open;
|
|
522
|
+
// on reopen, resync from the selected value.
|
|
523
|
+
if (multiple && currentOption && value.findIndex(val => isOptionEqualToValue(currentOption, val)) !== -1 && previousProps.filteredOptions?.length > 0) {
|
|
524
|
+
setHighlightedIndexFromSync({
|
|
525
|
+
index: highlightedIndexRef.current
|
|
526
|
+
});
|
|
456
527
|
return;
|
|
457
528
|
}
|
|
458
529
|
const itemIndex = filteredOptions.findIndex(optionItem => isOptionEqualToValue(optionItem, valueItem));
|
|
@@ -487,7 +558,7 @@ function useAutocomplete(props) {
|
|
|
487
558
|
filteredOptions.length,
|
|
488
559
|
// Don't sync the highlighted index with the value when multiple
|
|
489
560
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
490
|
-
multiple ? false : value, changeHighlightedIndex, setHighlightedIndex, popupOpen, inputValue, multiple]);
|
|
561
|
+
multiple ? false : value, changeHighlightedIndex, setHighlightedIndex, setHighlightedIndexFromSync, popupOpen, inputValue, multiple]);
|
|
491
562
|
const handleListboxRef = useEventCallback(node => {
|
|
492
563
|
setRef(listboxRef, node);
|
|
493
564
|
if (!node) {
|
|
@@ -533,6 +604,7 @@ function useAutocomplete(props) {
|
|
|
533
604
|
}
|
|
534
605
|
setOpenState(true);
|
|
535
606
|
setInputPristine(true);
|
|
607
|
+
isTouchRef.current = false;
|
|
536
608
|
if (onOpen) {
|
|
537
609
|
onOpen(event);
|
|
538
610
|
}
|
|
@@ -542,6 +614,8 @@ function useAutocomplete(props) {
|
|
|
542
614
|
return;
|
|
543
615
|
}
|
|
544
616
|
setOpenState(false);
|
|
617
|
+
touchScrolledRef.current = false;
|
|
618
|
+
highlightReasonRef.current = null;
|
|
545
619
|
if (onClose) {
|
|
546
620
|
onClose(event, reason);
|
|
547
621
|
}
|
|
@@ -559,7 +633,6 @@ function useAutocomplete(props) {
|
|
|
559
633
|
}
|
|
560
634
|
setValueState(newValue);
|
|
561
635
|
};
|
|
562
|
-
const isTouch = React.useRef(false);
|
|
563
636
|
const selectNewValue = (event, option, reasonProp = 'selectOption', origin = 'options') => {
|
|
564
637
|
let reason = reasonProp;
|
|
565
638
|
let newValue = option;
|
|
@@ -586,7 +659,7 @@ function useAutocomplete(props) {
|
|
|
586
659
|
if (!disableCloseOnSelect && (!event || !event.ctrlKey && !event.metaKey)) {
|
|
587
660
|
handleClose(event, reason);
|
|
588
661
|
}
|
|
589
|
-
if (blurOnSelect === true || blurOnSelect === 'touch' &&
|
|
662
|
+
if (blurOnSelect === true || blurOnSelect === 'touch' && isTouchRef.current || blurOnSelect === 'mouse' && !isTouchRef.current) {
|
|
590
663
|
inputRef.current.blur();
|
|
591
664
|
}
|
|
592
665
|
};
|
|
@@ -644,7 +717,6 @@ function useAutocomplete(props) {
|
|
|
644
717
|
focusItem(nextItem);
|
|
645
718
|
};
|
|
646
719
|
const handleClear = event => {
|
|
647
|
-
ignoreFocus.current = true;
|
|
648
720
|
setInputValueState('');
|
|
649
721
|
if (onInputChange) {
|
|
650
722
|
onInputChange(event, '', 'clear');
|
|
@@ -772,29 +844,47 @@ function useAutocomplete(props) {
|
|
|
772
844
|
}
|
|
773
845
|
break;
|
|
774
846
|
case 'Enter':
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
847
|
+
{
|
|
848
|
+
// In freeSolo, only select the highlighted option if the user hasn't
|
|
849
|
+
// typed new text (inputPristine) or explicitly interacted with an option
|
|
850
|
+
// (keyboard, mouse, or touch — any non-null reason). This lets typed
|
|
851
|
+
// text win over a programmatic highlight (reason=null, e.g. from
|
|
852
|
+
// syncHighlightedIndex matching a previous value) while still honoring
|
|
853
|
+
// deliberate user interactions like hovering a suggestion then pressing Enter.
|
|
854
|
+
const shouldSelectHighlighted = !freeSolo || inputPristine || highlightReasonRef.current !== null;
|
|
855
|
+
if (highlightedIndexRef.current !== -1 && popupOpen && shouldSelectHighlighted &&
|
|
856
|
+
// After a touch-scroll the highlight is stale (the user scrolled
|
|
857
|
+
// past it), so skip selection until the next deliberate interaction.
|
|
858
|
+
!touchScrolledRef.current) {
|
|
859
|
+
const option = filteredOptions[highlightedIndexRef.current];
|
|
860
|
+
const disabled = getOptionDisabled ? getOptionDisabled(option) : false;
|
|
778
861
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
862
|
+
// Avoid early form validation, let the end-users continue filling the form.
|
|
863
|
+
event.preventDefault();
|
|
864
|
+
if (disabled) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
selectNewValue(event, option, 'selectOption');
|
|
785
868
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
869
|
+
// Move the selection to the end.
|
|
870
|
+
if (autoComplete) {
|
|
871
|
+
inputRef.current.setSelectionRange(inputRef.current.value.length, inputRef.current.value.length);
|
|
872
|
+
}
|
|
873
|
+
} else if (freeSolo && inputValue !== '' && inputValueIsSelectedValue === false) {
|
|
874
|
+
if (multiple) {
|
|
875
|
+
// Allow people to add new values before they submit the form.
|
|
876
|
+
event.preventDefault();
|
|
877
|
+
}
|
|
878
|
+
selectNewValue(event, inputValue, 'createOption', 'freeSolo');
|
|
879
|
+
} else if (popupOpen && touchScrolledRef.current) {
|
|
880
|
+
// The highlight is stale from a touch-scroll - close without selecting.
|
|
793
881
|
event.preventDefault();
|
|
882
|
+
// This happens on Enter, but re-using "escape" as the closest `AutocompleteCloseReason`
|
|
883
|
+
// to avoid creating a new reason
|
|
884
|
+
handleClose(event, 'escape');
|
|
794
885
|
}
|
|
795
|
-
|
|
886
|
+
break;
|
|
796
887
|
}
|
|
797
|
-
break;
|
|
798
888
|
case 'Escape':
|
|
799
889
|
if (popupOpen) {
|
|
800
890
|
// Avoid Opera to exit fullscreen mode.
|
|
@@ -812,6 +902,10 @@ function useAutocomplete(props) {
|
|
|
812
902
|
break;
|
|
813
903
|
case 'Backspace':
|
|
814
904
|
// Remove the value on the left of the "cursor"
|
|
905
|
+
if (ignoreNextBackspaceRef.current) {
|
|
906
|
+
ignoreNextBackspaceRef.current = false;
|
|
907
|
+
break;
|
|
908
|
+
}
|
|
815
909
|
if (multiple && !readOnly && inputValue === '' && value.length > 0) {
|
|
816
910
|
const index = focusedItem === -1 ? value.length - 1 : focusedItem;
|
|
817
911
|
const newValue = value.slice();
|
|
@@ -819,6 +913,18 @@ function useAutocomplete(props) {
|
|
|
819
913
|
handleValue(event, newValue, 'removeOption', {
|
|
820
914
|
option: value[index]
|
|
821
915
|
});
|
|
916
|
+
if (focusedItem !== -1) {
|
|
917
|
+
// Suppress the spurious Backspace VoiceOver synthesises on the
|
|
918
|
+
// input after focus returns to it. Clear it shortly after
|
|
919
|
+
// deletion so a later real Backspace is not ignored if the
|
|
920
|
+
// synthetic follow-up event never arrives.
|
|
921
|
+
ignoreNextBackspaceRef.current = true;
|
|
922
|
+
setTimeout(() => {
|
|
923
|
+
if (ignoreNextBackspaceRef.current) {
|
|
924
|
+
ignoreNextBackspaceRef.current = false;
|
|
925
|
+
}
|
|
926
|
+
}, 0);
|
|
927
|
+
}
|
|
822
928
|
}
|
|
823
929
|
if (!multiple && renderValue && !readOnly && inputValue === '') {
|
|
824
930
|
handleValue(event, null, 'removeOption', {
|
|
@@ -872,7 +978,7 @@ function useAutocomplete(props) {
|
|
|
872
978
|
}
|
|
873
979
|
};
|
|
874
980
|
const handleBlur = event => {
|
|
875
|
-
// Ignore the event when using the scrollbar with
|
|
981
|
+
// Ignore the event when using the scrollbar with IE 11
|
|
876
982
|
if (unstable_isActiveElementInListbox(listboxRef)) {
|
|
877
983
|
inputRef.current.focus();
|
|
878
984
|
return;
|
|
@@ -880,7 +986,12 @@ function useAutocomplete(props) {
|
|
|
880
986
|
setFocused(false);
|
|
881
987
|
firstFocus.current = true;
|
|
882
988
|
ignoreFocus.current = false;
|
|
883
|
-
|
|
989
|
+
|
|
990
|
+
// Auto-select the highlighted option on blur, but only if the highlight
|
|
991
|
+
// came from keyboard navigation or was set programmatically (autoHighlight).
|
|
992
|
+
// Mouse hover and touch should not trigger selection — the user may have
|
|
993
|
+
// moved the pointer over an option without intending to commit to it.
|
|
994
|
+
if (autoSelect && highlightedIndexRef.current !== -1 && popupOpen && highlightReasonRef.current !== 'mouse' && highlightReasonRef.current !== 'touch') {
|
|
884
995
|
selectNewValue(event, filteredOptions[highlightedIndexRef.current], 'blur');
|
|
885
996
|
} else if (autoSelect && freeSolo && inputValue !== '') {
|
|
886
997
|
selectNewValue(event, inputValue, 'blur', 'freeSolo');
|
|
@@ -891,9 +1002,10 @@ function useAutocomplete(props) {
|
|
|
891
1002
|
};
|
|
892
1003
|
const handleInputChange = event => {
|
|
893
1004
|
const newValue = event.target.value;
|
|
894
|
-
|
|
1005
|
+
const valueChanged = inputValue !== newValue;
|
|
1006
|
+
if (valueChanged) {
|
|
895
1007
|
setInputValueState(newValue);
|
|
896
|
-
|
|
1008
|
+
touchScrolledRef.current = false;
|
|
897
1009
|
if (onInputChange) {
|
|
898
1010
|
onInputChange(event, newValue, 'input');
|
|
899
1011
|
}
|
|
@@ -907,6 +1019,12 @@ function useAutocomplete(props) {
|
|
|
907
1019
|
} else {
|
|
908
1020
|
handleOpen(event);
|
|
909
1021
|
}
|
|
1022
|
+
|
|
1023
|
+
// Called after handleOpen so it overrides handleOpen's setInputPristine(true)
|
|
1024
|
+
// when the first keystroke also opens the popup.
|
|
1025
|
+
if (valueChanged) {
|
|
1026
|
+
setInputPristine(false);
|
|
1027
|
+
}
|
|
910
1028
|
};
|
|
911
1029
|
const handleOptionMouseMove = event => {
|
|
912
1030
|
const index = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
@@ -916,20 +1034,46 @@ function useAutocomplete(props) {
|
|
|
916
1034
|
index,
|
|
917
1035
|
reason: 'mouse'
|
|
918
1036
|
});
|
|
1037
|
+
} else {
|
|
1038
|
+
// The option is already highlighted (e.g. programmatically via autoHighlight),
|
|
1039
|
+
// but the user moved the mouse over it — mark as mouse-initiated so
|
|
1040
|
+
// autoSelect on blur correctly treats this as incidental hover.
|
|
1041
|
+
highlightReasonRef.current = 'mouse';
|
|
1042
|
+
}
|
|
1043
|
+
// Don't clear the touch-scroll guard while touch state is still latched.
|
|
1044
|
+
// After a touch gesture, browsers may fire compatibility mousemove
|
|
1045
|
+
// events; if those cleared the guard immediately, later compat events in
|
|
1046
|
+
// the same sequence could be misclassified as a real mouse interaction.
|
|
1047
|
+
// Touch state is cleared by the next deliberate interaction
|
|
1048
|
+
// (keyboard nav, handleOptionClick, or handleOpen).
|
|
1049
|
+
if (!isTouchRef.current) {
|
|
1050
|
+
touchScrolledRef.current = false;
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
const handleListboxMouseLeave = event => {
|
|
1054
|
+
if (!resetHighlightOnMouseLeave || highlightedIndexRef.current === -1 || highlightReasonRef.current !== 'mouse' || isTouchRef.current) {
|
|
1055
|
+
return;
|
|
919
1056
|
}
|
|
1057
|
+
setHighlightedIndex({
|
|
1058
|
+
event,
|
|
1059
|
+
index: -1,
|
|
1060
|
+
reason: 'mouse',
|
|
1061
|
+
preserveScroll: true
|
|
1062
|
+
});
|
|
920
1063
|
};
|
|
921
1064
|
const handleOptionTouchStart = event => {
|
|
1065
|
+
touchScrolledRef.current = false;
|
|
922
1066
|
setHighlightedIndex({
|
|
923
1067
|
event,
|
|
924
1068
|
index: Number(event.currentTarget.getAttribute('data-option-index')),
|
|
925
1069
|
reason: 'touch'
|
|
926
1070
|
});
|
|
927
|
-
|
|
1071
|
+
isTouchRef.current = true;
|
|
928
1072
|
};
|
|
929
1073
|
const handleOptionClick = event => {
|
|
930
1074
|
const index = Number(event.currentTarget.getAttribute('data-option-index'));
|
|
931
1075
|
selectNewValue(event, filteredOptions[index], 'selectOption');
|
|
932
|
-
|
|
1076
|
+
isTouchRef.current = false;
|
|
933
1077
|
};
|
|
934
1078
|
const handleItemDelete = index => event => {
|
|
935
1079
|
const newValue = value.slice();
|
|
@@ -954,11 +1098,11 @@ function useAutocomplete(props) {
|
|
|
954
1098
|
// Prevent input blur when interacting with the combobox
|
|
955
1099
|
const handleMouseDown = event => {
|
|
956
1100
|
// Prevent focusing the input if click is anywhere outside the Autocomplete
|
|
957
|
-
if (!event.currentTarget
|
|
1101
|
+
if (!contains(event.currentTarget, event.target)) {
|
|
958
1102
|
return;
|
|
959
1103
|
}
|
|
960
1104
|
// Don't interfere with interactions outside the input area (e.g. helper text)
|
|
961
|
-
if (anchorEl && !
|
|
1105
|
+
if (anchorEl && !contains(anchorEl, event.target)) {
|
|
962
1106
|
return;
|
|
963
1107
|
}
|
|
964
1108
|
if (event.target.getAttribute('id') !== id) {
|
|
@@ -969,11 +1113,11 @@ function useAutocomplete(props) {
|
|
|
969
1113
|
// Focus the input when interacting with the combobox
|
|
970
1114
|
const handleClick = event => {
|
|
971
1115
|
// Prevent focusing the input if click is anywhere outside the Autocomplete
|
|
972
|
-
if (!event.currentTarget
|
|
1116
|
+
if (!contains(event.currentTarget, event.target)) {
|
|
973
1117
|
return;
|
|
974
1118
|
}
|
|
975
1119
|
// Don't interfere with interactions outside the input area (e.g. helper text)
|
|
976
|
-
if (anchorEl && !
|
|
1120
|
+
if (anchorEl && !contains(anchorEl, event.target)) {
|
|
977
1121
|
return;
|
|
978
1122
|
}
|
|
979
1123
|
inputRef.current.focus();
|
|
@@ -1057,7 +1201,10 @@ function useAutocomplete(props) {
|
|
|
1057
1201
|
getClearProps: () => ({
|
|
1058
1202
|
tabIndex: -1,
|
|
1059
1203
|
type: 'button',
|
|
1060
|
-
onClick:
|
|
1204
|
+
onClick: event => {
|
|
1205
|
+
ignoreFocus.current = true;
|
|
1206
|
+
handleClear(event);
|
|
1207
|
+
}
|
|
1061
1208
|
}),
|
|
1062
1209
|
getItemProps: ({
|
|
1063
1210
|
index = 0
|
|
@@ -1067,6 +1214,12 @@ function useAutocomplete(props) {
|
|
|
1067
1214
|
}),
|
|
1068
1215
|
'data-item-index': index,
|
|
1069
1216
|
tabIndex: -1,
|
|
1217
|
+
onFocus: () => {
|
|
1218
|
+
// If focus on the item doesn't come from keyboard events, we update the state via onFocus.
|
|
1219
|
+
if (focusedItem !== index) {
|
|
1220
|
+
setFocusedItem(index);
|
|
1221
|
+
}
|
|
1222
|
+
},
|
|
1070
1223
|
...(!readOnly && {
|
|
1071
1224
|
onDelete: multiple ? handleItemDelete(index) : handleSingleItemDelete
|
|
1072
1225
|
})
|
|
@@ -1076,15 +1229,37 @@ function useAutocomplete(props) {
|
|
|
1076
1229
|
type: 'button',
|
|
1077
1230
|
onClick: handlePopupIndicator
|
|
1078
1231
|
}),
|
|
1079
|
-
getListboxProps: () => ({
|
|
1232
|
+
getListboxProps: (other = {}) => ({
|
|
1233
|
+
...other,
|
|
1080
1234
|
role: 'listbox',
|
|
1081
1235
|
id: `${id}-listbox`,
|
|
1082
1236
|
'aria-labelledby': `${id}-label`,
|
|
1083
1237
|
'aria-multiselectable': multiple || undefined,
|
|
1084
1238
|
ref: handleListboxRef,
|
|
1085
1239
|
onMouseDown: event => {
|
|
1240
|
+
other.onMouseDown?.(event);
|
|
1241
|
+
if (event.defaultMuiPrevented) {
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1086
1245
|
// Prevent blur
|
|
1087
1246
|
event.preventDefault();
|
|
1247
|
+
},
|
|
1248
|
+
onScroll: event => {
|
|
1249
|
+
other.onScroll?.(event);
|
|
1250
|
+
if (event.defaultMuiPrevented) {
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
if (isTouchRef.current) {
|
|
1254
|
+
touchScrolledRef.current = true;
|
|
1255
|
+
}
|
|
1256
|
+
},
|
|
1257
|
+
onMouseLeave: event => {
|
|
1258
|
+
other.onMouseLeave?.(event);
|
|
1259
|
+
if (event.defaultMuiPrevented) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
handleListboxMouseLeave(event);
|
|
1088
1263
|
}
|
|
1089
1264
|
}),
|
|
1090
1265
|
getOptionProps: ({
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _contains = _interopRequireDefault(require("@mui/utils/contains"));
|
|
9
|
+
var _default = exports.default = _contains.default;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const FOCUSABLE_ATTRIBUTE = "data-mui-focusable";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the element marked as the initial focus target inside a focus trap.
|
|
4
|
+
* The root element takes precedence over marked descendants so components can
|
|
5
|
+
* opt into focusing their own root surface directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getFocusTarget(rootElement: HTMLElement | null | undefined): HTMLElement | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const FOCUSABLE_ATTRIBUTE = "data-mui-focusable";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the element marked as the initial focus target inside a focus trap.
|
|
4
|
+
* The root element takes precedence over marked descendants so components can
|
|
5
|
+
* opt into focusing their own root surface directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getFocusTarget(rootElement: HTMLElement | null | undefined): HTMLElement | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FOCUSABLE_ATTRIBUTE = void 0;
|
|
7
|
+
exports.getFocusTarget = getFocusTarget;
|
|
8
|
+
const FOCUSABLE_ATTRIBUTE = exports.FOCUSABLE_ATTRIBUTE = 'data-mui-focusable';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns the element marked as the initial focus target inside a focus trap.
|
|
12
|
+
* The root element takes precedence over marked descendants so components can
|
|
13
|
+
* opt into focusing their own root surface directly.
|
|
14
|
+
*/
|
|
15
|
+
function getFocusTarget(rootElement) {
|
|
16
|
+
if (!rootElement) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return rootElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? rootElement : rootElement.querySelector(`[${FOCUSABLE_ATTRIBUTE}]`);
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const FOCUSABLE_ATTRIBUTE = 'data-mui-focusable';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns the element marked as the initial focus target inside a focus trap.
|
|
5
|
+
* The root element takes precedence over marked descendants so components can
|
|
6
|
+
* opt into focusing their own root surface directly.
|
|
7
|
+
*/
|
|
8
|
+
export function getFocusTarget(rootElement) {
|
|
9
|
+
if (!rootElement) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return rootElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? rootElement : rootElement.querySelector(`[${FOCUSABLE_ATTRIBUTE}]`);
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = void 0;
|
|
8
|
+
var _getEventTarget = _interopRequireDefault(require("@mui/utils/getEventTarget"));
|
|
9
|
+
var _default = exports.default = _getEventTarget.default;
|