102 lines
2.0 KiB
TypeScript
102 lines
2.0 KiB
TypeScript
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 (
|
|
<Container style={position} className="item-field-context-menu">
|
|
{children}
|
|
</Container>
|
|
)
|
|
},
|
|
[show, position]
|
|
)
|
|
|
|
return {
|
|
onRightClick,
|
|
Item,
|
|
ContextMenuContainer,
|
|
}
|
|
}
|