55 lines
1.4 KiB
TypeScript

"use client";
import { FC, PropsWithChildren, ReactNode, useCallback, useState } from "react";
import { PoppableContent } from "./poppable-content";
import { useDebounce } from "../../../hooks/useDebounce";
interface IProps {
content: ReactNode;
className?: string;
preferredEdge: "top" | "bottom" | "left" | "right";
preferredAlign: "centered" | "top" | "bottom" | "left" | "right";
spacing?: number;
}
export const Poppable: FC<PropsWithChildren<IProps>> = (
{ className, content, children, preferredEdge, preferredAlign, spacing },
) => {
const [isHovered, setIsHovered] = useState(false);
const closing = useDebounce(!isHovered, 1000);
const closed = useDebounce(closing, 300);
const [ref, setRef] = useState<HTMLElement>();
const updateRef = useCallback((node: HTMLElement) => {
if (!node) return;
setRef(node);
}, []);
return (
<>
<span
ref={updateRef}
className={className}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{children}
</span>
{!!ref && (
<PoppableContent
preferredAlign={preferredAlign}
preferredEdge={preferredEdge}
spacing={spacing}
isClosing={closing}
isClosed={closed}
relativeElement={ref}
setHover={setIsHovered}
>
{content}
</PoppableContent>
)}
</>
);
};