import classnames from 'classnames' ; import { isArray } from 'lodash' ; import isUndefined from 'lodash/isUndefined' ; import { ElementType , useEffect , useRef , useState } from 'react' ; import { FiExternalLink } from 'react-icons/fi' ; import ReactMarkdown from 'react-markdown' ; import useOutsideClick from '../../../hooks/useOutsideClick' ; import styles from './ParamInfo.module.css' ; interface Props { element : JSX . Element ; info : string | JSX . Element ; isMarkdown ? : boolean ; className ? : string ; fixedWidth ? : boolean ; } interface HeadingProps { level : number ; children ? : JSX . Element [ ] ; } interface LinkProps { href : string ; target : string ; children : any ; } const Heading = ( data ) => { const Tag = `h${ data . level }` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' ; return < Tag className = { `text-dark lh-1 fw-bold ${ styles . header }` } > { data . children } < /Tag>; } ; const Link = ( data ) => { const linkIcon = data . children && isArray ( data . children ) && data . children [ 0 ] === 'iconLink' ? ( < FiExternalLink className = { `position-relative ${ styles . linkIcon }` } />) : undefined; return ( < a href = { data . href } target = { data . target } rel = "noopener noreferrer" className = "d-inline-block text-dark" > { linkIcon || data . children } < /a>); } ; const ParamInfo = ( props ) => { const ref = useRef ( null ) ; const [ openStatus , setOpenStatus ] = useState ( false ) ; const [ onParamHover , setOnParamHover ] = useState ( false ) ; const [ onDropdownHover , setOnDropdownHover ] = useState ( false ) ; useOutsideClick ( [ ref ] , openStatus , ( ) => setOpenStatus ( false ) ) ; useEffect ( ( ) => { let timeout ; if ( ! openStatus && ( onParamHover || onDropdownHover ) ) { timeout = setTimeout ( ( ) => { setOpenStatus ( true ) ; } , 100 ) ; } if ( openStatus && ! onParamHover && ! onDropdownHover ) { timeout = setTimeout ( ( ) => { setOpenStatus ( false ) ; } , 50 ) ; } return ( ) => { if ( ! isUndefined ( timeout ) ) { clearTimeout ( timeout ) ; } } ; } , [ onParamHover , onDropdownHover , openStatus ] ) ; return ( < div className = { `position-relative d-inline-block ${ props . className }` } > < div className = "position-absolute" > < div ref = { ref } data - testid = "infoDropdown" className = { classnames ( 'dropdown-menu dropdown-menu-left p-0 show d-block me-1 mb-1 text-wrap' , styles . dropdown , { invisible : ! openStatus } , { visible : openStatus } , { [ styles . fixedWidth ] : ! isUndefined ( props . fixedWidth ) && props . fixedWidth } ) } onMouseEnter = { ( ) => setOnDropdownHover ( true ) } onMouseLeave = { ( ) => setOnDropdownHover ( false ) } > < div className = { styles . content } > { ! isUndefined ( props . isMarkdown ) && props . isMarkdown ? ( < ReactMarkdown className = "p-2" children = { props . info as string } components = { { h1 : Heading , h2 : Heading , h3 : Heading , h4 : Heading , h5 : Heading , h6 : Heading , a : Link , } } linkTarget = "_blank" skipHtml / > ) : ( < > { props . info } < />)} < /div> < /div> < /div> < div data - testid = "infoText" onMouseEnter = { ( e ) => { e . preventDefault ( ) ; setOnParamHover ( true ) ; } } onMouseLeave = { ( ) => { setOnParamHover ( false ) ; } } aria - expanded = { openStatus } > { props . element } < /div> < /div>); } ; export default ParamInfo ;