import { useCallback, useEffect, useState } from "react" import styled from "@emotion/styled" const Container = styled.menu` background-color: #fff; border-radius: 3px; box-shadow: #0004 0px 1px 4px; left: 99%; margin-block-start: 0; min-width: 180px; padding-inline-start: 0; position: absolute; top: 0; user-select: none; z-index: 2; @media (prefers-color-scheme: dark) { background-color: #3c3c3c; box-shadow: rgb(0 0 0) 0px 2px 4px; color: #f0f0f0; } & & { display: none; } ` const Separator = styled.div` border-bottom: 1px solid #777; margin-top: 0.4em; margin-bottom: 0.4em; margin-left: 0.6em; margin-right: 0.6em; ` const Item = styled.div` cursor: default; font-size: 13px; flex: 1 1 auto; display: flex; height: 2.5em; align-items: center; padding-left: 1em; padding-right: 5px; position: relative; &:hover { background-color: #ddd; border-radius: 3px; .item-field-context-menu { display: block; } @media (prefers-color-scheme: dark) { background-color: #094771; } } ` function useContextMenu() { const [show, setShow] = useState(false) const [pos, setPos] = useState({ x: 0, y: 0 }) const onRightClick = useCallback((e: React.MouseEvent) => { setShow(true) e.preventDefault() setPos({ x: e.pageX, y: e.pageY }) }, []) useEffect(() => { const fn = () => setShow(false) document.addEventListener("click", fn) return () => document.removeEventListener("click", fn) }, []) return { show, position: { top: pos.y, left: pos.x, }, onRightClick, } } export function useItemFieldContextMenu() { const { onRightClick, position, show } = useContextMenu() const ContextMenuContainer: React.FC = useCallback( ({ children }) => { if (!show) return null return ( {children} ) }, [show, position] ) return { onRightClick, Item, ContextMenuContainer, } }