80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
import { useEffect, useRef, RefObject, useLayoutEffect } from "react";
|
|
|
|
// https://usehooks-ts.com/react-hook/use-event-listener
|
|
|
|
// MediaQueryList Event based useEventListener interface
|
|
export function useEventListener<K extends keyof MediaQueryListEventMap>(
|
|
eventName: K,
|
|
handler: (event: MediaQueryListEventMap[K]) => void,
|
|
element: RefObject<MediaQueryList>,
|
|
options?: boolean | AddEventListenerOptions,
|
|
): void;
|
|
|
|
// Window Event based useEventListener interface
|
|
export function useEventListener<K extends keyof WindowEventMap>(
|
|
eventName: K,
|
|
handler: (event: WindowEventMap[K]) => void,
|
|
element?: undefined,
|
|
options?: boolean | AddEventListenerOptions,
|
|
): void;
|
|
|
|
// Element Event based useEventListener interface
|
|
export function useEventListener<
|
|
K extends keyof HTMLElementEventMap,
|
|
T extends HTMLElement = HTMLDivElement,
|
|
>(
|
|
eventName: K,
|
|
handler: (event: HTMLElementEventMap[K]) => void,
|
|
element: RefObject<T>,
|
|
options?: boolean | AddEventListenerOptions,
|
|
): void;
|
|
|
|
// Document Event based useEventListener interface
|
|
export function useEventListener<K extends keyof DocumentEventMap>(
|
|
eventName: K,
|
|
handler: (event: DocumentEventMap[K]) => void,
|
|
element: RefObject<Document>,
|
|
options?: boolean | AddEventListenerOptions,
|
|
): void;
|
|
|
|
export function useEventListener<
|
|
KW extends keyof WindowEventMap,
|
|
KH extends keyof HTMLElementEventMap,
|
|
KM extends keyof MediaQueryListEventMap,
|
|
T extends HTMLElement | MediaQueryList | void = void,
|
|
>(
|
|
eventName: KW | KH | KM,
|
|
handler: (
|
|
event:
|
|
| WindowEventMap[KW]
|
|
| HTMLElementEventMap[KH]
|
|
| MediaQueryListEventMap[KM]
|
|
| Event,
|
|
) => void,
|
|
element?: RefObject<T>,
|
|
options?: boolean | AddEventListenerOptions,
|
|
) {
|
|
// Create a ref that stores handler
|
|
const savedHandler = useRef(handler);
|
|
|
|
useLayoutEffect(() => {
|
|
savedHandler.current = handler;
|
|
}, [handler]);
|
|
|
|
useEffect(() => {
|
|
// Define the listening target
|
|
const targetElement: T | Window = element?.current ?? window;
|
|
|
|
if (!(targetElement && targetElement.addEventListener)) return;
|
|
|
|
// Create event listener that calls handler export function stored in ref
|
|
const listener: typeof handler = event => savedHandler.current(event);
|
|
|
|
targetElement.addEventListener(eventName, listener, options);
|
|
|
|
// Remove event listener on cleanup
|
|
return () => {
|
|
targetElement.removeEventListener(eventName, listener, options);
|
|
};
|
|
}, [eventName, element, options]);
|
|
} |