import { useLayoutEffect, useRef, useState } from 'react' import { useClickAway } from 'react-use' import useLockMainScroll from '@/web/hooks/useLockMainScroll' import useMeasure from 'react-use-measure' import { ContextMenuItem } from './MenuItem' import MenuPanel from './MenuPanel' const BasicContextMenu = ({ onClose, items, target, cursorPosition, options, classNames, }: { onClose: (e: MouseEvent) => void items: ContextMenuItem[] target: HTMLElement cursorPosition: { x: number; y: number } options?: { useCursorPosition?: boolean } | null classNames?: string }) => { const menuRef = useRef(null) const [measureRef, menu] = useMeasure() const [position, setPosition] = useState<{ x: number; y: number } | null>( null ) useClickAway(menuRef, onClose) useLockMainScroll(!!position) useLayoutEffect(() => { if (options?.useCursorPosition) { const leftX = cursorPosition.x const rightX = cursorPosition.x - menu.width const bottomY = cursorPosition.y const topY = cursorPosition.y - menu.height const position = { x: leftX + menu.width < window.innerWidth ? leftX : rightX, y: bottomY + menu.height < window.innerHeight ? bottomY : topY, } setPosition(position) } else { const button = target.getBoundingClientRect() const leftX = button.x const rightX = button.x - menu.width + button.width const bottomY = button.y + button.height + 8 const topY = button.y - menu.height - 8 const position = { x: leftX + menu.width < window.innerWidth ? leftX : rightX, y: bottomY + menu.height < window.innerHeight ? bottomY : topY, } setPosition(position) } }, [target, menu, options?.useCursorPosition, cursorPosition]) return ( <> { // }} forMeasure={true} classNames={classNames} /> {position && ( )} ) } export default BasicContextMenu