import { useNavigate, type LinkOptions } from '@tanstack/react-router'; import clsx from 'clsx'; import React, { useEffect, useRef } from 'react'; import Counter from '@/components/ui/counter'; import Icon from '@/components/ui/icon'; import Toggle from '@/components/ui/toggle'; import { userTouching } from '@/is-mobile'; type Menu = Array; type MenuItem = { action?: React.EventHandler; active?: boolean; checked?: boolean; count?: number; destructive?: boolean; href?: string; icon?: string; meta?: string; middleClick?(event: React.MouseEvent): void; onChange?: (value: boolean) => void; target?: React.HTMLAttributeAnchorTarget; text: string; type?: 'toggle' | 'radio'; items?: Menu; onSelectFile?: (files: FileList) => void; accept?: string; } & (LinkOptions | { to?: undefined }); interface IDropdownMenuItem { index: number; item: MenuItem | null; onClick?(goBack?: boolean): void; autoFocus?: boolean; onSetTab: (tab?: number) => void; } const DropdownMenuItem = ({ index, item, onClick, autoFocus, onSetTab }: IDropdownMenuItem) => { const navigate = useNavigate(); const itemRef = useRef(null); const fileElement = useRef(null); const handleClick: React.EventHandler = (event) => { event.stopPropagation(); if (!item) return; if (item.items?.length) { event.preventDefault(); onSetTab(index); return; } if (item.onSelectFile) { fileElement.current?.click(); return; } if (onClick) onClick(!(item.to && userTouching.matches)); if (item.to) { event.preventDefault(); if (userTouching.matches) { navigate({ to: item.to, params: item.params, search: item.search, replace: true }); } else navigate({ to: item.to, params: item.params, search: item.search }); } else if (typeof item.action === 'function') { const action = item.action; event.preventDefault(); action(event); } }; const handleAuxClick: React.EventHandler = (event) => { if (!item) return; if (item.onSelectFile) fileElement.current?.click(); if (onClick) onClick(); if (event.button === 1 && item.middleClick) { item.middleClick(event); } }; const handleItemKeyPress: React.EventHandler = (event) => { if (event.key === 'Enter' || event.key === ' ') { handleClick(event); } }; const handleChange: React.ChangeEventHandler = (event) => { event.preventDefault(); event.stopPropagation(); if (!item) return; if (item.onChange) item.onChange(event.target.checked); }; const handleSelectFileChange: React.ChangeEventHandler = (e) => { if (e.target.files?.length && item?.onSelectFile) { item.onSelectFile(e.target.files); } }; useEffect(() => { const firstItem = index === 0; if (itemRef.current && (autoFocus ? firstItem : item?.active)) { itemRef.current.focus({ preventScroll: true }); } }, [itemRef.current, index]); if (item === null) { return
; } return (
  • {item.icon && }
    {item.meta ? ( <>
    {item.text}
    {item.meta}
    ) : item.text}
    {item.count ? ( ) : null} {(item.type === 'toggle' || item.type === 'radio') && (
    )} {!!item.items?.length && ( )}
    {item.onSelectFile && ( )}
  • ); }; export { type Menu, type MenuItem, DropdownMenuItem as default };