Files
stash/ui/v2.5/src/components/Shared/HoverPopover.tsx
WithoutPants 9b7e20351a Plugin api improvements (#5703)
* Add ReactSelect to PluginApi.libraries
* Make Performer tabs patchable
* Make PerformerCard patchable
* Use registration pattern for HoverPopover, TagLink and LoadingIndicator

Initialising the components map to include these was causing an initialisation error.

* Add showZero property to PopoverCountButton
* Make TagCard patchable
* Make ScenePage and ScenePlayer patchable
* Pass properties to container components
* Add example for scene tabs
* Make FrontPage patchable
* Add FrontPage example
2025-03-05 14:04:12 +11:00

88 lines
2.2 KiB
TypeScript

import React, { useState, useCallback, useEffect, useRef } from "react";
import { Overlay, Popover, OverlayProps } from "react-bootstrap";
import { PatchComponent } from "src/patch";
interface IHoverPopover {
enterDelay?: number;
leaveDelay?: number;
content: JSX.Element[] | JSX.Element | string;
className?: string;
placement?: OverlayProps["placement"];
onOpen?: () => void;
onClose?: () => void;
target?: React.RefObject<HTMLElement>;
}
export const HoverPopover: React.FC<IHoverPopover> = PatchComponent(
"HoverPopover",
({
enterDelay = 200,
leaveDelay = 200,
content,
children,
className,
placement = "top",
onOpen,
onClose,
target,
}) => {
const [show, setShow] = useState(false);
const triggerRef = useRef<HTMLDivElement>(null);
const enterTimer = useRef<number>();
const leaveTimer = useRef<number>();
const handleMouseEnter = useCallback(() => {
window.clearTimeout(leaveTimer.current);
enterTimer.current = window.setTimeout(() => {
setShow(true);
onOpen?.();
}, enterDelay);
}, [enterDelay, onOpen]);
const handleMouseLeave = useCallback(() => {
window.clearTimeout(enterTimer.current);
leaveTimer.current = window.setTimeout(() => {
setShow(false);
onClose?.();
}, leaveDelay);
}, [leaveDelay, onClose]);
useEffect(
() => () => {
window.clearTimeout(enterTimer.current);
window.clearTimeout(leaveTimer.current);
},
[]
);
return (
<>
<div
className={className}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
ref={triggerRef}
>
{children}
</div>
{triggerRef.current && (
<Overlay
show={show}
placement={placement}
target={target?.current ?? triggerRef.current}
>
<Popover
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
id="popover"
className="hover-popover-content"
>
{content}
</Popover>
</Overlay>
)}
</>
);
}
);