-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhooks.ts
50 lines (38 loc) · 1.6 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
"use client";
/* eslint-disable react-hooks/exhaustive-deps */
import { useCallback, useEffect, useMemo, useState, type DependencyList } from "react";
export function useScroll(container: React.RefObject<HTMLElement> | HTMLElement | null) {
const element = useMemo(() => container && "current" in container ? container.current : container, [ container ]);
const [ scrollX, setScrollX ] = useState(0);
const [ scrollY, setScrollY ] = useState(0);
const handle = useCallback(function({ target }: Event) {
if (!(target instanceof HTMLElement)) return;
setScrollX(target.scrollLeft);
setScrollY(target.scrollTop);
}, [ container ]);
useEffect(function() {
if (!element) return;
element.addEventListener("scroll", handle);
return () => element.removeEventListener("scroll", handle);
}, [ element, handle ]);
return { scrollX, scrollY };
}
export function useEvent<K extends keyof WindowEventMap>(event: K, handler: (this: Window, ev: WindowEventMap[K]) => (void | unknown)) {
useEffect(function() {
window.addEventListener(event, handler);
return () => window.removeEventListener(event, handler);
}, [ event, handler ]);
}
export function useResize(handler: () => (void | unknown), additionalDeps?: DependencyList) {
useEffect(function() {
handler();
window.addEventListener("resize", handler);
return () => window.removeEventListener("resize", handler);
}, [ handler, ...additionalDeps ?? [] ]);
}
export function useInterval(cb: () => void, delay: number) {
useEffect(function() {
const interval = setInterval(cb, delay);
return () => clearInterval(interval);
}, [ cb, delay ]);
}