parent
d0f9ced223
commit
5b231fdb7e
3 changed files with 61 additions and 0 deletions
@ -0,0 +1,41 @@ |
||||
import { Menu as MuiMenu } from '@mui/material'; |
||||
import { FC, useMemo } from 'react'; |
||||
|
||||
import MenuItem from './MenuItem'; |
||||
|
||||
const Menu: FC<MenuProps> = (props) => { |
||||
const { |
||||
items = {}, |
||||
muiMenuProps: menuProps, |
||||
onItemClick, |
||||
open, |
||||
renderItem, |
||||
} = props; |
||||
|
||||
const pairs = useMemo(() => Object.entries(items), [items]); |
||||
|
||||
const itemElements = useMemo( |
||||
() => |
||||
pairs.map(([key, value]) => ( |
||||
<MenuItem |
||||
onClick={(...parent) => |
||||
onItemClick?.call(null, key, value, ...parent) |
||||
} |
||||
// The key is only relevant within the same branch; i.e., instance of
|
||||
// the same key under a different parent is OK.
|
||||
key={key} |
||||
> |
||||
{renderItem?.call(null, key, value)} |
||||
</MenuItem> |
||||
)), |
||||
[onItemClick, pairs, renderItem], |
||||
); |
||||
|
||||
return ( |
||||
<MuiMenu open={open} {...menuProps}> |
||||
{itemElements} |
||||
</MuiMenu> |
||||
); |
||||
}; |
||||
|
||||
export default Menu as <T>(props: MenuProps<T>) => ReturnType<FC<MenuProps<T>>>; |
@ -0,0 +1,14 @@ |
||||
type MuiMenuProps = import('@mui/material').MenuProps; |
||||
|
||||
type MenuOptionalProps<T = unknown> = Pick<MuiMenuProps, 'open'> & { |
||||
items?: Record<string, T>; |
||||
muiMenuProps?: Partial<MuiMenuProps>; |
||||
onItemClick?: ( |
||||
key: string, |
||||
value: T, |
||||
...parent: Parameters<MuiMenuItemClickEventHandler> |
||||
) => ReturnType<MuiMenuItemClickEventHandler>; |
||||
renderItem?: (key: string, value: T) => import('react').ReactNode; |
||||
}; |
||||
|
||||
type MenuProps<T = unknown> = MenuOptionalProps<T>; |
@ -0,0 +1,6 @@ |
||||
type MuiMenuItemProps = import('@mui/material').MenuItemProps; |
||||
|
||||
type MuiMenuItemClickEventHandler = Exclude< |
||||
MuiMenuItemProps['onClick'], |
||||
undefined |
||||
>; |
Loading…
Reference in new issue