Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 19x 19x 19x 19x 88x 50x 50x 50x 50x 50x 50x 45x 50x 42x 8x 8x 12x | import { ReactElement, useEffect, useState } from "react";
import {
CardContentContextMenu,
CardTrackContextMenu,
PortalTarget,
} from "components";
import type { ICardContentContextMenu } from "components/CardContentContextMenu";
import { useContextMenu, useEventListener } from "hooks";
import type { ITrack } from "types/spotify";
import {
calculateContextMenuPosition,
CONTEXT_MENU_SIDE_OFFSET,
positionContextMenu,
} from "utils";
export default function ContextMenu({
document = window.document,
}: {
document?: Document;
}): ReactElement | null {
const { contextMenuData, removeContextMenu } = useContextMenu();
const [contextMenuPos, setContextMenuPos] = useState({
x: (contextMenuData?.position.x ?? 0) - 30,
y: (contextMenuData?.position.y ?? 0) - 40,
});
const [isContextMenuOffscreen, setIsContextMenuOffscreen] = useState({
x: false,
y: false,
});
const [element, setElement] = useState<HTMLElement | null>(null);
useEventListener({
target: document.querySelector("#__next"),
type: "click",
listener: removeContextMenu,
options: { once: true },
ignore: !contextMenuData?.data,
});
useEffect(() => {
positionContextMenu({
currentPosition: contextMenuData?.position,
element: element,
setPosition: setContextMenuPos,
setIsOffScreen: setIsContextMenuOffscreen,
offsets: { x: 30, y: 10 },
});
}, [contextMenuData?.position, element]);
if (!contextMenuData) {
return null;
}
const top = calculateContextMenuPosition(
isContextMenuOffscreen.y,
contextMenuPos.y,
contextMenuData.position.y,
CONTEXT_MENU_SIDE_OFFSET
);
const left = calculateContextMenuPosition(
isContextMenuOffscreen.x,
contextMenuPos.x,
contextMenuData.position.x,
CONTEXT_MENU_SIDE_OFFSET
);
return (
<PortalTarget
targetId={
document.querySelector<HTMLElement>("#contextMenu") ?? undefined
}
>
<section
role="menu"
data-type={contextMenuData.data?.type}
ref={(element) => setElement(element)}
style={{ top, left }}
>
{contextMenuData.data?.type === "track" ||
contextMenuData.data?.type === "episode" ? (
<CardTrackContextMenu track={contextMenuData.data as ITrack} />
) : (
<CardContentContextMenu
data={contextMenuData.data as ICardContentContextMenu["data"]}
/>
)}
<style jsx>{`
section {
max-width: 400px;
width: fit-content;
position: absolute;
margin: 0 auto;
border-radius: 5px;
background-color: #282828;
box-shadow: 0px 2px 9px 0px rgb(0 0 0 / 5%);
padding: 3px;
max-height: 95vh;
z-index: 999999999999;
}
`}</style>
</section>
</PortalTarget>
);
}
|