210 lines
No EOL
7.3 KiB
JavaScript
210 lines
No EOL
7.3 KiB
JavaScript
'use client';
|
|
|
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
const _excluded = ["autoFocus", "onChange", "className", "classes", "disabled", "readOnly", "items", "active", "slots", "slotProps", "skipDisabled"];
|
|
import * as React from 'react';
|
|
import clsx from 'clsx';
|
|
import { alpha, styled, useThemeProps } from '@mui/material/styles';
|
|
import composeClasses from '@mui/utils/composeClasses';
|
|
import MenuList from '@mui/material/MenuList';
|
|
import MenuItem from '@mui/material/MenuItem';
|
|
import useForkRef from '@mui/utils/useForkRef';
|
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
import { getMultiSectionDigitalClockSectionUtilityClass } from "./multiSectionDigitalClockSectionClasses.js";
|
|
import { DIGITAL_CLOCK_VIEW_HEIGHT, MULTI_SECTION_CLOCK_SECTION_WIDTH } from "../internals/constants/dimensions.js";
|
|
import { getFocusedListItemIndex } from "../internals/utils/utils.js";
|
|
import { usePickerPrivateContext } from "../internals/hooks/usePickerPrivateContext.js";
|
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
const useUtilityClasses = classes => {
|
|
const slots = {
|
|
root: ['root'],
|
|
item: ['item']
|
|
};
|
|
return composeClasses(slots, getMultiSectionDigitalClockSectionUtilityClass, classes);
|
|
};
|
|
const MultiSectionDigitalClockSectionRoot = styled(MenuList, {
|
|
name: 'MuiMultiSectionDigitalClockSection',
|
|
slot: 'Root'
|
|
})(({
|
|
theme
|
|
}) => ({
|
|
maxHeight: DIGITAL_CLOCK_VIEW_HEIGHT,
|
|
width: 56,
|
|
padding: 0,
|
|
overflow: 'hidden',
|
|
scrollbarWidth: 'thin',
|
|
'@media (prefers-reduced-motion: no-preference)': {
|
|
scrollBehavior: 'auto'
|
|
},
|
|
'@media (pointer: fine)': {
|
|
'&:hover': {
|
|
overflowY: 'auto'
|
|
}
|
|
},
|
|
'@media (pointer: none), (pointer: coarse)': {
|
|
overflowY: 'auto'
|
|
},
|
|
'&:not(:first-of-type)': {
|
|
borderLeft: `1px solid ${(theme.vars || theme).palette.divider}`
|
|
},
|
|
'&::after': {
|
|
display: 'block',
|
|
content: '""',
|
|
// subtracting the height of one item, extra margin and borders to make sure the max height is correct
|
|
height: 'calc(100% - 40px - 6px)'
|
|
},
|
|
variants: [{
|
|
props: {
|
|
hasDigitalClockAlreadyBeenRendered: true
|
|
},
|
|
style: {
|
|
'@media (prefers-reduced-motion: no-preference)': {
|
|
scrollBehavior: 'smooth'
|
|
}
|
|
}
|
|
}]
|
|
}));
|
|
const MultiSectionDigitalClockSectionItem = styled(MenuItem, {
|
|
name: 'MuiMultiSectionDigitalClockSection',
|
|
slot: 'Item'
|
|
})(({
|
|
theme
|
|
}) => ({
|
|
padding: 8,
|
|
margin: '2px 4px',
|
|
width: MULTI_SECTION_CLOCK_SECTION_WIDTH,
|
|
justifyContent: 'center',
|
|
'&:first-of-type': {
|
|
marginTop: 4
|
|
},
|
|
'&:hover': {
|
|
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity)
|
|
},
|
|
'&.Mui-selected': {
|
|
backgroundColor: (theme.vars || theme).palette.primary.main,
|
|
color: (theme.vars || theme).palette.primary.contrastText,
|
|
'&:focus-visible, &:hover': {
|
|
backgroundColor: (theme.vars || theme).palette.primary.dark
|
|
}
|
|
},
|
|
'&.Mui-focusVisible': {
|
|
backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.focusOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.focusOpacity)
|
|
}
|
|
}));
|
|
/**
|
|
* @ignore - internal component.
|
|
*/
|
|
export const MultiSectionDigitalClockSection = /*#__PURE__*/React.forwardRef(function MultiSectionDigitalClockSection(inProps, ref) {
|
|
const containerRef = React.useRef(null);
|
|
const handleRef = useForkRef(ref, containerRef);
|
|
const previousActive = React.useRef(null);
|
|
const props = useThemeProps({
|
|
props: inProps,
|
|
name: 'MuiMultiSectionDigitalClockSection'
|
|
});
|
|
const {
|
|
autoFocus,
|
|
onChange,
|
|
className,
|
|
classes: classesProp,
|
|
disabled,
|
|
readOnly,
|
|
items,
|
|
active,
|
|
slots,
|
|
slotProps,
|
|
skipDisabled
|
|
} = props,
|
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
const {
|
|
ownerState: pickerOwnerState
|
|
} = usePickerPrivateContext();
|
|
const ownerState = _extends({}, pickerOwnerState, {
|
|
hasDigitalClockAlreadyBeenRendered: !!containerRef.current
|
|
});
|
|
const classes = useUtilityClasses(classesProp);
|
|
const DigitalClockSectionItem = slots?.digitalClockSectionItem ?? MultiSectionDigitalClockSectionItem;
|
|
useEnhancedEffect(() => {
|
|
if (containerRef.current === null) {
|
|
return;
|
|
}
|
|
const activeItem = containerRef.current.querySelector('[role="option"][tabindex="0"], [role="option"][aria-selected="true"]');
|
|
if (active && autoFocus && activeItem) {
|
|
activeItem.focus();
|
|
}
|
|
if (!activeItem || previousActive.current === activeItem) {
|
|
return;
|
|
}
|
|
previousActive.current = activeItem;
|
|
const offsetTop = activeItem.offsetTop;
|
|
|
|
// Subtracting the 4px of extra margin intended for the first visible section item
|
|
containerRef.current.scrollTop = offsetTop - 4;
|
|
});
|
|
const focusedOptionIndex = items.findIndex(item => item.isFocused(item.value));
|
|
const handleKeyDown = event => {
|
|
switch (event.key) {
|
|
case 'PageUp':
|
|
{
|
|
const newIndex = getFocusedListItemIndex(containerRef.current) - 5;
|
|
const children = containerRef.current.children;
|
|
const newFocusedIndex = Math.max(0, newIndex);
|
|
const childToFocus = children[newFocusedIndex];
|
|
if (childToFocus) {
|
|
childToFocus.focus();
|
|
}
|
|
event.preventDefault();
|
|
break;
|
|
}
|
|
case 'PageDown':
|
|
{
|
|
const newIndex = getFocusedListItemIndex(containerRef.current) + 5;
|
|
const children = containerRef.current.children;
|
|
const newFocusedIndex = Math.min(children.length - 1, newIndex);
|
|
const childToFocus = children[newFocusedIndex];
|
|
if (childToFocus) {
|
|
childToFocus.focus();
|
|
}
|
|
event.preventDefault();
|
|
break;
|
|
}
|
|
default:
|
|
}
|
|
};
|
|
return /*#__PURE__*/_jsx(MultiSectionDigitalClockSectionRoot, _extends({
|
|
ref: handleRef,
|
|
className: clsx(classes.root, className),
|
|
ownerState: ownerState,
|
|
autoFocusItem: autoFocus && active,
|
|
role: "listbox",
|
|
onKeyDown: handleKeyDown
|
|
}, other, {
|
|
children: items.map((option, index) => {
|
|
const isItemDisabled = option.isDisabled?.(option.value);
|
|
const isDisabled = disabled || isItemDisabled;
|
|
if (skipDisabled && isDisabled) {
|
|
return null;
|
|
}
|
|
const isSelected = option.isSelected(option.value);
|
|
const tabIndex = focusedOptionIndex === index || focusedOptionIndex === -1 && index === 0 ? 0 : -1;
|
|
return /*#__PURE__*/_jsx(DigitalClockSectionItem, _extends({
|
|
onClick: () => !readOnly && onChange(option.value),
|
|
selected: isSelected,
|
|
disabled: isDisabled,
|
|
disableRipple: readOnly,
|
|
role: "option"
|
|
// aria-readonly is not supported here and does not have any effect
|
|
,
|
|
"aria-disabled": readOnly || isDisabled || undefined,
|
|
"aria-label": option.ariaLabel,
|
|
"aria-selected": isSelected,
|
|
tabIndex: tabIndex,
|
|
className: classes.item
|
|
}, slotProps?.digitalClockSectionItem, {
|
|
children: option.label
|
|
}), option.label);
|
|
})
|
|
}));
|
|
});
|
|
if (process.env.NODE_ENV !== "production") MultiSectionDigitalClockSection.displayName = "MultiSectionDigitalClockSection"; |