import * as React from 'react' ; import { useCloseOnEscape , useAlwaysCloseOnOutsideClick , usePopupModel , useCloseOnFullscreenExit , } from '@workday/canvas-kit-react/popup' ; import { useUniqueId } from '@workday/canvas-kit-react/common' ; const useIntentTimer = ( fn , waitMs = 0 ) : { start ( ) : void ; clear ( ) : void ; } => { const timer = React . useRef ( ) as React . MutableRefObject < number | undefined > ; const start = ( ) => { timer . current = window . setTimeout ( fn , waitMs ) ; } ; const clear = ( ) => { window . clearTimeout ( timer . current ) ; timer . current = undefined ; } ; React . useEffect ( ( ) => { return ( ) => { window . clearTimeout ( timer . current ) ; } ; } , [ timer ] ) ; return { start , clear , } ; } ; const isInteractiveElement = ( element ) => { const tagName = element . tagName . toLowerCase ( ) ; const tabIndex = element . getAttribute ( 'tabindex' ) ; switch ( tagName ) { case 'button' : case 'input' : case 'select' : case 'textarea' : case 'details' : return true ; default : return tabIndex ? Number ( tabIndex ) >= 0 : false ; } } ; /**
 * Convenience hook for creating components with tooltips. It will return an object of properties to mix
 * into a target, popper and tooltip
 */ export function useTooltip < T extends Element = Element > ( { type = 'label' , titleText = '' , showDelay = 300 , hideDelay = 100 , } = { } ) { const mouseDownRef = React . useRef ( false ) ; const popupModel = usePopupModel ( ) ; const [ anchorElement , setAnchorElement ] = React . useState < T | null > ( null ) ; const id = useUniqueId ( ) ; const intentTimerHide = useIntentTimer ( popupModel . events . hide , hideDelay ) ; const intentTimerShow = useIntentTimer ( popupModel . events . show , showDelay ) ; const onHide = ( ) => { intentTimerHide . start ( ) ; intentTimerShow . clear ( ) ; } ; const onOpen = ( ) => { intentTimerShow . start ( ) ; intentTimerHide . clear ( ) ; } ; const onOpenFromTarget = ( event ) => { setAnchorElement ( event . currentTarget as T ) ; onOpen ( ) ; } ; const onFocus = ( event ) => { if ( ! mouseDownRef . current ) { onOpenFromTarget ( event ) ; } mouseDownRef . current = false ; } ; const onMouseDown = ( event ) => { mouseDownRef . current = true ; if ( isInteractiveElement ( event . currentTarget ) ) { popupModel . events . hide ( ) ; } } ; useCloseOnEscape ( popupModel ) ; useAlwaysCloseOnOutsideClick ( popupModel ) ; useCloseOnFullscreenExit ( popupModel ) ; const visible = popupModel . state . visibility !== 'hidden' ; return { /** Mix these properties into the target element. **Must be an Element** */ targetProps : { 'aria-describedby' : type === 'describe' && visible ? id : undefined , 'aria-label' : type === 'label' ? titleText : undefined , onMouseEnter : onOpenFromTarget , onMouseLeave : onHide , onMouseDown , onFocus , onBlur : onHide , } , /** Mix these properties into the `Popper` component */ popperProps : { open : visible , anchorElement , ref : popupModel . state . stackRef , } , /** Mix these properties into the `TooltipContainer` component */ tooltipProps : { id : type === 'describe' && visible ? id : undefined , role : 'tooltip' , onMouseEnter : onOpen , onMouseLeave : onHide , } , } ; }