52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
import { useEffect } from "react"
|
|
|
|
type UseEventListenerOptions = boolean | AddEventListenerOptions
|
|
|
|
export { useEventListener }
|
|
|
|
type On<This, Ev> = {
|
|
on(listener: (this: This, ev: Ev) => void, deps?: any[]): void
|
|
}
|
|
|
|
interface UseEventListener {
|
|
<K extends keyof MediaQueryListEventMap>(
|
|
mediaQueryList: MediaQueryList,
|
|
type: K,
|
|
options?: UseEventListenerOptions
|
|
): On<MediaQueryList, MediaQueryListEventMap[K]>
|
|
<K extends keyof WindowEventMap>(
|
|
window: Window,
|
|
type: K,
|
|
options?: UseEventListenerOptions
|
|
): On<Window, WindowEventMap[K]>
|
|
<K extends keyof DocumentEventMap>(
|
|
document: Document,
|
|
type: K,
|
|
options?: UseEventListenerOptions
|
|
): On<Document, DocumentEventMap[K]>
|
|
<K extends keyof HTMLElementEventMap>(
|
|
element: HTMLElement,
|
|
type: K,
|
|
options?: UseEventListenerOptions
|
|
): On<HTMLElement, HTMLElementEventMap[K]>
|
|
}
|
|
|
|
const useEventListener: UseEventListener = function useEventListener(
|
|
element: EventTarget,
|
|
type: string,
|
|
options?: UseEventListenerOptions
|
|
) {
|
|
return {
|
|
on(listener: (ev: any) => any, deps?: any[]) {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
useEffect(
|
|
() => {
|
|
element.addEventListener(type, listener, options)
|
|
return () => element.removeEventListener(type, listener, options)
|
|
},
|
|
deps ? [element, type, ...deps] : undefined
|
|
)
|
|
},
|
|
}
|
|
}
|