@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
package/Select/SelectInput.mjs
CHANGED
|
@@ -9,18 +9,52 @@ import clsx from 'clsx';
|
|
|
9
9
|
import composeClasses from '@mui/utils/composeClasses';
|
|
10
10
|
import useId from '@mui/utils/useId';
|
|
11
11
|
import refType from '@mui/utils/refType';
|
|
12
|
+
import useTimeout from '@mui/utils/useTimeout';
|
|
12
13
|
import ownerDocument from "../utils/ownerDocument.mjs";
|
|
13
14
|
import Menu from "../Menu/Menu.mjs";
|
|
14
15
|
import { StyledSelectSelect, StyledSelectIcon } from "../NativeSelect/NativeSelectInput.mjs";
|
|
15
16
|
import { isFilled } from "../InputBase/utils.mjs";
|
|
16
17
|
import { styled } from "../zero-styled/index.mjs";
|
|
17
18
|
import slotShouldForwardProp from "../styles/slotShouldForwardProp.mjs";
|
|
19
|
+
import useEnhancedEffect from "../utils/useEnhancedEffect.mjs";
|
|
20
|
+
import useEventCallback from "../utils/useEventCallback.mjs";
|
|
18
21
|
import useForkRef from "../utils/useForkRef.mjs";
|
|
19
22
|
import useControlled from "../utils/useControlled.mjs";
|
|
20
23
|
import selectClasses, { getSelectUtilityClasses } from "./selectClasses.mjs";
|
|
21
24
|
import { areEqualValues, isEmpty, getOpenInteractionType } from "./utils/index.mjs";
|
|
22
25
|
import { SelectFocusSourceProvider } from "./utils/SelectFocusSourceContext.mjs";
|
|
23
26
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
27
|
+
const OPENING_MOUSE_UP_BOUNDARY_OFFSET = 2;
|
|
28
|
+
// The initial mouseup may land on an item when the menu opens over the trigger.
|
|
29
|
+
const SELECTED_MOUSE_UP_DELAY = 400;
|
|
30
|
+
const UNSELECTED_MOUSE_UP_DELAY = 200;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns true when a native mouse event should be treated as happening inside
|
|
34
|
+
* the element, even if a portal or backdrop retargeted the event away from it.
|
|
35
|
+
*
|
|
36
|
+
* Select uses this for the opening mouseup: when the menu opens over the
|
|
37
|
+
* trigger, the release can target the backdrop or portaled menu even though the
|
|
38
|
+
* pointer is still inside the trigger or menu bounds.
|
|
39
|
+
*/
|
|
40
|
+
function isMouseEventInsideElement(event, element) {
|
|
41
|
+
if (!element) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const eventPath = event.composedPath();
|
|
45
|
+
if (eventPath.includes(element)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (event.target?.nodeType && element.contains(event.target)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
const rect = element.getBoundingClientRect();
|
|
52
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
53
|
+
// Hidden or transition-mounted elements do not have useful bounds to hit-test.
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
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;
|
|
57
|
+
}
|
|
24
58
|
const SelectSelect = styled(StyledSelectSelect, {
|
|
25
59
|
name: 'MuiSelect',
|
|
26
60
|
slot: 'Select',
|
|
@@ -147,6 +181,17 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
147
181
|
});
|
|
148
182
|
const inputRef = React.useRef(null);
|
|
149
183
|
const displayRef = React.useRef(null);
|
|
184
|
+
const paperRef = React.useRef(null);
|
|
185
|
+
const openRef = React.useRef(false);
|
|
186
|
+
const hasSelectedItemInListRef = React.useRef(false);
|
|
187
|
+
const openingMouseUpListenerCleanupRef = React.useRef(null);
|
|
188
|
+
const didPointerDownOnItemRef = React.useRef(false);
|
|
189
|
+
const selectionRef = React.useRef({
|
|
190
|
+
allowSelectedMouseUp: false,
|
|
191
|
+
allowUnselectedMouseUp: false
|
|
192
|
+
});
|
|
193
|
+
const selectedMouseUpTimer = useTimeout();
|
|
194
|
+
const unselectedMouseUpTimer = useTimeout();
|
|
150
195
|
const [displayNode, setDisplayNode] = React.useState(null);
|
|
151
196
|
const {
|
|
152
197
|
current: isOpenControlled
|
|
@@ -169,6 +214,42 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
169
214
|
value
|
|
170
215
|
}), [value]);
|
|
171
216
|
const open = displayNode !== null && openState;
|
|
217
|
+
useEnhancedEffect(() => {
|
|
218
|
+
openRef.current = open;
|
|
219
|
+
}, [open]);
|
|
220
|
+
const clearSelectionTimers = React.useCallback(() => {
|
|
221
|
+
selectedMouseUpTimer.clear();
|
|
222
|
+
unselectedMouseUpTimer.clear();
|
|
223
|
+
}, [selectedMouseUpTimer, unselectedMouseUpTimer]);
|
|
224
|
+
const resetMouseUpSelection = React.useCallback(() => {
|
|
225
|
+
clearSelectionTimers();
|
|
226
|
+
didPointerDownOnItemRef.current = false;
|
|
227
|
+
selectionRef.current = {
|
|
228
|
+
allowSelectedMouseUp: false,
|
|
229
|
+
allowUnselectedMouseUp: false
|
|
230
|
+
};
|
|
231
|
+
}, [clearSelectionTimers]);
|
|
232
|
+
const clearOpeningMouseUpListener = React.useCallback(() => {
|
|
233
|
+
if (openingMouseUpListenerCleanupRef.current) {
|
|
234
|
+
openingMouseUpListenerCleanupRef.current();
|
|
235
|
+
openingMouseUpListenerCleanupRef.current = null;
|
|
236
|
+
}
|
|
237
|
+
}, []);
|
|
238
|
+
React.useEffect(() => {
|
|
239
|
+
if (!open) {
|
|
240
|
+
resetMouseUpSelection();
|
|
241
|
+
clearOpeningMouseUpListener();
|
|
242
|
+
}
|
|
243
|
+
}, [open, resetMouseUpSelection, clearOpeningMouseUpListener]);
|
|
244
|
+
|
|
245
|
+
// Keep unmount cleanup separate from the `open` effect. Effect cleanups also run
|
|
246
|
+
// before the next effect, which would clear the opening mouseup listener while opening.
|
|
247
|
+
React.useEffect(() => {
|
|
248
|
+
return () => {
|
|
249
|
+
resetMouseUpSelection();
|
|
250
|
+
clearOpeningMouseUpListener();
|
|
251
|
+
};
|
|
252
|
+
}, [resetMouseUpSelection, clearOpeningMouseUpListener]);
|
|
172
253
|
React.useEffect(() => {
|
|
173
254
|
if (!open || !anchorElement || autoWidth) {
|
|
174
255
|
return undefined;
|
|
@@ -219,7 +300,11 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
219
300
|
}
|
|
220
301
|
return undefined;
|
|
221
302
|
}, [labelId]);
|
|
222
|
-
const update = (openParam, event) => {
|
|
303
|
+
const update = useEventCallback((openParam, event) => {
|
|
304
|
+
if (!openParam) {
|
|
305
|
+
resetMouseUpSelection();
|
|
306
|
+
clearOpeningMouseUpListener();
|
|
307
|
+
}
|
|
223
308
|
if (openParam) {
|
|
224
309
|
setOpenInteractionType(getOpenInteractionType(event));
|
|
225
310
|
if (onOpen) {
|
|
@@ -232,9 +317,33 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
232
317
|
}
|
|
233
318
|
}
|
|
234
319
|
if (!isOpenControlled) {
|
|
320
|
+
openRef.current = openParam;
|
|
235
321
|
setMenuMinWidthState(autoWidth ? null : anchorElement.clientWidth);
|
|
236
322
|
setOpenState(openParam);
|
|
237
323
|
}
|
|
324
|
+
});
|
|
325
|
+
const scheduleMouseUpSelection = () => {
|
|
326
|
+
resetMouseUpSelection();
|
|
327
|
+
|
|
328
|
+
// When there is no selected item in the list, a mousedown
|
|
329
|
+
// on the trigger followed by a quick mouseup over the first option can accidentally select
|
|
330
|
+
// within 200ms. Delay unselected mouseup to match the safer 400ms window.
|
|
331
|
+
if (!hasSelectedItemInListRef.current) {
|
|
332
|
+
selectedMouseUpTimer.start(SELECTED_MOUSE_UP_DELAY, () => {
|
|
333
|
+
selectionRef.current.allowSelectedMouseUp = true;
|
|
334
|
+
selectionRef.current.allowUnselectedMouseUp = true;
|
|
335
|
+
});
|
|
336
|
+
} else {
|
|
337
|
+
// mousedown -> move to unselected item -> mouseup should not select within 200ms.
|
|
338
|
+
unselectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
|
|
339
|
+
selectionRef.current.allowUnselectedMouseUp = true;
|
|
340
|
+
|
|
341
|
+
// mousedown -> mouseup on selected item should not select within 400ms.
|
|
342
|
+
selectedMouseUpTimer.start(UNSELECTED_MOUSE_UP_DELAY, () => {
|
|
343
|
+
selectionRef.current.allowSelectedMouseUp = true;
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
}
|
|
238
347
|
};
|
|
239
348
|
const handleMouseDown = event => {
|
|
240
349
|
onMouseDown?.(event);
|
|
@@ -245,6 +354,29 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
245
354
|
// Hijack the default focus behavior.
|
|
246
355
|
event.preventDefault();
|
|
247
356
|
displayRef.current.focus();
|
|
357
|
+
const doc = ownerDocument(event.currentTarget);
|
|
358
|
+
scheduleMouseUpSelection();
|
|
359
|
+
clearOpeningMouseUpListener();
|
|
360
|
+
const handleMouseUp = mouseEvent => {
|
|
361
|
+
openingMouseUpListenerCleanupRef.current = null;
|
|
362
|
+
if (!displayRef.current) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (isMouseEventInsideElement(mouseEvent, displayRef.current) || isMouseEventInsideElement(mouseEvent, paperRef.current)) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (!openRef.current && isOpenControlled) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
update(false, mouseEvent);
|
|
372
|
+
};
|
|
373
|
+
doc.addEventListener('mouseup', handleMouseUp, {
|
|
374
|
+
capture: true,
|
|
375
|
+
once: true
|
|
376
|
+
});
|
|
377
|
+
openingMouseUpListenerCleanupRef.current = () => {
|
|
378
|
+
doc.removeEventListener('mouseup', handleMouseUp, true);
|
|
379
|
+
};
|
|
248
380
|
update(true, event);
|
|
249
381
|
};
|
|
250
382
|
const handleClose = event => {
|
|
@@ -264,6 +396,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
264
396
|
}
|
|
265
397
|
};
|
|
266
398
|
const handleItemClick = child => event => {
|
|
399
|
+
didPointerDownOnItemRef.current = false;
|
|
267
400
|
let newValue;
|
|
268
401
|
|
|
269
402
|
// We use the tabindex attribute to signal the available options.
|
|
@@ -307,6 +440,19 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
307
440
|
update(false, event);
|
|
308
441
|
}
|
|
309
442
|
};
|
|
443
|
+
const handleItemMouseUp = (child, selected) => event => {
|
|
444
|
+
child.props.onMouseUp?.(event);
|
|
445
|
+
if (didPointerDownOnItemRef.current) {
|
|
446
|
+
didPointerDownOnItemRef.current = false;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
const disallowSelectedMouseUp = !selectionRef.current.allowSelectedMouseUp && selected;
|
|
450
|
+
const disallowUnselectedMouseUp = !selectionRef.current.allowUnselectedMouseUp && !selected;
|
|
451
|
+
if (disallowSelectedMouseUp || disallowUnselectedMouseUp) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
event.currentTarget.click();
|
|
455
|
+
};
|
|
310
456
|
const handleKeyDown = event => {
|
|
311
457
|
if (!readOnly) {
|
|
312
458
|
const validKeys = [' ', 'ArrowUp', 'ArrowDown',
|
|
@@ -380,7 +526,16 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
380
526
|
}
|
|
381
527
|
return /*#__PURE__*/React.cloneElement(child, {
|
|
382
528
|
'aria-selected': selected ? 'true' : 'false',
|
|
529
|
+
onMouseDown: event => {
|
|
530
|
+
didPointerDownOnItemRef.current = true;
|
|
531
|
+
child.props.onMouseDown?.(event);
|
|
532
|
+
},
|
|
533
|
+
onPointerDown: event => {
|
|
534
|
+
didPointerDownOnItemRef.current = true;
|
|
535
|
+
child.props.onPointerDown?.(event);
|
|
536
|
+
},
|
|
383
537
|
onClick: handleItemClick(child),
|
|
538
|
+
onMouseUp: handleItemMouseUp(child, selected),
|
|
384
539
|
onKeyUp: event => {
|
|
385
540
|
if (event.key === ' ') {
|
|
386
541
|
// otherwise our MenuItems dispatches a click event
|
|
@@ -399,6 +554,11 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
399
554
|
'data-value': child.props.value // Instead, we provide it as a data attribute.
|
|
400
555
|
});
|
|
401
556
|
});
|
|
557
|
+
|
|
558
|
+
// Keep the opening mouseup guard current without mutating refs during render.
|
|
559
|
+
useEnhancedEffect(() => {
|
|
560
|
+
hasSelectedItemInListRef.current = foundMatch;
|
|
561
|
+
}, [foundMatch]);
|
|
402
562
|
if (process.env.NODE_ENV !== 'production') {
|
|
403
563
|
// TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
|
|
404
564
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
@@ -448,6 +608,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
448
608
|
};
|
|
449
609
|
const classes = useUtilityClasses(ownerState);
|
|
450
610
|
const menuPaperSlotProps = typeof MenuProps.slotProps?.paper === 'function' ? MenuProps.slotProps.paper(ownerState) : MenuProps.slotProps?.paper;
|
|
611
|
+
const handlePaperRef = useForkRef(menuPaperSlotProps?.ref, paperRef);
|
|
451
612
|
const menuListSlotProps = typeof MenuProps.slotProps?.list === 'function' ? MenuProps.slotProps.list(ownerState) : MenuProps.slotProps?.list;
|
|
452
613
|
const listboxId = useId();
|
|
453
614
|
const nativeInputId = useId();
|
|
@@ -462,7 +623,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
462
623
|
"aria-expanded": open ? 'true' : 'false',
|
|
463
624
|
"aria-haspopup": "listbox",
|
|
464
625
|
"aria-label": ariaLabel,
|
|
465
|
-
"aria-labelledby":
|
|
626
|
+
"aria-labelledby": labelId,
|
|
466
627
|
"aria-describedby": ariaDescribedby,
|
|
467
628
|
"aria-required": required ? 'true' : undefined,
|
|
468
629
|
"aria-invalid": error ? 'true' : undefined,
|
|
@@ -529,6 +690,7 @@ const SelectInput = /*#__PURE__*/React.forwardRef(function SelectInput(props, re
|
|
|
529
690
|
},
|
|
530
691
|
paper: {
|
|
531
692
|
...menuPaperSlotProps,
|
|
693
|
+
ref: handlePaperRef,
|
|
532
694
|
style: {
|
|
533
695
|
minWidth: menuMinWidth,
|
|
534
696
|
...menuPaperSlotProps?.style
|
package/Slide/Slide.js
CHANGED
|
@@ -26,33 +26,46 @@ const hiddenStyles = {
|
|
|
26
26
|
visibility: 'hidden'
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Detects SwipeableDrawer's active-swipe `translate(x, y)` transform.
|
|
31
|
+
* Keep this in sync with SwipeableDrawer.setPosition.
|
|
32
|
+
*/
|
|
33
|
+
function isGestureTranslate(transform) {
|
|
34
|
+
return typeof transform === 'string' && /^translate\(.+,\s*.+\)$/.test(transform);
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
// Translate the node so it can't be seen on the screen.
|
|
30
38
|
// Later, we're going to translate the node back to its original location with `none`.
|
|
31
|
-
function getTranslateValue(direction, node, resolvedContainer) {
|
|
39
|
+
function getTranslateValue(direction, node, resolvedContainer, options = {}) {
|
|
40
|
+
const {
|
|
41
|
+
resetInlineTransform = true
|
|
42
|
+
} = options;
|
|
32
43
|
const containerRect = resolvedContainer && resolvedContainer.getBoundingClientRect();
|
|
33
44
|
const containerWindow = (0, _utils2.ownerWindow)(node);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
offsetX = parseInt(transformValues[4], 10);
|
|
54
|
-
offsetY = parseInt(transformValues[5], 10);
|
|
45
|
+
let rect;
|
|
46
|
+
let transform;
|
|
47
|
+
if (resetInlineTransform) {
|
|
48
|
+
// Clear the inline transform and transition before reading layout and computed
|
|
49
|
+
// style so we compute from the element's natural position, not its previous
|
|
50
|
+
// off-screen translation.
|
|
51
|
+
const previousTransform = node.style.transform;
|
|
52
|
+
const previousTransition = node.style.transition;
|
|
53
|
+
node.style.transition = '';
|
|
54
|
+
node.style.transform = '';
|
|
55
|
+
rect = node.getBoundingClientRect();
|
|
56
|
+
const computedStyle = containerWindow.getComputedStyle(node);
|
|
57
|
+
transform = computedStyle.getPropertyValue('transform');
|
|
58
|
+
node.style.transform = previousTransform;
|
|
59
|
+
node.style.transition = previousTransition;
|
|
60
|
+
} else {
|
|
61
|
+
rect = node.getBoundingClientRect();
|
|
62
|
+
const computedStyle = containerWindow.getComputedStyle(node);
|
|
63
|
+
transform = computedStyle.getPropertyValue('transform');
|
|
55
64
|
}
|
|
65
|
+
const {
|
|
66
|
+
offsetX,
|
|
67
|
+
offsetY
|
|
68
|
+
} = (0, _utils.getTranslateOffsets)(transform);
|
|
56
69
|
if (direction === 'left') {
|
|
57
70
|
if (containerRect) {
|
|
58
71
|
return `translateX(${containerRect.right + offsetX - rect.left}px)`;
|
|
@@ -81,9 +94,9 @@ function getTranslateValue(direction, node, resolvedContainer) {
|
|
|
81
94
|
function resolveContainer(containerPropProp) {
|
|
82
95
|
return typeof containerPropProp === 'function' ? containerPropProp() : containerPropProp;
|
|
83
96
|
}
|
|
84
|
-
function setTranslateValue(direction, node, containerProp) {
|
|
97
|
+
function setTranslateValue(direction, node, containerProp, options) {
|
|
85
98
|
const resolvedContainer = resolveContainer(containerProp);
|
|
86
|
-
const transform = getTranslateValue(direction, node, resolvedContainer);
|
|
99
|
+
const transform = getTranslateValue(direction, node, resolvedContainer, options);
|
|
87
100
|
if (transform) {
|
|
88
101
|
node.style.transform = transform;
|
|
89
102
|
}
|
|
@@ -122,6 +135,7 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
122
135
|
...other
|
|
123
136
|
} = props;
|
|
124
137
|
const childrenRef = React.useRef(null);
|
|
138
|
+
const preserveInlineTransformRef = React.useRef(false);
|
|
125
139
|
const handleRef = (0, _useForkRef.default)((0, _getReactElementRef.default)(children), childrenRef, ref);
|
|
126
140
|
const handleEnter = (0, _utils.normalizedTransitionCallback)(childrenRef, (node, isAppearing) => {
|
|
127
141
|
setTranslateValue(direction, node, containerProp);
|
|
@@ -155,12 +169,20 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
155
169
|
mode: 'exit'
|
|
156
170
|
});
|
|
157
171
|
node.style.transition = theme.transitions.create('transform', transitionProps);
|
|
158
|
-
|
|
172
|
+
const preserveInlineTransform = isGestureTranslate(node.style.transform);
|
|
173
|
+
preserveInlineTransformRef.current = preserveInlineTransform;
|
|
174
|
+
|
|
175
|
+
// Preserve SwipeableDrawer's inline gesture transform during exit. Slide's
|
|
176
|
+
// own off-screen translateX/Y transforms still use the reset path.
|
|
177
|
+
setTranslateValue(direction, node, containerProp, {
|
|
178
|
+
resetInlineTransform: !preserveInlineTransform
|
|
179
|
+
});
|
|
159
180
|
if (onExit) {
|
|
160
181
|
onExit(node);
|
|
161
182
|
}
|
|
162
183
|
});
|
|
163
184
|
const handleExited = (0, _utils.normalizedTransitionCallback)(childrenRef, node => {
|
|
185
|
+
preserveInlineTransformRef.current = false;
|
|
164
186
|
// No need for transitions when the component is hidden
|
|
165
187
|
node.style.transition = '';
|
|
166
188
|
if (onExited) {
|
|
@@ -196,7 +218,7 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
196
218
|
};
|
|
197
219
|
}, [direction, inProp, containerProp]);
|
|
198
220
|
React.useEffect(() => {
|
|
199
|
-
if (!inProp) {
|
|
221
|
+
if (!inProp && !preserveInlineTransformRef.current) {
|
|
200
222
|
// We need to update the position of the drawer when the direction change and
|
|
201
223
|
// when it's hidden.
|
|
202
224
|
updatePosition();
|
package/Slide/Slide.mjs
CHANGED
|
@@ -11,40 +11,53 @@ import isLayoutSupported from "../utils/isLayoutSupported.mjs";
|
|
|
11
11
|
import debounce from "../utils/debounce.mjs";
|
|
12
12
|
import useForkRef from "../utils/useForkRef.mjs";
|
|
13
13
|
import { useTheme } from "../zero-styled/index.mjs";
|
|
14
|
-
import { normalizedTransitionCallback, reflow, getTransitionProps } from "../transitions/utils.mjs";
|
|
14
|
+
import { normalizedTransitionCallback, reflow, getTransitionProps, getTranslateOffsets } from "../transitions/utils.mjs";
|
|
15
15
|
import { ownerWindow } from "../utils/index.mjs";
|
|
16
16
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
17
17
|
const hiddenStyles = {
|
|
18
18
|
visibility: 'hidden'
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Detects SwipeableDrawer's active-swipe `translate(x, y)` transform.
|
|
23
|
+
* Keep this in sync with SwipeableDrawer.setPosition.
|
|
24
|
+
*/
|
|
25
|
+
function isGestureTranslate(transform) {
|
|
26
|
+
return typeof transform === 'string' && /^translate\(.+,\s*.+\)$/.test(transform);
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
// Translate the node so it can't be seen on the screen.
|
|
22
30
|
// Later, we're going to translate the node back to its original location with `none`.
|
|
23
|
-
function getTranslateValue(direction, node, resolvedContainer) {
|
|
31
|
+
function getTranslateValue(direction, node, resolvedContainer, options = {}) {
|
|
32
|
+
const {
|
|
33
|
+
resetInlineTransform = true
|
|
34
|
+
} = options;
|
|
24
35
|
const containerRect = resolvedContainer && resolvedContainer.getBoundingClientRect();
|
|
25
36
|
const containerWindow = ownerWindow(node);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
offsetX = parseInt(transformValues[4], 10);
|
|
46
|
-
offsetY = parseInt(transformValues[5], 10);
|
|
37
|
+
let rect;
|
|
38
|
+
let transform;
|
|
39
|
+
if (resetInlineTransform) {
|
|
40
|
+
// Clear the inline transform and transition before reading layout and computed
|
|
41
|
+
// style so we compute from the element's natural position, not its previous
|
|
42
|
+
// off-screen translation.
|
|
43
|
+
const previousTransform = node.style.transform;
|
|
44
|
+
const previousTransition = node.style.transition;
|
|
45
|
+
node.style.transition = '';
|
|
46
|
+
node.style.transform = '';
|
|
47
|
+
rect = node.getBoundingClientRect();
|
|
48
|
+
const computedStyle = containerWindow.getComputedStyle(node);
|
|
49
|
+
transform = computedStyle.getPropertyValue('transform');
|
|
50
|
+
node.style.transform = previousTransform;
|
|
51
|
+
node.style.transition = previousTransition;
|
|
52
|
+
} else {
|
|
53
|
+
rect = node.getBoundingClientRect();
|
|
54
|
+
const computedStyle = containerWindow.getComputedStyle(node);
|
|
55
|
+
transform = computedStyle.getPropertyValue('transform');
|
|
47
56
|
}
|
|
57
|
+
const {
|
|
58
|
+
offsetX,
|
|
59
|
+
offsetY
|
|
60
|
+
} = getTranslateOffsets(transform);
|
|
48
61
|
if (direction === 'left') {
|
|
49
62
|
if (containerRect) {
|
|
50
63
|
return `translateX(${containerRect.right + offsetX - rect.left}px)`;
|
|
@@ -73,9 +86,9 @@ function getTranslateValue(direction, node, resolvedContainer) {
|
|
|
73
86
|
function resolveContainer(containerPropProp) {
|
|
74
87
|
return typeof containerPropProp === 'function' ? containerPropProp() : containerPropProp;
|
|
75
88
|
}
|
|
76
|
-
export function setTranslateValue(direction, node, containerProp) {
|
|
89
|
+
export function setTranslateValue(direction, node, containerProp, options) {
|
|
77
90
|
const resolvedContainer = resolveContainer(containerProp);
|
|
78
|
-
const transform = getTranslateValue(direction, node, resolvedContainer);
|
|
91
|
+
const transform = getTranslateValue(direction, node, resolvedContainer, options);
|
|
79
92
|
if (transform) {
|
|
80
93
|
node.style.transform = transform;
|
|
81
94
|
}
|
|
@@ -114,6 +127,7 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
114
127
|
...other
|
|
115
128
|
} = props;
|
|
116
129
|
const childrenRef = React.useRef(null);
|
|
130
|
+
const preserveInlineTransformRef = React.useRef(false);
|
|
117
131
|
const handleRef = useForkRef(getReactElementRef(children), childrenRef, ref);
|
|
118
132
|
const handleEnter = normalizedTransitionCallback(childrenRef, (node, isAppearing) => {
|
|
119
133
|
setTranslateValue(direction, node, containerProp);
|
|
@@ -147,12 +161,20 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
147
161
|
mode: 'exit'
|
|
148
162
|
});
|
|
149
163
|
node.style.transition = theme.transitions.create('transform', transitionProps);
|
|
150
|
-
|
|
164
|
+
const preserveInlineTransform = isGestureTranslate(node.style.transform);
|
|
165
|
+
preserveInlineTransformRef.current = preserveInlineTransform;
|
|
166
|
+
|
|
167
|
+
// Preserve SwipeableDrawer's inline gesture transform during exit. Slide's
|
|
168
|
+
// own off-screen translateX/Y transforms still use the reset path.
|
|
169
|
+
setTranslateValue(direction, node, containerProp, {
|
|
170
|
+
resetInlineTransform: !preserveInlineTransform
|
|
171
|
+
});
|
|
151
172
|
if (onExit) {
|
|
152
173
|
onExit(node);
|
|
153
174
|
}
|
|
154
175
|
});
|
|
155
176
|
const handleExited = normalizedTransitionCallback(childrenRef, node => {
|
|
177
|
+
preserveInlineTransformRef.current = false;
|
|
156
178
|
// No need for transitions when the component is hidden
|
|
157
179
|
node.style.transition = '';
|
|
158
180
|
if (onExited) {
|
|
@@ -188,7 +210,7 @@ const Slide = /*#__PURE__*/React.forwardRef(function Slide(props, ref) {
|
|
|
188
210
|
};
|
|
189
211
|
}, [direction, inProp, containerProp]);
|
|
190
212
|
React.useEffect(() => {
|
|
191
|
-
if (!inProp) {
|
|
213
|
+
if (!inProp && !preserveInlineTransformRef.current) {
|
|
192
214
|
// We need to update the position of the drawer when the direction change and
|
|
193
215
|
// when it's hidden.
|
|
194
216
|
updatePosition();
|
package/Slider/Slider.js
CHANGED
|
@@ -138,6 +138,10 @@ const SliderRail = exports.SliderRail = (0, _zeroStyled.styled)('span', {
|
|
|
138
138
|
borderRadius: 'inherit',
|
|
139
139
|
backgroundColor: 'currentColor',
|
|
140
140
|
opacity: 0.38,
|
|
141
|
+
'@media (forced-colors: active)': {
|
|
142
|
+
border: '1px solid transparent',
|
|
143
|
+
boxSizing: 'border-box'
|
|
144
|
+
},
|
|
141
145
|
variants: [{
|
|
142
146
|
props: {
|
|
143
147
|
orientation: 'horizontal'
|
|
@@ -187,7 +191,9 @@ const SliderTrack = exports.SliderTrack = (0, _zeroStyled.styled)('span', {
|
|
|
187
191
|
size: 'small'
|
|
188
192
|
},
|
|
189
193
|
style: {
|
|
190
|
-
|
|
194
|
+
'@media (forced-colors: none)': {
|
|
195
|
+
border: 'none'
|
|
196
|
+
}
|
|
191
197
|
}
|
|
192
198
|
}, {
|
|
193
199
|
props: {
|
|
@@ -256,6 +262,9 @@ const SliderThumb = exports.SliderThumb = (0, _zeroStyled.styled)('span', {
|
|
|
256
262
|
transition: theme.transitions.create(['box-shadow', 'left', 'bottom'], {
|
|
257
263
|
duration: theme.transitions.duration.shortest
|
|
258
264
|
}),
|
|
265
|
+
'@media (forced-colors: active)': {
|
|
266
|
+
border: '1px solid ButtonBorder'
|
|
267
|
+
},
|
|
259
268
|
'&::before': {
|
|
260
269
|
position: 'absolute',
|
|
261
270
|
content: '""',
|
package/Slider/Slider.mjs
CHANGED
|
@@ -131,6 +131,10 @@ export const SliderRail = styled('span', {
|
|
|
131
131
|
borderRadius: 'inherit',
|
|
132
132
|
backgroundColor: 'currentColor',
|
|
133
133
|
opacity: 0.38,
|
|
134
|
+
'@media (forced-colors: active)': {
|
|
135
|
+
border: '1px solid transparent',
|
|
136
|
+
boxSizing: 'border-box'
|
|
137
|
+
},
|
|
134
138
|
variants: [{
|
|
135
139
|
props: {
|
|
136
140
|
orientation: 'horizontal'
|
|
@@ -180,7 +184,9 @@ export const SliderTrack = styled('span', {
|
|
|
180
184
|
size: 'small'
|
|
181
185
|
},
|
|
182
186
|
style: {
|
|
183
|
-
|
|
187
|
+
'@media (forced-colors: none)': {
|
|
188
|
+
border: 'none'
|
|
189
|
+
}
|
|
184
190
|
}
|
|
185
191
|
}, {
|
|
186
192
|
props: {
|
|
@@ -249,6 +255,9 @@ export const SliderThumb = styled('span', {
|
|
|
249
255
|
transition: theme.transitions.create(['box-shadow', 'left', 'bottom'], {
|
|
250
256
|
duration: theme.transitions.duration.shortest
|
|
251
257
|
}),
|
|
258
|
+
'@media (forced-colors: active)': {
|
|
259
|
+
border: '1px solid ButtonBorder'
|
|
260
|
+
},
|
|
252
261
|
'&::before': {
|
|
253
262
|
position: 'absolute',
|
|
254
263
|
content: '""',
|
package/Slider/useSlider.js
CHANGED
|
@@ -20,6 +20,7 @@ var _visuallyHidden = _interopRequireDefault(require("@mui/utils/visuallyHidden"
|
|
|
20
20
|
var _clamp = _interopRequireDefault(require("@mui/utils/clamp"));
|
|
21
21
|
var _extractEventHandlers = _interopRequireDefault(require("@mui/utils/extractEventHandlers"));
|
|
22
22
|
var _areArraysEqual = _interopRequireDefault(require("../utils/areArraysEqual"));
|
|
23
|
+
var _contains = _interopRequireDefault(require("../utils/contains"));
|
|
23
24
|
var _getActiveElement = _interopRequireDefault(require("../utils/getActiveElement"));
|
|
24
25
|
const INTENTIONAL_DRAG_COUNT_THRESHOLD = 2;
|
|
25
26
|
const EMPTY_MARKS = [];
|
|
@@ -103,7 +104,7 @@ function setValueIndex(values, newValue, index) {
|
|
|
103
104
|
function focusThumb(sliderRef, activeIndex, setActive, focusVisible) {
|
|
104
105
|
const doc = (0, _ownerDocument.default)(sliderRef.current);
|
|
105
106
|
const activeElement = (0, _getActiveElement.default)(doc);
|
|
106
|
-
if (!sliderRef.current
|
|
107
|
+
if (!(0, _contains.default)(sliderRef.current, activeElement) || Number(activeElement?.getAttribute('data-index')) !== activeIndex) {
|
|
107
108
|
const input = sliderRef.current?.querySelector(`[type="range"][data-index="${activeIndex}"]`);
|
|
108
109
|
if (input != null) {
|
|
109
110
|
if (focusVisible == null) {
|
|
@@ -388,7 +389,7 @@ function useSlider(parameters) {
|
|
|
388
389
|
};
|
|
389
390
|
(0, _useEnhancedEffect.default)(() => {
|
|
390
391
|
const activeElement = (0, _getActiveElement.default)((0, _ownerDocument.default)(sliderRef.current));
|
|
391
|
-
if (disabled && sliderRef.current
|
|
392
|
+
if (disabled && (0, _contains.default)(sliderRef.current, activeElement)) {
|
|
392
393
|
// This is necessary because Firefox and Safari will keep focus
|
|
393
394
|
// on a disabled element:
|
|
394
395
|
// https://codesandbox.io/p/sandbox/mui-pr-22247-forked-h151h?file=/src/App.js
|
package/Slider/useSlider.mjs
CHANGED
|
@@ -11,6 +11,7 @@ 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.mjs";
|
|
14
|
+
import contains from "../utils/contains.mjs";
|
|
14
15
|
import getActiveElement from "../utils/getActiveElement.mjs";
|
|
15
16
|
const INTENTIONAL_DRAG_COUNT_THRESHOLD = 2;
|
|
16
17
|
const EMPTY_MARKS = [];
|
|
@@ -94,7 +95,7 @@ function setValueIndex(values, newValue, index) {
|
|
|
94
95
|
function focusThumb(sliderRef, activeIndex, setActive, focusVisible) {
|
|
95
96
|
const doc = ownerDocument(sliderRef.current);
|
|
96
97
|
const activeElement = getActiveElement(doc);
|
|
97
|
-
if (!sliderRef.current
|
|
98
|
+
if (!contains(sliderRef.current, activeElement) || Number(activeElement?.getAttribute('data-index')) !== activeIndex) {
|
|
98
99
|
const input = sliderRef.current?.querySelector(`[type="range"][data-index="${activeIndex}"]`);
|
|
99
100
|
if (input != null) {
|
|
100
101
|
if (focusVisible == null) {
|
|
@@ -378,7 +379,7 @@ export function useSlider(parameters) {
|
|
|
378
379
|
};
|
|
379
380
|
useEnhancedEffect(() => {
|
|
380
381
|
const activeElement = getActiveElement(ownerDocument(sliderRef.current));
|
|
381
|
-
if (disabled && sliderRef.current
|
|
382
|
+
if (disabled && contains(sliderRef.current, activeElement)) {
|
|
382
383
|
// This is necessary because Firefox and Safari will keep focus
|
|
383
384
|
// on a disabled element:
|
|
384
385
|
// https://codesandbox.io/p/sandbox/mui-pr-22247-forked-h151h?file=/src/App.js
|