Files
frontend/src/h

94 lines
2.1 KiB
Plaintext
Raw Normal View History

/**
* useHover Hook
* 用于检测鼠标悬停状态,仅在桌面端(Web)生效
* 在移动端返回默认值 false
*/
import { useState, useCallback, useRef, useEffect } from 'react';
import { Platform } from 'react-native';
interface UseHoverOptions {
enterDelay?: number;
leaveDelay?: number;
}
interface UseHoverReturn {
isHovered: boolean;
hoverProps: {
onMouseEnter: () => void;
onMouseLeave: () => void;
};
}
/**
* 检测当前是否在 Web 平台
*/
const isWeb = Platform.OS === 'web';
/**
* useHover Hook
* @param options 配置选项
* @returns 悬停状态和事件处理器
*/
export function useHover(options: UseHoverOptions = {}): UseHoverReturn {
const { enterDelay = 0, leaveDelay = 0 } = options;
const [isHovered, setIsHovered] = useState(false);
const enterTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const leaveTimeoutRef = useRef<NodeJS.Timeout | null>(null);
// 清理定时器
useEffect(() => {
return () => {
if (enterTimeoutRef.current) {
clearTimeout(enterTimeoutRef.current);
}
if (leaveTimeoutRef.current) {
clearTimeout(leaveTimeoutRef.current);
}
};
}, []);
const handleMouseEnter = useCallback(() => {
if (!isWeb) return;
if (leaveTimeoutRef.current) {
clearTimeout(leaveTimeoutRef.current);
leaveTimeoutRef.current = null;
}
if (enterDelay > 0) {
enterTimeoutRef.current = setTimeout(() => {
setIsHovered(true);
}, enterDelay);
} else {
setIsHovered(true);
}
}, [enterDelay]);
const handleMouseLeave = useCallback(() => {
if (!isWeb) return;
if (enterTimeoutRef.current) {
clearTimeout(enterTimeoutRef.current);
enterTimeoutRef.current = null;
}
if (leaveDelay > 0) {
leaveTimeoutRef.current = setTimeout(() => {
setIsHovered(false);
}, leaveDelay);
} else {
setIsHovered(false);
}
}, [leaveDelay]);
return {
isHovered,
hoverProps: {
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
},
};
}
export default useHover;