1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import * as React from 'react';
    
  11. import * as ReactDOM from 'react-dom';
    
  12. 
    
  13. const {useLayoutEffect, useRef} = React;
    
  14. const {unstable_createEventHandle} = ReactDOM;
    
  15. 
    
  16. type UseEventHandle = {
    
  17.   setListener: (
    
  18.     target: EventTarget,
    
  19.     null | ((SyntheticEvent<EventTarget>) => void),
    
  20.   ) => void,
    
  21.   clear: () => void,
    
  22. };
    
  23. 
    
  24. export default function useEvent(
    
  25.   event: string,
    
  26.   options?: {
    
  27.     capture?: boolean,
    
  28.   },
    
  29. ): UseEventHandle {
    
  30.   const handleRef = useRef<UseEventHandle | null>(null);
    
  31.   let useEventHandle = handleRef.current;
    
  32. 
    
  33.   if (useEventHandle === null) {
    
  34.     const setEventHandle = unstable_createEventHandle(event, options);
    
  35.     const clears = new Map<EventTarget, () => void>();
    
  36.     useEventHandle = {
    
  37.       setListener(
    
  38.         target: EventTarget,
    
  39.         callback: null | ((SyntheticEvent<EventTarget>) => void),
    
  40.       ): void {
    
  41.         let clear = clears.get(target);
    
  42.         if (clear !== undefined) {
    
  43.           clear();
    
  44.         }
    
  45.         if (callback === null) {
    
  46.           clears.delete(target);
    
  47.           return;
    
  48.         }
    
  49.         clear = setEventHandle(target, callback);
    
  50.         clears.set(target, clear);
    
  51.       },
    
  52.       clear(): void {
    
  53.         clears.forEach(c => {
    
  54.           c();
    
  55.         });
    
  56.         clears.clear();
    
  57.       },
    
  58.     };
    
  59.     handleRef.current = useEventHandle;
    
  60.   }
    
  61. 
    
  62.   useLayoutEffect(() => {
    
  63.     return () => {
    
  64.       if (useEventHandle !== null) {
    
  65.         useEventHandle.clear();
    
  66.       }
    
  67.       handleRef.current = null;
    
  68.     };
    
  69.   }, [useEventHandle]);
    
  70. 
    
  71.   return useEventHandle;
    
  72. }