| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- import {
- Dropdown,
- DropdownMenu,
- DropdownToggle,
- } from '@/shared/components/dropdown/dropdown-menu'
- import { FC, forwardRef, useCallback } from 'react'
- import classNames from 'classnames'
- import { useNestableDropdown } from '@/shared/hooks/use-nestable-dropdown'
- import { NestableDropdownContextProvider } from '@/shared/context/nestable-dropdown-context'
- import { AnchorProps } from 'react-bootstrap'
- import MaterialIcon from '../material-icon'
- import { DropdownMenuProps } from '@/shared/components/types/dropdown-menu-props'
- type MenuBarDropdownProps = {
- title: string
- id: string
- className?: string
- align?: 'start' | 'end'
- }
- export const MenuBarDropdown: FC<
- React.PropsWithChildren<MenuBarDropdownProps>
- > = ({ title, children, id, className, align = 'start' }) => {
- const { menuId, selected, setSelected } = useNestableDropdown()
- const onToggle = useCallback(
- (show: boolean) => {
- setSelected(show ? id : null)
- },
- [id, setSelected]
- )
- const onHover = useCallback(() => {
- setSelected(prev => {
- if (prev === null) {
- return null
- }
- return id
- })
- }, [id, setSelected])
- const active = selected === id
- return (
- <Dropdown show={active} align={align} onToggle={onToggle} autoClose>
- <DropdownToggle
- id={`${menuId}-${id}`}
- variant="secondary"
- className={classNames(className, 'menu-bar-toggle')}
- onMouseEnter={onHover}
- >
- {title}
- </DropdownToggle>
- {active && (
- <NestableDropdownMenu renderOnMount id={`${menuId}-${id}`}>
- {children}
- </NestableDropdownMenu>
- )}
- </Dropdown>
- )
- }
- const NestableDropdownMenu: FC<
- React.PropsWithChildren<DropdownMenuProps & { id: string }>
- > = ({ children, id, ...props }) => {
- return (
- <DropdownMenu {...props}>
- <NestableDropdownContextProvider id={id}>
- {children}
- </NestableDropdownContextProvider>
- </DropdownMenu>
- )
- }
- const NestedDropdownToggle: FC<React.PropsWithChildren> = forwardRef<
- HTMLAnchorElement,
- AnchorProps
- >(function NestedDropdownToggle(
- { children, className, onMouseEnter, id },
- ref
- ) {
- return (
- // eslint-disable-next-line jsx-a11y/anchor-is-valid
- <a
- id={id}
- href="#"
- ref={ref}
- onMouseEnter={onMouseEnter}
- onClick={onMouseEnter}
- className={classNames(
- className,
- 'nested-dropdown-toggle',
- 'dropdown-item'
- )}
- role="menuitem"
- aria-haspopup
- >
- {children}
- <MaterialIcon type="chevron_right" />
- </a>
- )
- })
- export const NestedMenuBarDropdown: FC<
- React.PropsWithChildren<{ id: string; title: string }>
- > = ({ children, id, title }) => {
- const { menuId, selected, setSelected } = useNestableDropdown()
- const select = useCallback(() => {
- setSelected(id)
- }, [id, setSelected])
- const onToggle = useCallback(
- (show: boolean) => {
- // Only handle opening
- if (show) {
- setSelected(id)
- }
- },
- [setSelected, id]
- )
- const active = selected === id
- return (
- <Dropdown
- align="start"
- drop="end"
- show={active}
- autoClose
- onToggle={onToggle}
- as="li"
- role="none"
- >
- <DropdownToggle
- id={`${menuId}-${id}`}
- onMouseEnter={select}
- className={classNames({ 'nested-dropdown-toggle-shown': active })}
- as={NestedDropdownToggle}
- >
- {title}
- </DropdownToggle>
- {active && (
- <NestableDropdownMenu renderOnMount id={`${menuId}-${id}`}>
- {children}
- </NestableDropdownMenu>
- )}
- </Dropdown>
- )
- }
|