@mui/material 7.3.10 → 7.3.11
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 +63 -12
- package/Button/Button.js +18 -1
- package/CHANGELOG.md +35 -0
- package/Checkbox/Checkbox.js +2 -1
- package/ClickAwayListener/ClickAwayListener.js +2 -5
- package/Dialog/Dialog.js +11 -6
- package/Drawer/Drawer.js +18 -4
- package/Fab/Fab.js +7 -1
- package/InputBase/InputBase.js +39 -7
- package/ListItemButton/ListItemButton.js +7 -1
- package/MenuItem/MenuItem.js +6 -1
- package/Popper/BasePopper.js +23 -1
- package/Slider/useSlider.js +6 -3
- package/SwipeableDrawer/SwipeableDrawer.js +5 -4
- package/Switch/Switch.js +3 -4
- package/Unstable_TrapFocus/FocusTrap.js +15 -5
- package/esm/Autocomplete/Autocomplete.js +63 -12
- package/esm/Button/Button.js +18 -1
- package/esm/Checkbox/Checkbox.js +2 -1
- package/esm/ClickAwayListener/ClickAwayListener.js +2 -5
- package/esm/Dialog/Dialog.js +11 -6
- package/esm/Drawer/Drawer.js +18 -4
- package/esm/Fab/Fab.js +7 -1
- package/esm/InputBase/InputBase.js +39 -7
- package/esm/ListItemButton/ListItemButton.js +7 -1
- package/esm/MenuItem/MenuItem.js +6 -1
- package/esm/Popper/BasePopper.js +23 -1
- package/esm/Slider/useSlider.js +6 -3
- package/esm/SwipeableDrawer/SwipeableDrawer.js +5 -4
- package/esm/Switch/Switch.js +3 -4
- package/esm/Unstable_TrapFocus/FocusTrap.js +15 -5
- package/esm/index.js +1 -1
- package/esm/useAutocomplete/useAutocomplete.d.ts +4 -5
- package/esm/useAutocomplete/useAutocomplete.js +155 -46
- package/esm/utils/contains.d.ts +2 -0
- package/esm/utils/contains.js +2 -0
- package/esm/utils/focusable.d.ts +7 -0
- package/esm/utils/focusable.js +13 -0
- package/esm/utils/getEventTarget.d.ts +2 -0
- package/esm/utils/getEventTarget.js +2 -0
- package/esm/version/index.js +2 -2
- package/index.js +1 -1
- package/package.json +5 -5
- package/useAutocomplete/useAutocomplete.d.ts +4 -5
- package/useAutocomplete/useAutocomplete.js +155 -46
- package/utils/contains.d.ts +2 -0
- package/utils/contains.js +9 -0
- package/utils/focusable.d.ts +7 -0
- package/utils/focusable.js +20 -0
- package/utils/getEventTarget.d.ts +2 -0
- package/utils/getEventTarget.js +9 -0
- package/version/index.js +2 -2
|
@@ -15,7 +15,9 @@ var _ownerDocument = _interopRequireDefault(require("@mui/utils/ownerDocument"))
|
|
|
15
15
|
var _getReactElementRef = _interopRequireDefault(require("@mui/utils/getReactElementRef"));
|
|
16
16
|
var _exactProp = _interopRequireDefault(require("@mui/utils/exactProp"));
|
|
17
17
|
var _elementAcceptingRef = _interopRequireDefault(require("@mui/utils/elementAcceptingRef"));
|
|
18
|
+
var _contains = _interopRequireDefault(require("../utils/contains"));
|
|
18
19
|
var _getActiveElement = _interopRequireDefault(require("../utils/getActiveElement"));
|
|
20
|
+
var _focusable = require("../utils/focusable");
|
|
19
21
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
20
22
|
// Inspired by https://github.com/focus-trap/tabbable
|
|
21
23
|
const candidatesSelector = ['input', 'select', 'textarea', 'a[href]', 'button', '[tabindex]', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])'].join(',');
|
|
@@ -114,21 +116,29 @@ function FocusTrap(props) {
|
|
|
114
116
|
activated.current = !disableAutoFocus;
|
|
115
117
|
}, [disableAutoFocus, open]);
|
|
116
118
|
React.useEffect(() => {
|
|
119
|
+
// Reset on every mount — React 18 Strict Mode double-mounts leave this
|
|
120
|
+
// stuck at `true` after the cleanup of the previous mount set it.
|
|
121
|
+
ignoreNextEnforceFocus.current = false;
|
|
122
|
+
|
|
117
123
|
// We might render an empty child.
|
|
118
124
|
if (!open || !rootRef.current) {
|
|
119
125
|
return;
|
|
120
126
|
}
|
|
121
127
|
const doc = (0, _ownerDocument.default)(rootRef.current);
|
|
122
128
|
const activeElement = (0, _getActiveElement.default)(doc);
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
|
|
130
|
+
// Prefer the explicitly marked focusable element. Fall back to the root
|
|
131
|
+
// element for generic FocusTrap usage.
|
|
132
|
+
const focusTarget = (0, _focusable.getFocusTarget)(rootRef.current) ?? rootRef.current;
|
|
133
|
+
if (!(0, _contains.default)(rootRef.current, activeElement)) {
|
|
134
|
+
if (!focusTarget.hasAttribute('tabIndex')) {
|
|
125
135
|
if (process.env.NODE_ENV !== 'production') {
|
|
126
136
|
console.error(['MUI: The modal content node does not accept focus.', 'For the benefit of assistive technologies, ' + 'the tabIndex of the node is being set to "-1".'].join('\n'));
|
|
127
137
|
}
|
|
128
|
-
|
|
138
|
+
focusTarget.setAttribute('tabIndex', '-1');
|
|
129
139
|
}
|
|
130
140
|
if (activated.current) {
|
|
131
|
-
|
|
141
|
+
focusTarget.focus();
|
|
132
142
|
}
|
|
133
143
|
}
|
|
134
144
|
return () => {
|
|
@@ -188,7 +198,7 @@ function FocusTrap(props) {
|
|
|
188
198
|
}
|
|
189
199
|
|
|
190
200
|
// The focus is already inside
|
|
191
|
-
if (
|
|
201
|
+
if ((0, _contains.default)(rootElement, activeEl)) {
|
|
192
202
|
return;
|
|
193
203
|
}
|
|
194
204
|
|
|
@@ -6,6 +6,8 @@ import PropTypes from 'prop-types';
|
|
|
6
6
|
import integerPropType from '@mui/utils/integerPropType';
|
|
7
7
|
import chainPropTypes from '@mui/utils/chainPropTypes';
|
|
8
8
|
import composeClasses from '@mui/utils/composeClasses';
|
|
9
|
+
import useForcedRerendering from '@mui/utils/useForcedRerendering';
|
|
10
|
+
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
9
11
|
import useAutocomplete, { createFilterOptions } from "../useAutocomplete/index.js";
|
|
10
12
|
import Popper from "../Popper/index.js";
|
|
11
13
|
import ListSubheader from "../ListSubheader/index.js";
|
|
@@ -495,6 +497,46 @@ const Autocomplete = /*#__PURE__*/React.forwardRef(function Autocomplete(inProps
|
|
|
495
497
|
...props,
|
|
496
498
|
componentName: 'Autocomplete'
|
|
497
499
|
});
|
|
500
|
+
|
|
501
|
+
// Re-render when anchorEl resizes so the Popper width stays in sync.
|
|
502
|
+
// Width is always read synchronously from anchorEl.clientWidth during render
|
|
503
|
+
// (no stale cached value). The hook just triggers a re-render on resize.
|
|
504
|
+
const forceRenderOnResize = useForcedRerendering();
|
|
505
|
+
React.useEffect(() => {
|
|
506
|
+
if (!popupOpen || !anchorEl || typeof ResizeObserver === 'undefined') {
|
|
507
|
+
return undefined;
|
|
508
|
+
}
|
|
509
|
+
let lastWidth = anchorEl.clientWidth;
|
|
510
|
+
const observer = new ResizeObserver(() => {
|
|
511
|
+
const newWidth = anchorEl.clientWidth;
|
|
512
|
+
if (lastWidth !== newWidth) {
|
|
513
|
+
lastWidth = newWidth;
|
|
514
|
+
forceRenderOnResize();
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
observer.observe(anchorEl);
|
|
518
|
+
return () => {
|
|
519
|
+
observer.disconnect();
|
|
520
|
+
};
|
|
521
|
+
}, [popupOpen, anchorEl, forceRenderOnResize]);
|
|
522
|
+
|
|
523
|
+
// When popupOpen becomes false, useAutocomplete returns [] for groupedOptions.
|
|
524
|
+
// Transitioned Poppers can remain mounted for their exit animation, so keep rendering
|
|
525
|
+
// the last open-state options instead of flashing "No options" or an empty Paper.
|
|
526
|
+
// These options are stale because they no longer reflect the hook's current
|
|
527
|
+
// groupedOptions, but they are non-interactive while closing and reset on next open.
|
|
528
|
+
const previousGroupedOptionsRef = React.useRef([]);
|
|
529
|
+
const prevPopupOpenRef = React.useRef(false);
|
|
530
|
+
const renderedOptions = popupOpen ? groupedOptions : previousGroupedOptionsRef.current;
|
|
531
|
+
useEnhancedEffect(() => {
|
|
532
|
+
if (popupOpen && !prevPopupOpenRef.current) {
|
|
533
|
+
previousGroupedOptionsRef.current = [];
|
|
534
|
+
}
|
|
535
|
+
prevPopupOpenRef.current = popupOpen;
|
|
536
|
+
if (popupOpen && groupedOptions.length > 0) {
|
|
537
|
+
previousGroupedOptionsRef.current = groupedOptions;
|
|
538
|
+
}
|
|
539
|
+
}, [popupOpen, groupedOptions]);
|
|
498
540
|
const hasClearIcon = !disableClearable && !disabled && dirty && !readOnly;
|
|
499
541
|
const hasPopupIcon = (!freeSolo || forcePopupIcon === true) && forcePopupIcon !== false;
|
|
500
542
|
const {
|
|
@@ -568,13 +610,24 @@ const Autocomplete = /*#__PURE__*/React.forwardRef(function Autocomplete(inProps
|
|
|
568
610
|
additionalProps: {
|
|
569
611
|
disablePortal,
|
|
570
612
|
style: {
|
|
571
|
-
width: anchorEl ? anchorEl.clientWidth : null
|
|
613
|
+
width: anchorEl ? anchorEl.clientWidth : null,
|
|
614
|
+
// Prevent interaction with stale cached options during exit transitions.
|
|
615
|
+
// The hook's filteredOptions is [] when popupOpen=false, so clicks on stale
|
|
616
|
+
// rendered options would pass undefined to selectNewValue.
|
|
617
|
+
pointerEvents: popupOpen ? undefined : 'none'
|
|
572
618
|
},
|
|
573
619
|
role: 'presentation',
|
|
574
620
|
anchorEl,
|
|
575
621
|
open: popupOpen
|
|
576
622
|
}
|
|
577
623
|
});
|
|
624
|
+
|
|
625
|
+
// Don't render the Popper when there's no content to show.
|
|
626
|
+
// In freeSolo mode, "No options" text is suppressed, so if there are also no
|
|
627
|
+
// matching options and loading is false, the Paper would be empty.
|
|
628
|
+
// Uses renderedOptions (not groupedOptions) so Popper stays during exit transitions.
|
|
629
|
+
// Respect keepMounted from resolved popperProps (handles both object and callback slotProps forms).
|
|
630
|
+
const hasPopupContent = renderedOptions.length > 0 || loading || !freeSolo || popperProps.keepMounted === true;
|
|
578
631
|
const [ClearIndicatorSlot, clearIndicatorProps] = useSlot('clearIndicator', {
|
|
579
632
|
elementType: AutocompleteClearIndicator,
|
|
580
633
|
externalForwardedProps,
|
|
@@ -720,17 +773,17 @@ const Autocomplete = /*#__PURE__*/React.forwardRef(function Autocomplete(inProps
|
|
|
720
773
|
...getInputProps()
|
|
721
774
|
}
|
|
722
775
|
})
|
|
723
|
-
}), anchorEl ? /*#__PURE__*/_jsx(AutocompletePopper, {
|
|
776
|
+
}), anchorEl && hasPopupContent ? /*#__PURE__*/_jsx(AutocompletePopper, {
|
|
724
777
|
as: PopperSlot,
|
|
725
778
|
...popperProps,
|
|
726
779
|
children: /*#__PURE__*/_jsxs(AutocompletePaper, {
|
|
727
780
|
as: PaperSlot,
|
|
728
781
|
...paperProps,
|
|
729
|
-
children: [loading &&
|
|
782
|
+
children: [loading && renderedOptions.length === 0 ? /*#__PURE__*/_jsx(AutocompleteLoading, {
|
|
730
783
|
className: classes.loading,
|
|
731
784
|
ownerState: ownerState,
|
|
732
785
|
children: loadingText
|
|
733
|
-
}) : null,
|
|
786
|
+
}) : null, renderedOptions.length === 0 && !freeSolo && !loading ? /*#__PURE__*/_jsx(AutocompleteNoOptions, {
|
|
734
787
|
className: classes.noOptions,
|
|
735
788
|
ownerState: ownerState,
|
|
736
789
|
role: "presentation",
|
|
@@ -739,10 +792,9 @@ const Autocomplete = /*#__PURE__*/React.forwardRef(function Autocomplete(inProps
|
|
|
739
792
|
event.preventDefault();
|
|
740
793
|
},
|
|
741
794
|
children: noOptionsText
|
|
742
|
-
}) : null,
|
|
743
|
-
as: ListboxComponentProp,
|
|
795
|
+
}) : null, renderedOptions.length > 0 ? /*#__PURE__*/_jsx(ListboxSlot, {
|
|
744
796
|
...listboxProps,
|
|
745
|
-
children:
|
|
797
|
+
children: renderedOptions.map((option, index) => {
|
|
746
798
|
if (groupBy) {
|
|
747
799
|
return renderGroup({
|
|
748
800
|
key: option.key,
|
|
@@ -775,12 +827,11 @@ process.env.NODE_ENV !== "production" ? Autocomplete.propTypes /* remove-proptyp
|
|
|
775
827
|
*/
|
|
776
828
|
autoHighlight: PropTypes.bool,
|
|
777
829
|
/**
|
|
778
|
-
* If `true`, the
|
|
779
|
-
* when the Autocomplete loses focus unless the user chooses
|
|
780
|
-
* a different option or changes the character string in the input.
|
|
830
|
+
* If `true`, the value is updated when the input loses focus under one of these conditions:
|
|
781
831
|
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
832
|
+
* - An option highlighted via keyboard navigation or `autoHighlight` is selected.
|
|
833
|
+
* Hover and touch highlights are ignored.
|
|
834
|
+
* - Otherwise, in `freeSolo` mode, the typed text becomes the value.
|
|
784
835
|
* @default false
|
|
785
836
|
*/
|
|
786
837
|
autoSelect: PropTypes.bool,
|
package/esm/Button/Button.js
CHANGED
|
@@ -102,6 +102,17 @@ const ButtonRoot = styled(ButtonBase, {
|
|
|
102
102
|
color: (theme.vars || theme).palette.action.disabled
|
|
103
103
|
},
|
|
104
104
|
variants: [{
|
|
105
|
+
props: ({
|
|
106
|
+
ownerState
|
|
107
|
+
}) => ownerState.startIcon || ownerState.loading && ownerState.loadingPosition === 'start',
|
|
108
|
+
style: {
|
|
109
|
+
'&::before': {
|
|
110
|
+
content: '"\\200b"',
|
|
111
|
+
width: 0,
|
|
112
|
+
overflow: 'hidden'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}, {
|
|
105
116
|
props: {
|
|
106
117
|
variant: 'contained'
|
|
107
118
|
},
|
|
@@ -551,6 +562,12 @@ const Button = /*#__PURE__*/React.forwardRef(function Button(inProps, ref) {
|
|
|
551
562
|
children: loadingIndicator
|
|
552
563
|
})
|
|
553
564
|
}) : null;
|
|
565
|
+
|
|
566
|
+
// Don't forward the 'root' classes to the ButtonBase, as they will get duplicated with the one passed to the className prop.
|
|
567
|
+
const {
|
|
568
|
+
root,
|
|
569
|
+
...forwardedClasses
|
|
570
|
+
} = classes;
|
|
554
571
|
return /*#__PURE__*/_jsxs(ButtonRoot, {
|
|
555
572
|
ownerState: ownerState,
|
|
556
573
|
className: clsx(contextProps.className, classes.root, className, positionClassName),
|
|
@@ -562,7 +579,7 @@ const Button = /*#__PURE__*/React.forwardRef(function Button(inProps, ref) {
|
|
|
562
579
|
type: type,
|
|
563
580
|
id: loading ? loadingId : idProp,
|
|
564
581
|
...other,
|
|
565
|
-
classes:
|
|
582
|
+
classes: forwardedClasses,
|
|
566
583
|
children: [startIcon, loadingPosition !== 'end' && loader, children, loadingPosition === 'end' && loader, endIcon]
|
|
567
584
|
});
|
|
568
585
|
});
|
package/esm/Checkbox/Checkbox.js
CHANGED
|
@@ -152,7 +152,8 @@ const Checkbox = /*#__PURE__*/React.forwardRef(function Checkbox(inProps, ref) {
|
|
|
152
152
|
slots,
|
|
153
153
|
slotProps: {
|
|
154
154
|
input: mergeSlotProps(typeof externalInputProps === 'function' ? externalInputProps(ownerState) : externalInputProps, {
|
|
155
|
-
'data-indeterminate': indeterminate
|
|
155
|
+
'data-indeterminate': indeterminate,
|
|
156
|
+
'aria-checked': indeterminate ? 'mixed' : undefined
|
|
156
157
|
})
|
|
157
158
|
}
|
|
158
159
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
|
+
import contains from '@mui/utils/contains';
|
|
5
6
|
import ownerDocument from '@mui/utils/ownerDocument';
|
|
6
7
|
import useForkRef from '@mui/utils/useForkRef';
|
|
7
8
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
@@ -84,11 +85,7 @@ function ClickAwayListener(props) {
|
|
|
84
85
|
if (event.composedPath) {
|
|
85
86
|
insideDOM = event.composedPath().includes(nodeRef.current);
|
|
86
87
|
} else {
|
|
87
|
-
insideDOM = !doc.documentElement.contains(
|
|
88
|
-
// @ts-expect-error returns `false` as intended when not dispatched from a Node
|
|
89
|
-
event.target) || nodeRef.current.contains(
|
|
90
|
-
// @ts-expect-error returns `false` as intended when not dispatched from a Node
|
|
91
|
-
event.target);
|
|
88
|
+
insideDOM = !contains(doc.documentElement, event.target) || contains(nodeRef.current, event.target);
|
|
92
89
|
}
|
|
93
90
|
if (!insideDOM && (disableReactTree || !insideReactTree)) {
|
|
94
91
|
onClickAway(event);
|
package/esm/Dialog/Dialog.js
CHANGED
|
@@ -16,6 +16,7 @@ import { styled, useTheme } from "../zero-styled/index.js";
|
|
|
16
16
|
import memoTheme from "../utils/memoTheme.js";
|
|
17
17
|
import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
|
18
18
|
import useSlot from "../utils/useSlot.js";
|
|
19
|
+
import { FOCUSABLE_ATTRIBUTE } from "../utils/focusable.js";
|
|
19
20
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
20
21
|
const DialogBackdrop = styled(Backdrop, {
|
|
21
22
|
name: 'MuiDialog',
|
|
@@ -294,7 +295,16 @@ const Dialog = /*#__PURE__*/React.forwardRef(function Dialog(inProps, ref) {
|
|
|
294
295
|
shouldForwardComponentProp: true,
|
|
295
296
|
externalForwardedProps,
|
|
296
297
|
ownerState,
|
|
297
|
-
className:
|
|
298
|
+
className: classes.paper,
|
|
299
|
+
additionalProps: {
|
|
300
|
+
elevation: 24,
|
|
301
|
+
role,
|
|
302
|
+
'aria-describedby': ariaDescribedby,
|
|
303
|
+
'aria-labelledby': ariaLabelledby,
|
|
304
|
+
'aria-modal': ariaModal,
|
|
305
|
+
tabIndex: -1,
|
|
306
|
+
[FOCUSABLE_ATTRIBUTE]: ''
|
|
307
|
+
}
|
|
298
308
|
});
|
|
299
309
|
const [ContainerSlot, containerSlotProps] = useSlot('container', {
|
|
300
310
|
elementType: DialogContainer,
|
|
@@ -338,11 +348,6 @@ const Dialog = /*#__PURE__*/React.forwardRef(function Dialog(inProps, ref) {
|
|
|
338
348
|
...containerSlotProps,
|
|
339
349
|
children: /*#__PURE__*/_jsx(PaperSlot, {
|
|
340
350
|
as: PaperComponent,
|
|
341
|
-
elevation: 24,
|
|
342
|
-
role: role,
|
|
343
|
-
"aria-describedby": ariaDescribedby,
|
|
344
|
-
"aria-labelledby": ariaLabelledby,
|
|
345
|
-
"aria-modal": ariaModal,
|
|
346
351
|
...paperSlotProps,
|
|
347
352
|
children: /*#__PURE__*/_jsx(DialogContext.Provider, {
|
|
348
353
|
value: dialogContextValue,
|
package/esm/Drawer/Drawer.js
CHANGED
|
@@ -14,8 +14,10 @@ import rootShouldForwardProp from "../styles/rootShouldForwardProp.js";
|
|
|
14
14
|
import { styled, useTheme } from "../zero-styled/index.js";
|
|
15
15
|
import memoTheme from "../utils/memoTheme.js";
|
|
16
16
|
import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
|
17
|
+
import useForkRef from "../utils/useForkRef.js";
|
|
17
18
|
import { getDrawerUtilityClass } from "./drawerClasses.js";
|
|
18
19
|
import useSlot from "../utils/useSlot.js";
|
|
20
|
+
import { FOCUSABLE_ATTRIBUTE } from "../utils/focusable.js";
|
|
19
21
|
import { mergeSlotProps } from "../utils/index.js";
|
|
20
22
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
21
23
|
const overridesResolver = (props, styles) => {
|
|
@@ -208,9 +210,15 @@ const Drawer = /*#__PURE__*/React.forwardRef(function Drawer(inProps, ref) {
|
|
|
208
210
|
// We use this state is order to skip the appear transition during the
|
|
209
211
|
// initial mount of the component.
|
|
210
212
|
const mounted = React.useRef(false);
|
|
213
|
+
const rootRef = React.useRef(null);
|
|
214
|
+
const handleRef = useForkRef(ref, rootRef);
|
|
211
215
|
React.useEffect(() => {
|
|
212
216
|
mounted.current = true;
|
|
213
217
|
}, []);
|
|
218
|
+
|
|
219
|
+
// Resolve the container lazily so Slide reads the mounted modal root
|
|
220
|
+
// after refs are assigned, rather than the initial null ref during render.
|
|
221
|
+
const resolveSlideContainer = React.useCallback(() => rootRef.current, []);
|
|
214
222
|
const anchorInvariant = getAnchor({
|
|
215
223
|
direction: isRtl ? 'rtl' : 'ltr'
|
|
216
224
|
}, anchorProp);
|
|
@@ -242,7 +250,7 @@ const Drawer = /*#__PURE__*/React.forwardRef(function Drawer(inProps, ref) {
|
|
|
242
250
|
}
|
|
243
251
|
};
|
|
244
252
|
const [RootSlot, rootSlotProps] = useSlot('root', {
|
|
245
|
-
ref,
|
|
253
|
+
ref: handleRef,
|
|
246
254
|
elementType: DrawerRoot,
|
|
247
255
|
className: clsx(classes.root, classes.modal, className),
|
|
248
256
|
shouldForwardComponentProp: true,
|
|
@@ -253,6 +261,7 @@ const Drawer = /*#__PURE__*/React.forwardRef(function Drawer(inProps, ref) {
|
|
|
253
261
|
...ModalProps
|
|
254
262
|
},
|
|
255
263
|
additionalProps: {
|
|
264
|
+
closeAfterTransition: true,
|
|
256
265
|
open,
|
|
257
266
|
onClose,
|
|
258
267
|
hideBackdrop,
|
|
@@ -275,13 +284,15 @@ const Drawer = /*#__PURE__*/React.forwardRef(function Drawer(inProps, ref) {
|
|
|
275
284
|
square: true,
|
|
276
285
|
...(variant === 'temporary' && {
|
|
277
286
|
role: 'dialog',
|
|
278
|
-
'aria-modal': 'true'
|
|
287
|
+
'aria-modal': 'true',
|
|
288
|
+
[FOCUSABLE_ATTRIBUTE]: '',
|
|
289
|
+
tabIndex: -1
|
|
279
290
|
})
|
|
280
291
|
}
|
|
281
292
|
});
|
|
282
293
|
const [DockedSlot, dockedSlotProps] = useSlot('docked', {
|
|
283
294
|
elementType: DrawerDockedRoot,
|
|
284
|
-
ref,
|
|
295
|
+
ref: handleRef,
|
|
285
296
|
className: clsx(classes.root, classes.docked, className),
|
|
286
297
|
ownerState,
|
|
287
298
|
externalForwardedProps,
|
|
@@ -295,7 +306,10 @@ const Drawer = /*#__PURE__*/React.forwardRef(function Drawer(inProps, ref) {
|
|
|
295
306
|
in: open,
|
|
296
307
|
direction: oppositeDirection[anchorInvariant],
|
|
297
308
|
timeout: transitionDuration,
|
|
298
|
-
appear: mounted.current
|
|
309
|
+
appear: mounted.current,
|
|
310
|
+
...(variant === 'temporary' && (slots.transition == null || slots.transition === Slide) && {
|
|
311
|
+
container: resolveSlideContainer
|
|
312
|
+
})
|
|
299
313
|
}
|
|
300
314
|
});
|
|
301
315
|
const drawer = /*#__PURE__*/_jsx(PaperSlot, {
|
package/esm/Fab/Fab.js
CHANGED
|
@@ -187,6 +187,12 @@ const Fab = /*#__PURE__*/React.forwardRef(function Fab(inProps, ref) {
|
|
|
187
187
|
variant
|
|
188
188
|
};
|
|
189
189
|
const classes = useUtilityClasses(ownerState);
|
|
190
|
+
|
|
191
|
+
// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
|
|
192
|
+
const {
|
|
193
|
+
root,
|
|
194
|
+
...forwardedClasses
|
|
195
|
+
} = classes;
|
|
190
196
|
return /*#__PURE__*/_jsx(FabRoot, {
|
|
191
197
|
className: clsx(classes.root, className),
|
|
192
198
|
component: component,
|
|
@@ -196,7 +202,7 @@ const Fab = /*#__PURE__*/React.forwardRef(function Fab(inProps, ref) {
|
|
|
196
202
|
ownerState: ownerState,
|
|
197
203
|
ref: ref,
|
|
198
204
|
...other,
|
|
199
|
-
classes:
|
|
205
|
+
classes: forwardedClasses,
|
|
200
206
|
children: children
|
|
201
207
|
});
|
|
202
208
|
});
|
|
@@ -19,9 +19,13 @@ import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
|
|
19
19
|
import capitalize from "../utils/capitalize.js";
|
|
20
20
|
import useForkRef from "../utils/useForkRef.js";
|
|
21
21
|
import useEnhancedEffect from "../utils/useEnhancedEffect.js";
|
|
22
|
+
import ownerDocument from "../utils/ownerDocument.js";
|
|
23
|
+
import getActiveElement from "../utils/getActiveElement.js";
|
|
22
24
|
import { isFilled } from "./utils.js";
|
|
23
25
|
import inputBaseClasses, { getInputBaseUtilityClass } from "./inputBaseClasses.js";
|
|
24
26
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
27
|
+
const MUI_AUTO_FILL = 'mui-auto-fill';
|
|
28
|
+
const MUI_AUTO_FILL_CANCEL = 'mui-auto-fill-cancel';
|
|
25
29
|
export const rootOverridesResolver = (props, styles) => {
|
|
26
30
|
const {
|
|
27
31
|
ownerState
|
|
@@ -184,11 +188,11 @@ export const InputBaseInput = styled('input', {
|
|
|
184
188
|
ownerState
|
|
185
189
|
}) => !ownerState.disableInjectingGlobalStyles,
|
|
186
190
|
style: {
|
|
187
|
-
animationName:
|
|
191
|
+
animationName: MUI_AUTO_FILL_CANCEL,
|
|
188
192
|
animationDuration: '10ms',
|
|
189
193
|
'&:-webkit-autofill': {
|
|
190
194
|
animationDuration: '5000s',
|
|
191
|
-
animationName:
|
|
195
|
+
animationName: MUI_AUTO_FILL
|
|
192
196
|
}
|
|
193
197
|
}
|
|
194
198
|
}, {
|
|
@@ -219,14 +223,16 @@ export const InputBaseInput = styled('input', {
|
|
|
219
223
|
};
|
|
220
224
|
}));
|
|
221
225
|
const InputGlobalStyles = globalCss({
|
|
222
|
-
|
|
226
|
+
// Keep keyframes non-empty for Emotion production builds. Animation properties are ignored
|
|
227
|
+
// inside keyframes, avoiding the visible display animation triggered by Chrome 117+.
|
|
228
|
+
[`@keyframes ${MUI_AUTO_FILL}`]: {
|
|
223
229
|
from: {
|
|
224
|
-
|
|
230
|
+
animationName: MUI_AUTO_FILL
|
|
225
231
|
}
|
|
226
232
|
},
|
|
227
|
-
|
|
233
|
+
[`@keyframes ${MUI_AUTO_FILL_CANCEL}`]: {
|
|
228
234
|
from: {
|
|
229
|
-
|
|
235
|
+
animationName: MUI_AUTO_FILL_CANCEL
|
|
230
236
|
}
|
|
231
237
|
}
|
|
232
238
|
});
|
|
@@ -342,6 +348,32 @@ const InputBase = /*#__PURE__*/React.forwardRef(function InputBase(inProps, ref)
|
|
|
342
348
|
});
|
|
343
349
|
}
|
|
344
350
|
}, [value, checkDirty, isControlled]);
|
|
351
|
+
|
|
352
|
+
// Sync focused state when autoFocus is used in SSR.
|
|
353
|
+
// If the browser focused the element before hydration, the onFocus handler never
|
|
354
|
+
// fires. If it did not, React hydration does not call focus() for autoFocus.
|
|
355
|
+
useEnhancedEffect(() => {
|
|
356
|
+
if (!autoFocus) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const input = inputRef.current;
|
|
360
|
+
if (!input) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const doc = ownerDocument(input);
|
|
364
|
+
const activeElement = getActiveElement(doc);
|
|
365
|
+
const noElementFocused = activeElement == null || activeElement === doc.body || activeElement === doc.documentElement;
|
|
366
|
+
if (input === activeElement) {
|
|
367
|
+
if (muiFormControl && muiFormControl.onFocus) {
|
|
368
|
+
muiFormControl.onFocus();
|
|
369
|
+
} else {
|
|
370
|
+
setFocused(true);
|
|
371
|
+
}
|
|
372
|
+
} else if (noElementFocused) {
|
|
373
|
+
input.focus();
|
|
374
|
+
}
|
|
375
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
376
|
+
}, [autoFocus]);
|
|
345
377
|
const handleFocus = event => {
|
|
346
378
|
if (onFocus) {
|
|
347
379
|
onFocus(event);
|
|
@@ -430,7 +462,7 @@ const InputBase = /*#__PURE__*/React.forwardRef(function InputBase(inProps, ref)
|
|
|
430
462
|
}
|
|
431
463
|
const handleAutoFill = event => {
|
|
432
464
|
// Provide a fake value as Chrome might not let you access it for security reasons.
|
|
433
|
-
checkDirty(event.animationName ===
|
|
465
|
+
checkDirty(event.animationName === MUI_AUTO_FILL_CANCEL ? inputRef.current : {
|
|
434
466
|
value: 'x'
|
|
435
467
|
});
|
|
436
468
|
};
|
|
@@ -164,6 +164,12 @@ const ListItemButton = /*#__PURE__*/React.forwardRef(function ListItemButton(inP
|
|
|
164
164
|
selected
|
|
165
165
|
};
|
|
166
166
|
const classes = useUtilityClasses(ownerState);
|
|
167
|
+
|
|
168
|
+
// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
|
|
169
|
+
const {
|
|
170
|
+
root,
|
|
171
|
+
...forwardedClasses
|
|
172
|
+
} = classes;
|
|
167
173
|
const handleRef = useForkRef(listItemRef, ref);
|
|
168
174
|
return /*#__PURE__*/_jsx(ListContext.Provider, {
|
|
169
175
|
value: childContext,
|
|
@@ -177,7 +183,7 @@ const ListItemButton = /*#__PURE__*/React.forwardRef(function ListItemButton(inP
|
|
|
177
183
|
ownerState: ownerState,
|
|
178
184
|
className: clsx(classes.root, className),
|
|
179
185
|
...other,
|
|
180
|
-
classes:
|
|
186
|
+
classes: forwardedClasses,
|
|
181
187
|
children: children
|
|
182
188
|
})
|
|
183
189
|
});
|
package/esm/MenuItem/MenuItem.js
CHANGED
|
@@ -207,6 +207,11 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem(inProps, ref) {
|
|
|
207
207
|
};
|
|
208
208
|
const classes = useUtilityClasses(props);
|
|
209
209
|
const handleRef = useForkRef(menuItemRef, ref);
|
|
210
|
+
// Don't forward the 'root' class to the ButtonBase, as it will get duplicated with the one passed to the className prop.
|
|
211
|
+
const {
|
|
212
|
+
root,
|
|
213
|
+
...forwardedClasses
|
|
214
|
+
} = classes;
|
|
210
215
|
let tabIndex;
|
|
211
216
|
if (!props.disabled) {
|
|
212
217
|
tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1;
|
|
@@ -222,7 +227,7 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem(inProps, ref) {
|
|
|
222
227
|
className: clsx(classes.root, className),
|
|
223
228
|
...other,
|
|
224
229
|
ownerState: ownerState,
|
|
225
|
-
classes:
|
|
230
|
+
classes: forwardedClasses
|
|
226
231
|
})
|
|
227
232
|
});
|
|
228
233
|
});
|
package/esm/Popper/BasePopper.js
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/esm/Slider/useSlider.js
CHANGED
|
@@ -11,6 +11,8 @@ import visuallyHidden from '@mui/utils/visuallyHidden';
|
|
|
11
11
|
import clamp from '@mui/utils/clamp';
|
|
12
12
|
import extractEventHandlers from '@mui/utils/extractEventHandlers';
|
|
13
13
|
import areArraysEqual from "../utils/areArraysEqual.js";
|
|
14
|
+
import contains from "../utils/contains.js";
|
|
15
|
+
import getActiveElement from "../utils/getActiveElement.js";
|
|
14
16
|
const INTENTIONAL_DRAG_COUNT_THRESHOLD = 2;
|
|
15
17
|
function getNewValue(currentValue, step, direction, min, max) {
|
|
16
18
|
return direction === 1 ? Math.min(currentValue + step, max) : Math.max(currentValue - step, min);
|
|
@@ -90,8 +92,8 @@ function focusThumb({
|
|
|
90
92
|
activeIndex,
|
|
91
93
|
setActive
|
|
92
94
|
}) {
|
|
93
|
-
const
|
|
94
|
-
if (!sliderRef.current
|
|
95
|
+
const activeElement = getActiveElement(ownerDocument(sliderRef.current));
|
|
96
|
+
if (!contains(sliderRef.current, activeElement) || Number(activeElement?.getAttribute('data-index')) !== activeIndex) {
|
|
95
97
|
sliderRef.current?.querySelector(`[type="range"][data-index="${activeIndex}"]`).focus();
|
|
96
98
|
}
|
|
97
99
|
if (setActive) {
|
|
@@ -347,7 +349,8 @@ export function useSlider(parameters) {
|
|
|
347
349
|
otherHandlers?.onKeyDown?.(event);
|
|
348
350
|
};
|
|
349
351
|
useEnhancedEffect(() => {
|
|
350
|
-
|
|
352
|
+
const activeElement = getActiveElement(ownerDocument(sliderRef.current));
|
|
353
|
+
if (disabled && contains(sliderRef.current, activeElement)) {
|
|
351
354
|
// This is necessary because Firefox and Safari will keep focus
|
|
352
355
|
// on a disabled element:
|
|
353
356
|
// https://codesandbox.io/p/sandbox/mui-pr-22247-forked-h151h?file=/src/App.js
|
|
@@ -6,10 +6,11 @@ import PropTypes from 'prop-types';
|
|
|
6
6
|
import elementTypeAcceptingRef from '@mui/utils/elementTypeAcceptingRef';
|
|
7
7
|
import NoSsr from "../NoSsr/index.js";
|
|
8
8
|
import Drawer, { getAnchor, isHorizontal } from "../Drawer/Drawer.js";
|
|
9
|
-
import
|
|
9
|
+
import contains from "../utils/contains.js";
|
|
10
10
|
import ownerDocument from "../utils/ownerDocument.js";
|
|
11
11
|
import ownerWindow from "../utils/ownerWindow.js";
|
|
12
12
|
import useEventCallback from "../utils/useEventCallback.js";
|
|
13
|
+
import useForkRef from "../utils/useForkRef.js";
|
|
13
14
|
import useEnhancedEffect from "../utils/useEnhancedEffect.js";
|
|
14
15
|
import { useTheme } from "../zero-styled/index.js";
|
|
15
16
|
import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
|
@@ -292,7 +293,7 @@ const SwipeableDrawer = /*#__PURE__*/React.forwardRef(function SwipeableDrawer(i
|
|
|
292
293
|
const horizontalSwipe = isHorizontal(anchor);
|
|
293
294
|
const currentX = calculateCurrentX(anchorRtl, nativeEvent.touches, ownerDocument(nativeEvent.currentTarget));
|
|
294
295
|
const currentY = calculateCurrentY(anchorRtl, nativeEvent.touches, ownerWindow(nativeEvent.currentTarget));
|
|
295
|
-
if (open && paperRef.current
|
|
296
|
+
if (open && contains(paperRef.current, nativeEvent.target) && claimedSwipeInstance === null) {
|
|
296
297
|
const domTreeShapes = getDomTreeShapes(nativeEvent.target, paperRef.current);
|
|
297
298
|
const hasNativeHandler = computeHasNativeHandler({
|
|
298
299
|
domTreeShapes,
|
|
@@ -390,7 +391,7 @@ const SwipeableDrawer = /*#__PURE__*/React.forwardRef(function SwipeableDrawer(i
|
|
|
390
391
|
}
|
|
391
392
|
|
|
392
393
|
// At least one element clogs the drawer interaction zone.
|
|
393
|
-
if (open && (hideBackdrop || !backdropRef.current
|
|
394
|
+
if (open && (hideBackdrop || !contains(backdropRef.current, nativeEvent.target)) && !contains(paperRef.current, nativeEvent.target)) {
|
|
394
395
|
return;
|
|
395
396
|
}
|
|
396
397
|
const anchorRtl = getAnchor(theme, anchor);
|
|
@@ -402,7 +403,7 @@ const SwipeableDrawer = /*#__PURE__*/React.forwardRef(function SwipeableDrawer(i
|
|
|
402
403
|
// if disableSwipeToOpen
|
|
403
404
|
// if target != swipeArea, and target is not a child of paper ref
|
|
404
405
|
// if is a child of paper ref, and `allowSwipeInChildren` does not allow it
|
|
405
|
-
if (disableSwipeToOpen || !(nativeEvent.target === swipeAreaRef.current || paperRef.current
|
|
406
|
+
if (disableSwipeToOpen || !(nativeEvent.target === swipeAreaRef.current || contains(paperRef.current, nativeEvent.target) && (typeof allowSwipeInChildren === 'function' ? allowSwipeInChildren(nativeEvent, swipeAreaRef.current, paperRef.current) : allowSwipeInChildren))) {
|
|
406
407
|
return;
|
|
407
408
|
}
|
|
408
409
|
if (horizontalSwipe) {
|
package/esm/Switch/Switch.js
CHANGED
|
@@ -13,6 +13,7 @@ import { styled } from "../zero-styled/index.js";
|
|
|
13
13
|
import memoTheme from "../utils/memoTheme.js";
|
|
14
14
|
import { useDefaultProps } from "../DefaultPropsProvider/index.js";
|
|
15
15
|
import switchClasses, { getSwitchUtilityClass } from "./switchClasses.js";
|
|
16
|
+
import { mergeSlotProps } from "../utils/index.js";
|
|
16
17
|
import useSlot from "../utils/useSlot.js";
|
|
17
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
19
|
const useUtilityClasses = ownerState => {
|
|
@@ -225,6 +226,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(inProps, ref) {
|
|
|
225
226
|
size
|
|
226
227
|
};
|
|
227
228
|
const classes = useUtilityClasses(ownerState);
|
|
229
|
+
const externalInputProps = slotProps.input;
|
|
228
230
|
const externalForwardedProps = {
|
|
229
231
|
slots,
|
|
230
232
|
slotProps
|
|
@@ -278,11 +280,8 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(inProps, ref) {
|
|
|
278
280
|
...(slotProps.switchBase && {
|
|
279
281
|
root: typeof slotProps.switchBase === 'function' ? slotProps.switchBase(ownerState) : slotProps.switchBase
|
|
280
282
|
}),
|
|
281
|
-
input: {
|
|
283
|
+
input: mergeSlotProps(typeof externalInputProps === 'function' ? externalInputProps(ownerState) : externalInputProps, {
|
|
282
284
|
role: 'switch'
|
|
283
|
-
},
|
|
284
|
-
...(slotProps.input && {
|
|
285
|
-
input: typeof slotProps.input === 'function' ? slotProps.input(ownerState) : slotProps.input
|
|
286
285
|
})
|
|
287
286
|
}
|
|
288
287
|
}), /*#__PURE__*/_jsx(TrackSlot, {
|