/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { unref, watch } from 'vue'; import { noop } from '../utils/noop'; import { tryOnScopeDispose } from '../utils/tryOnScopeDispose'; import { Fn, MaybeNullableRef } from '../typings/internal'; export interface InferEventTarget { addEventListener(event: Events, fn?: any, options?: any): any; removeEventListener(event: Events, fn?: any, options?: any): any; } export type GeneralEventListener = { (evt: E): void; }; export function useEventListener( target: Window, event: E, listener: (this: Window, ev: WindowEventMap[E]) => any, options?: boolean | AddEventListenerOptions ): Fn; export function useEventListener( target: Document, event: E, listener: (this: Document, ev: DocumentEventMap[E]) => any, options?: boolean | AddEventListenerOptions ): Fn; export function useEventListener( target: MaybeNullableRef, event: E, listener: (this: Window, ev: HTMLElementEventMap[E]) => any, options?: boolean | AddEventListenerOptions ): Fn; export function useEventListener( target: MaybeNullableRef, event: E, listener: (this: Window, ev: SVGElementEventMap[E]) => any, options?: boolean | AddEventListenerOptions ): Fn; export function useEventListener( target: MaybeNullableRef, event: string, listener: GeneralEventListener, options?: boolean | AddEventListenerOptions ): Fn; export function useEventListener( target: MaybeNullableRef | MaybeNullableRef, event: string, listener: any, options?: boolean | AddEventListenerOptions ): Fn { let cleanup = noop; const stopWatch = watch( () => unref(target), (el) => { cleanup(); if (!el) return; el.addEventListener(event, listener, options); cleanup = () => { el.removeEventListener(event, listener, options); }; }, { immediate: true, flush: 'sync' } ); let stopImpl = () => { stopWatch(); cleanup(); stopImpl = noop; }; const stop = () => { stopImpl(); }; tryOnScopeDispose(stop); return stop; }