import React, {forwardRef, Fragment, ReactElement} from 'react'; import {NavLink} from 'react-router-dom'; import clsx from 'clsx'; import {MenuConfig, MenuItemConfig} from '../core/settings/settings'; import {createSvgIconFromTree} from '../icons/create-svg-icon'; import {Orientation} from '../ui/forms/orientation'; import {useCustomMenu} from './use-custom-menu'; import {Trans} from '../i18n/trans'; import {IconSize} from '@common/icons/svg-icon'; type MatchDescendants = undefined | boolean | ((to: string) => boolean); interface CustomMenuProps { className?: string; matchDescendants?: MatchDescendants; iconClassName?: string; iconSize?: IconSize; itemClassName?: | string | ((props: { isActive: boolean; item: MenuItemConfig; }) => string | undefined); gap?: string; menu?: string | MenuConfig; children?: (menuItem: MenuItemConfig) => ReactElement; orientation?: Orientation; onlyShowIcons?: boolean; unstyled?: boolean; } export function CustomMenu({ className, iconClassName, itemClassName, gap = 'gap-30', menu: menuOrPosition, orientation = 'horizontal', children, matchDescendants, onlyShowIcons, iconSize, unstyled = false, }: CustomMenuProps) { const menu = useCustomMenu(menuOrPosition); if (!menu) return null; return (
{menu.items.map(item => { if (children) { return children(item); } return ( { return typeof itemClassName === 'function' ? itemClassName({...props, item}) : itemClassName; }} key={item.id} item={item} /> ); })}
); } interface MenuItemProps extends React.RefAttributes { item: MenuItemConfig; iconClassName?: string; className?: (props: {isActive: boolean}) => string | undefined; matchDescendants?: MatchDescendants; onlyShowIcon?: boolean; iconSize?: IconSize; unstyled?: boolean; } export const CustomMenuItem = forwardRef( ( { item, className, matchDescendants, unstyled, onlyShowIcon, iconClassName, iconSize = 'sm', ...linkProps }, ref ) => { const label = ; const Icon = item.icon && createSvgIconFromTree(item.icon); const content = ( {Icon && } {(!Icon || !onlyShowIcon) && label} ); const baseClassName = !unstyled && 'block whitespace-nowrap flex items-center justify-start gap-10'; const focusClassNames = !unstyled && 'outline-none focus-visible:ring-2'; if (item.type === 'link') { return ( {content} ); } return ( clsx(baseClassName, className?.(props), focusClassNames) } to={item.action} target={item.target} data-menu-item-id={item.id} ref={ref} {...linkProps} > {content} ); } );