34 lines
969 B
TypeScript
34 lines
969 B
TypeScript
"use client";
|
|||
|
|
|
||
|
|
import { useEffect, useRef, useState } from "react";
|
||
|
|
|
||
|
|
/** True once no pointer/keyboard activity has been seen for `timeoutMs`. */
|
||
|
|
export function useIdleTimer(timeoutMs = 3000): boolean {
|
||
|
|
const [isIdle, setIsIdle] = useState(false);
|
||
|
|
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const reset = () => {
|
||
|
|
setIsIdle(false);
|
||
|
|
if (timerRef.current) clearTimeout(timerRef.current);
|
||
|
|
timerRef.current = setTimeout(() => setIsIdle(true), timeoutMs);
|
||
|
|
};
|
||
|
|
|
||
|
|
reset();
|
||
|
|
const events: Array<keyof WindowEventMap> = [
|
||
|
|
"mousemove",
|
||
|
|
"pointerdown",
|
||
|
|
"touchstart",
|
||
|
|
"keydown",
|
||
|
|
];
|
||
|
|
events.forEach((event) => window.addEventListener(event, reset, { passive: true }));
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
if (timerRef.current) clearTimeout(timerRef.current);
|
||
|
|
events.forEach((event) => window.removeEventListener(event, reset));
|
||
|
|
};
|
||
|
|
}, [timeoutMs]);
|
||
|
|
|
||
|
|
return isIdle;
|
||
|
|
}
|