{"version":3,"sources":["../../src/use-event-listener/index.ts"],"sourcesContent":["import { useRef } from 'react'\nimport { useDeepCompareEffect } from '../use-deep-compare-effect'\nimport { useLatest } from '../use-latest'\nimport { useStableFn } from '../use-stable-fn'\nimport { isString } from '../utils/basic'\nimport { unwrapArrayable, unwrapGettable, unwrapReffable } from '../utils/unwrap'\n\nimport type { Arrayable, Gettable, GettableOrReffable, Noop } from '../utils/basic'\n\nexport interface InferEventTarget<Events> {\n  addEventListener: (event: Events, fn?: any, options?: any) => any\n  removeEventListener: (event: Events, fn?: any, options?: any) => any\n}\n\nexport type GeneralEventListener<E = Event> = (evt: E) => void\n\n/**\n * A React Hook that use `EventListener` with ease.\n *\n * Register using `addEventListener` on mounted, and `removeEventListener` automatically on unmounted.\n */\n// default window\nexport function useEventListener<E extends keyof WindowEventMap>(\n  event: Arrayable<E>,\n  listener: (this: Window, ev: WindowEventMap[E]) => unknown,\n  options?: boolean | AddEventListenerOptions,\n): Noop\n// explicit window\nexport function useEventListener<E extends keyof WindowEventMap>(\n  target: Gettable<Window>,\n  event: Arrayable<E>,\n  listener: (this: Document, ev: WindowEventMap[E]) => unknown,\n  options?: boolean | AddEventListenerOptions,\n): Noop\n// explicit document\nexport function useEventListener<E extends keyof DocumentEventMap>(\n  target: Gettable<DocumentOrShadowRoot>,\n  event: Arrayable<E>,\n  listener: (this: Document, ev: DocumentEventMap[E]) => unknown,\n  options?: boolean | AddEventListenerOptions,\n): Noop\n// explicit HTML element\nexport function useEventListener<E extends keyof HTMLElementEventMap>(\n  target: GettableOrReffable<HTMLElement | null | undefined>,\n  event: Arrayable<E>,\n  listener: (this: HTMLElement, ev: HTMLElementEventMap[E]) => unknown,\n  options?: boolean | AddEventListenerOptions,\n): Noop\n// custom target with event types inferred\nexport function useEventListener<E extends string, EventType = Event>(\n  target: GettableOrReffable<InferEventTarget<E> | null | undefined>,\n  event: Arrayable<E>,\n  listener: GeneralEventListener<EventType>,\n  options?: boolean | AddEventListenerOptions,\n): Noop\n// custom target and event fallback\nexport function useEventListener<EventType = Event>(\n  target: GettableOrReffable<EventTarget | null | undefined>,\n  event: Arrayable<string>,\n  listener: GeneralEventListener<EventType>,\n  options?: boolean | AddEventListenerOptions,\n): Noop\nexport function useEventListener(...args: any[]) {\n  let target: GettableOrReffable<EventTarget | null | undefined>\n  let events: Arrayable<string>\n  let listener: Noop\n  let options: boolean | AddEventListenerOptions\n\n  if (isString(args[0]) || Array.isArray(args[0])) {\n    ;[events, listener, options] = args\n    target = () => window\n  } else {\n    ;[target, events, listener, options] = args\n  }\n\n  const refTarget = unwrapReffable(target)\n  const actualEvents = unwrapArrayable(events)\n\n  const cleanups = useRef<Noop[]>([])\n  const latest = useLatest({ listener })\n\n  const cleanup = useStableFn(() => {\n    for (const cleanup of cleanups.current) cleanup()\n    cleanups.current.length = 0\n  })\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: need to detect ref.current change\n  useDeepCompareEffect(() => {\n    const actualTarget = unwrapReffable(unwrapGettable(target))\n\n    if (!actualTarget || !actualEvents.length) return\n\n    cleanups.current.push(\n      ...actualEvents.flatMap((e) => {\n        return addListener(actualTarget, e, (...args) => latest.current.listener(...args), options)\n      }),\n    )\n\n    return cleanup\n  }, [target, refTarget, actualEvents, options])\n\n  return cleanup\n}\n\nfunction addListener(\n  target: EventTarget,\n  event: string,\n  listener: Noop,\n  options: boolean | AddEventListenerOptions | undefined,\n): Noop {\n  target.addEventListener(event, listener, options)\n\n  return () => {\n    target.removeEventListener(event, listener, options)\n  }\n}\n"],"names":["useEventListener","args","target","events","listener","options","isString","Array","isArray","window","refTarget","unwrapReffable","actualEvents","unwrapArrayable","cleanups","useRef","latest","useLatest","cleanup","useStableFn","current","length","useDeepCompareEffect","actualTarget","unwrapGettable","push","flatMap","e","addListener","event","addEventListener","removeEventListener"],"mappings":";;;;+BA8DgBA;;;eAAAA;;;qBA9DO;oCACc;yBACX;2BACE;qBACH;sBACuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDzD,SAASA;IAAiB,IAAA,IAAA,OAAA,UAAA,QAAA,AAAGC,OAAH,UAAA,OAAA,OAAA,GAAA,OAAA,MAAA;QAAGA,KAAH,QAAA,SAAA,CAAA,KAAc;;IAC7C,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IAEJ,IAAIC,IAAAA,eAAQ,EAACL,IAAI,CAAC,EAAE,KAAKM,MAAMC,OAAO,CAACP,IAAI,CAAC,EAAE,GAAG;;+BAChBA,UAA7BE,iBAAQC,mBAAUC;QACpBH,SAAS;mBAAMO;;IACjB,OAAO;;gCACkCR,UAArCC,kBAAQC,kBAAQC,oBAAUC;IAC9B;IAEA,IAAMK,YAAYC,IAAAA,sBAAc,EAACT;IACjC,IAAMU,eAAeC,IAAAA,uBAAe,EAACV;IAErC,IAAMW,WAAWC,IAAAA,aAAM,EAAS,EAAE;IAClC,IAAMC,SAASC,IAAAA,oBAAS,EAAC;QAAEb,UAAAA;IAAS;IAEpC,IAAMc,UAAUC,IAAAA,wBAAW,EAAC;YACrB,kCAAA,2BAAA;;YAAL,QAAK,YAAiBL,SAASM,OAAO,qBAAjC,SAAA,6BAAA,QAAA,yBAAA;gBAAA,IAAMF,UAAN;gBAAmCA;;;YAAnC;YAAA;;;qBAAA,6BAAA;oBAAA;;;oBAAA;0BAAA;;;;QACLJ,SAASM,OAAO,CAACC,MAAM,GAAG;IAC5B;IAEA,6FAA6F;IAC7FC,IAAAA,0CAAoB,EAAC;YAKnBR;QAJA,IAAMS,eAAeZ,IAAAA,sBAAc,EAACa,IAAAA,sBAAc,EAACtB;QAEnD,IAAI,CAACqB,gBAAgB,CAACX,aAAaS,MAAM,EAAE;QAE3CP,CAAAA,oBAAAA,SAASM,OAAO,EAACK,IAAI,OAArBX,mBACE,qBAAGF,aAAac,OAAO,CAAC,SAACC;gBAC0BX;YAAjD,OAAOY,YAAYL,cAAcI,GAAG;iDAAI1B;oBAAAA;;uBAASe,CAAAA,kBAAAA,OAAOI,OAAO,EAAChB,QAAQ,OAAvBY,iBAAwB,qBAAGf;eAAOI;QACrF;QAGF,OAAOa;IACT,GAAG;QAAChB;QAAQQ;QAAWE;QAAcP;KAAQ;IAE7C,OAAOa;AACT;AAEA,SAASU,YACP1B,MAAmB,EACnB2B,KAAa,EACbzB,QAAc,EACdC,OAAsD;IAEtDH,OAAO4B,gBAAgB,CAACD,OAAOzB,UAAUC;IAEzC,OAAO;QACLH,OAAO6B,mBAAmB,CAACF,OAAOzB,UAAUC;IAC9C;AACF"}