codekingpro/portable-devtools
114k
1import { makeStyles } from '@mui/styles';2import React, { useRef } from 'react';3import CheckIcon from '@mui/icons-material/Check';4import PropTypes from 'prop-types';5 6import {7 MenuItem,8 ControlledMenu,9 applyStatics,10 Menu,11 SubMenu,12} from '@szhsin/react-menu';13export {MenuDivider as PgMenuDivider} from '@szhsin/react-menu';14import { shortcutToString } from './ShortcutTitle';15import clsx from 'clsx';16import CustomPropTypes from '../custom_prop_types';17 18const useStyles = makeStyles((theme)=>({19 menu: {20 '& .szh-menu': {21 padding: '4px 0px',22 zIndex: 1005,23 backgroundColor: theme.palette.background.default,24 color: theme.palette.text.primary,25 border: `1px solid ${theme.otherVars.borderColor}`26 },27 '& .szh-menu__divider': {28 margin: 0,29 background: theme.otherVars.borderColor,30 },31 '& .szh-menu__item': {32 display: 'flex',33 padding: '3px 12px',34 '&:after': {35 right: '0.75rem',36 },37 '&.szh-menu__item--active, &.szh-menu__item--hover': {38 backgroundColor: theme.palette.primary.main,39 color: theme.palette.primary.contrastText,40 },41 '&.szh-menu__item--disabled':{42 color: theme.palette.text.muted,43 }44 }45 },46 checkIcon: {47 width: '1.3rem',48 },49 hideCheck: {50 visibility: 'hidden',51 },52 shortcut: {53 marginLeft: 'auto',54 fontSize: '0.8em',55 paddingLeft: '12px',56 }57}));58 59export function PgMenu({open, className='', label, menuButton=null, ...props}) {60 const classes = useStyles();61 const state = open ? 'open' : 'closed';62 props.anchorRef?.current?.setAttribute('data-state', state);63 64 if(menuButton) {65 return <Menu66 {...props}67 menuButton={menuButton}68 className={clsx(classes.menu, className)}69 aria-label={label || 'Menu'}70 onContextMenu={(e)=>e.preventDefault()}71 viewScroll='close'72 />;73 }74 return (75 <ControlledMenu76 state={state}77 {...props}78 className={clsx(classes.menu, className)}79 aria-label={label || 'Menu'}80 data-state={state}81 onContextMenu={(e)=>e.preventDefault()}82 viewScroll='close'83 />84 );85}86 87PgMenu.propTypes = {88 open: PropTypes.bool,89 className: CustomPropTypes.className,90 label: PropTypes.string,91 anchorRef: CustomPropTypes.ref,92 menuButton: PropTypes.element,93};94 95export const PgSubMenu = applyStatics(SubMenu)(({label, ...props})=>{96 return (97 <SubMenu label={label} itemProps={{'data-label': label}} {...props} />98 );99});100 101export const PgMenuItem = applyStatics(MenuItem)(({hasCheck=false, checked=false, accesskey, shortcut, children, closeOnCheck=false, ...props})=>{102 const classes = useStyles();103 let onClick = props.onClick;104 if(hasCheck) {105 onClick = (e)=>{106 e.keepOpen = !closeOnCheck;107 props.onClick(e);108 };109 }110 const dataLabel = typeof(children) == 'string' ? children : props.datalabel;111 return <MenuItem {...props} onClick={onClick} data-label={dataLabel} data-checked={checked}>112 {hasCheck && <CheckIcon className={classes.checkIcon} style={checked ? {} : {visibility: 'hidden'}} data-label="CheckIcon"/>}113 {children}114 {(shortcut || accesskey) && <div className={classes.shortcut}>({shortcutToString(shortcut, accesskey)})</div>}115 </MenuItem>;116});117 118PgMenuItem.propTypes = {119 hasCheck: PropTypes.bool,120 checked: PropTypes.bool,121 accesskey: PropTypes.string,122 shortcut: CustomPropTypes.shortcut,123 children: CustomPropTypes.children,124 closeOnCheck: PropTypes.bool,125 onClick: PropTypes.func,126 dataLabel: PropTypes.string,127};128 129export function usePgMenuGroup() {130 const [openMenuName, setOpenMenuName] = React.useState(null);131 const prevMenuOpenIdRef = useRef(null);132 133 const toggleMenu = React.useCallback((e)=>{134 setOpenMenuName(()=>{135 return prevMenuOpenIdRef.current == e.currentTarget?.name ? null : e.currentTarget?.name;136 });137 prevMenuOpenIdRef.current = null;138 }, []);139 140 const handleMenuClose = React.useCallback(()=>{141 /* We have no way here to know if the menu was closed using menu button or not142 We will keep the last menu name ref for sometime so that the menu does not143 open again if menu button is clicked to close the menu */144 prevMenuOpenIdRef.current = openMenuName;145 setTimeout(()=>{146 prevMenuOpenIdRef.current = null;147 }, 300);148 setOpenMenuName(null);149 }, [openMenuName]);150 151 return {152 openMenuName: openMenuName,153 toggleMenu: toggleMenu,154 onMenuClose: handleMenuClose,155 };156}157 