import { useEffect, useRef, useState } from 'react';
interface HoverOption {
onEnter?: () => void;
onLeave?: () => void;
entryDelay?: number;
leaveDelay?: number;
}
const DEFAULT_DELAY: HoverOption = {
entryDelay: 100,
leaveDelay: 500,
};
const useHover = <T extends HTMLElement>(options?: HoverOption) => {
const { onEnter, onLeave, entryDelay, leaveDelay } = options || DEFAULT_DELAY;
const domRef = useRef<T | null>(null);
const [visible, setVisible] = useState(false);
const timeRef = useRef<any>();
const onMouseEnter = () => {
clearTimeout(timeRef.current);
timeRef.current = setTimeout(() => {
setVisible(true);
onEnter?.();
}, entryDelay);
};
const onMouseLeave = () => {
clearTimeout(timeRef.current);
timeRef.current = setTimeout(() => {
setVisible(false);
onLeave?.();
}, leaveDelay);
};
useEffect(() => {
if (domRef.current) {
domRef.current.addEventListener('mouseenter', onMouseEnter);
domRef.current.addEventListener('mouseleave', onMouseLeave);
}
return () => {
domRef.current?.removeEventListener('mouseenter', onMouseEnter);
domRef.current?.removeEventListener('mouseleave', onMouseLeave);
clearTimeout(timeRef.current);
};
}, []);
return [visible, domRef, { setVisible }] as const;
};
export default useHover;