import { useEffect , useState , useCallback , useRef } from 'react' ; const defaultOptions = { cancelOnUnmount : true , } ; /**
 * An async-utility hook that accepts a callback function and a delay time (in milliseconds), then delays the
 * execution of the given function by the defined time.
 */ export const useTimeout = ( fn ? , milliseconds ? , options ? ) : [ boolean , ( ) => void ] => { const opts = { ... defaultOptions , ... ( options || defaultOptions ) } ; const timeout = useRef < NodeJS . Timeout > ( ) ; const callbackRef = useRef ( fn ) ; const [ isCleared , setIsCleared ] = useState ( false ) ; const isComplete = useRef ( false ) ; const clear = useCallback ( ( ) => { if ( timeout . current ) { clearTimeout ( timeout . current ) ; setIsCleared ( true ) ; } } , [ ] ) ; const swapTimeout = useCallback ( ( ms ) => { isComplete . current = false ; timeout . current = setTimeout ( ( ) => { isComplete . current = true ; callbackRef . current ?. ( ) ; } , ms ) as any ; } , [ ] ) ; useEffect ( ( ) => { if ( typeof fn === 'function' ) { callbackRef . current = fn ; if ( isComplete . current ) { swapTimeout ( milliseconds ) ; } } } , [ fn ] ) ; useEffect ( ( ) => { if ( typeof milliseconds === 'number' && callbackRef . current ) { swapTimeout ( milliseconds ) ; } return clear ; } , [ milliseconds ] ) ; useEffect ( ( ) => ( ) => { if ( opts . cancelOnUnmount ) { clear ( ) ; } } , [ ] ) ; return [ isCleared , clear ] ; } ; param fn param milliseconds param options export const useSwappableTimeout = ( fn ? , milliseconds ? , options ? ) => { const [ args , setArgs ] = useState < [ React . EffectCallback | undefined , number | undefined , typeof defaultOptions | undefined ] > ( [ fn , milliseconds , options ] ) ; const [ fnArg , msArg , optionsArg ] = args ; const [ isCleared , clearTimeoutRef ] = useTimeout ( fnArg ?? fn , msArg ?? milliseconds , optionsArg ?? options ) ; const swapTimeout = ( ... args ) => { setArgs ( args as any ) ; } ; return { clearTimeoutRef , isCleared , swapTimeout , } ; } ;