import { FocusEvent , KeyboardEvent , MouseEvent , SyntheticEvent } from "react" ; import { Keys , isNil , useEventCallback } from "../../shared" ; export type OverlayTrigger = "none" | "click" | "hover" ; export interface UseOverlayTriggerOptions { hideOnLeave ? : boolean ; isDisabled ? : boolean ; onHide ? : ( event : SyntheticEvent ) => void ; onShow ? : ( event : SyntheticEvent ) => void ; trigger ? : OverlayTrigger ; } export function useOverlayTrigger ( isOpen , { hideOnLeave , isDisabled , onHide , onShow , trigger = "click" } = { } ) { const toggle = ( event ) => { if ( isOpen ) { hide ( event ) ; } else { show ( event ) ; } } ; const show = ( event ) => { if ( ! isNil ( onShow ) ) { onShow ( event ) ; } } ; const hide = ( event ) => { if ( ! isNil ( onHide ) ) { onHide ( event ) ; } } ; const handleClick = useEventCallback ( ( event ) => { event . preventDefault ( ) ; toggle ( event ) ; } ) ; const handleKeyDown = useEventCallback ( ( event ) => { switch ( event . key ) { case Keys . enter : case Keys . space : event . preventDefault ( ) ; show ( event ) ; break ; } } ) ; const handleKeyUp = useEventCallback ( ( event ) => { if ( event . key === Keys . space ) { event . preventDefault ( ) ; } } ) ; const handleMouseEnter = useEventCallback ( ( event ) => { show ( event ) ; if ( hideOnLeave ) { let target = event . currentTarget as HTMLElement ; if ( target . hasAttribute ( "disabled" ) ) { target = target . parentElement ; } target . addEventListener ( "mouseleave" , handleMouseLeave ) ; } } ) ; const handleMouseLeave = useEventCallback ( ( event ) => { hide ( event ) ; event . target . removeEventListener ( "mouseleave" , handleMouseLeave ) ; } ) ; const handleFocus = useEventCallback ( ( event ) => { show ( event ) ; } ) ; const handleBlur = useEventCallback ( ( event ) => { hide ( event ) ; } ) ; if ( isDisabled ) { return { } ; } switch ( trigger ) { case "click" : return { onClick : handleClick , onKeyDown : ! isOpen ? handleKeyDown : undefined , onKeyUp : ! isOpen ? handleKeyUp : undefined } ; case "hover" : return { onBlur : hideOnLeave ? handleBlur : undefined , onFocus : handleFocus , onMouseEnter : handleMouseEnter } ; default : return { } ; } }