Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tom Moor <tom.moor@gmail.com>
71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
import * as React from "react";
|
|
import { useMousePosition } from "~/hooks/useMousePosition";
|
|
|
|
type Positions = {
|
|
/* Sub-menu x */
|
|
x: number;
|
|
/* Sub-menu y */
|
|
y: number;
|
|
/* Sub-menu height */
|
|
h: number;
|
|
/* Sub-menu width */
|
|
w: number;
|
|
/* Mouse x */
|
|
mouseX: number;
|
|
/* Mouse y */
|
|
mouseY: number;
|
|
};
|
|
|
|
/**
|
|
* Component to cover the area between the mouse cursor and the sub-menu, to
|
|
* allow moving cursor to lower parts of sub-menu without the sub-menu
|
|
* disappearing.
|
|
*/
|
|
export default function MouseSafeArea(props: {
|
|
parentRef: React.RefObject<HTMLElement | null>;
|
|
}) {
|
|
const {
|
|
x = 0,
|
|
y = 0,
|
|
height: h = 0,
|
|
width: w = 0,
|
|
} = props.parentRef.current?.getBoundingClientRect() || {};
|
|
const [mouseX, mouseY] = useMousePosition();
|
|
const positions = { x, y, h, w, mouseX, mouseY };
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
// backgroundColor: "rgba(255,0,0,0.1)", // Uncomment to debug
|
|
right: getRight(positions),
|
|
left: getLeft(positions),
|
|
height: h,
|
|
width: getWidth(positions),
|
|
clipPath: getClipPath(positions),
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const getLeft = ({ x, mouseX }: Positions) =>
|
|
mouseX > x ? undefined : -Math.max(x - mouseX, 10) + "px";
|
|
|
|
const getRight = ({ x, w, mouseX }: Positions) =>
|
|
mouseX > x ? -Math.max(mouseX - (x + w), 10) + "px" : undefined;
|
|
|
|
const getWidth = ({ x, w, mouseX }: Positions) =>
|
|
mouseX > x
|
|
? Math.max(mouseX - (x + w), 10) + "px"
|
|
: Math.max(x - mouseX, 10) + "px";
|
|
|
|
const getClipPath = ({ x, y, h, mouseX, mouseY }: Positions) =>
|
|
mouseX > x
|
|
? `polygon(0% 0%, 0% 100%, 100% ${(100 * (mouseY - y)) / h - 10}%, 100% ${
|
|
(100 * (mouseY - y)) / h + 5
|
|
}%)`
|
|
: `polygon(100% 0%, 0% ${(100 * (mouseY - y)) / h - 10}%, 0% ${
|
|
(100 * (mouseY - y)) / h + 5
|
|
}%, 100% 100%)`;
|