import type { IDerivation } from '@theatre/dataverse' ; import { Box } from '@theatre/dataverse' ; import useRefAndState from '@theatre/studio/utils/useRefAndState' ; import React , { createContext , useCallback , useContext , useEffect , useMemo , } from 'react' ; const ctx = createContext < { cur : IDerivation < number > ; set : ( id : number , delay : number ) => void ; } > ( null ! ) ; let lastTooltipId = 0 ; export const useTooltipOpenState = ( ) : [ isOpen : boolean , setIsOpen : ( isOpen : boolean , delay : number ) => void ] => { const id = useMemo ( ( ) => lastTooltipId ++ , [ ] ) ; const { cur , set } = useContext ( ctx ) ; const [ isOpenRef , isOpen ] = useRefAndState < boolean > ( false ) ; const setIsOpen = useCallback ( ( shouldOpen , delay ) => { set ( shouldOpen ? id : - 1 , delay ) ; } , [ ] ) ; useEffect ( ( ) => { return cur . changesWithoutValues ( ) . tap ( ( ) => { const flag = cur . getValue ( ) === id ; if ( isOpenRef . current !== flag ) isOpenRef . current = flag ; } ) ; } , [ cur , id ] ) ; return [ isOpen , setIsOpen ] ; } ; const TooltipContext = ( { children } ) => { const currentTooltipId = useMemo ( ( ) => new Box ( - 1 ) , [ ] ) ; const cur = currentTooltipId . derivation ; const set = useMemo ( ( ) => { let lastTimeout = undefined ; return ( id , delay ) => { const overridingPreviousTimeout = lastTimeout !== undefined ; if ( lastTimeout !== undefined ) { clearTimeout ( lastTimeout ) ; lastTimeout = undefined ; } if ( delay === 0 || overridingPreviousTimeout ) { currentTooltipId . set ( id ) ; } else { lastTimeout = setTimeout ( ( ) => { currentTooltipId . set ( id ) ; lastTimeout = undefined ; } , delay ) ; } } ; } , [ ] ) ; return < ctx . Provider value = { { cur , set } } > { children } < /ctx.Provider>; } ; export default TooltipContext ;