@mui/base
Version:
MUI Base is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.
95 lines (93 loc) • 2.63 kB
JavaScript
'use client';
import * as React from 'react';
import { unstable_useForkRef as useForkRef } from '@mui/utils';
import { DropdownContext } from "../useDropdown/DropdownContext.js";
import { DropdownActionTypes } from "../useDropdown/useDropdown.types.js";
import { useButton } from "../useButton/useButton.js";
import { combineHooksSlotProps } from "../utils/combineHooksSlotProps.js";
import { extractEventHandlers } from "../utils/index.js";
/**
*
* Demos:
*
* - [Menu](https://mui.com/base-ui/react-menu/#hooks)
*
* API:
*
* - [useMenuButton API](https://mui.com/base-ui/react-menu/hooks-api/#use-menu-button)
*/
export function useMenuButton(parameters = {}) {
const {
disabled = false,
focusableWhenDisabled,
rootRef: externalRef
} = parameters;
const menuContext = React.useContext(DropdownContext);
if (menuContext === null) {
throw new Error('useMenuButton: no menu context available.');
}
const {
state,
dispatch,
registerTrigger,
popupId
} = menuContext;
const {
getRootProps: getButtonRootProps,
rootRef: buttonRootRef,
active
} = useButton({
disabled,
focusableWhenDisabled,
rootRef: externalRef
});
const handleRef = useForkRef(buttonRootRef, registerTrigger);
const createHandleClick = otherHandlers => event => {
otherHandlers.onClick?.(event);
if (event.defaultMuiPrevented) {
return;
}
dispatch({
type: DropdownActionTypes.toggle,
event
});
};
const createHandleKeyDown = otherHandlers => event => {
otherHandlers.onKeyDown?.(event);
if (event.defaultMuiPrevented) {
return;
}
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
event.preventDefault();
dispatch({
type: DropdownActionTypes.open,
event
});
}
};
const getOwnRootProps = (otherHandlers = {}) => ({
onClick: createHandleClick(otherHandlers),
onKeyDown: createHandleKeyDown(otherHandlers)
});
const getRootProps = (externalProps = {}) => {
const externalEventHandlers = extractEventHandlers(externalProps);
const getCombinedProps = combineHooksSlotProps(getOwnRootProps, getButtonRootProps);
return {
'aria-haspopup': 'menu',
'aria-expanded': state.open,
'aria-controls': popupId,
...externalProps,
...externalEventHandlers,
...getCombinedProps(externalEventHandlers),
tabIndex: 0,
// this is needed to make the button focused after click in Safari
ref: handleRef
};
};
return {
active,
getRootProps,
open: state.open,
rootRef: handleRef
};
}