import { Placement } from "@popperjs/core" ; import { background } from "../../background/background" ; import { border } from "../../border/border" ; import { shadow } from "../../shadow/shadow" ; import { ReactNode , useEffect , useState } from "react" ; import { createPortal } from "react-dom" ; import { usePopper } from "react-popper" ; import { getPortalContainer } from "../../utils/utils" ; import s from "./pane.module.css" ; interface Props { target : HTMLDivElement ; children : ReactNode ; placement ? : Placement ; onOutsideClick ? : ( ) => void ; } export const PopoverPane = ( props ) : JSX . Element => { const [ content , setContent ] = useState < HTMLDivElement | null > ( null ) ; const [ arrow , setArrow ] = useState < HTMLDivElement | null > ( null ) ; const style = PopoverPane . styles . outset ; const { styles , attributes , update } = usePopper ( props . target , content , { placement : props . placement ?? "top" , modifiers : [ { name : "offset" , options : { offset : [ 0 , 8 ] } } , { name : "arrow" , options : { element : arrow } } , ] , } ) ; const { onOutsideClick } = props ; useEffect ( ( ) => { if ( content === null ) return ; const listener = ( event ) => { if ( ! ( event . target instanceof Node ) ) return ; if ( content . contains ( event . target ) ) return ; onOutsideClick ?. ( ) ; } ; window . setTimeout ( ( ) => { document . addEventListener ( "click" , listener ) ; } , 0 ) ; return ( ) => void document . removeEventListener ( "click" , listener ) ; } , [ content , onOutsideClick ] ) ; useEffect ( ( ) => { update ?. ( ) ; } , [ update ] ) ; const element = ( < div ref = { setContent } style = { styles . popper } className = { [ s . container , style . content ] . join ( " " ) } { ... attributes . popper } > { props . children } { } < div style = { styles . arrow } ref = { setArrow } className = { s . arrow } { ... attributes . arrow } > < div className = { [ s . arrowShape , style . arrow ] . join ( " " ) } /> < /div> < /div>); return createPortal ( element , getPortalContainer ( ) ) ; } ; PopoverPane . styles = { outset : { content : [ shadow . dropStrong , border . px1 , border . strong , background . strong , ] . join ( " " ) , arrow : [ border . px1 , border . strong , background . strong ] . join ( " " ) , } , } ;