import * as React from 'react' ; import { getPlacementData } from '@radix-ui/popper' ; import { useComposedRefs } from '@radix-ui/react-compose-refs' ; import { createContextScope } from '@radix-ui/react-context' ; import { useRect } from '@radix-ui/react-use-rect' ; import { useSize } from '@radix-ui/react-use-size' ; import { Primitive } from '@radix-ui/react-primitive' ; import * as ArrowPrimitive from '@radix-ui/react-arrow' ; import type * as Radix from '@radix-ui/react-primitive' ; import type { Scope } from '@radix-ui/react-context' ; import type { Side , Align } from '@radix-ui/popper' ; import type { Measurable } from '@radix-ui/rect' ; const POPPER_NAME = 'Popper' ; type ScopedProps < P > = P & { __scopePopper ? : Scope ; } ; const [ createPopperContext , createPopperScope ] = createContextScope ( POPPER_NAME ) ; type PopperContextValue = { anchor : Measurable | null ; onAnchorChange ( anchor ) : void ; } ; const [ PopperProvider , usePopperContext ] = createPopperContext < PopperContextValue > ( POPPER_NAME ) ; interface PopperProps { children ? : React . ReactNode ; } const Popper = ( props ) => { const { __scopePopper , children } = props ; const [ anchor , setAnchor ] = React . useState < Measurable | null > ( null ) ; return ( < PopperProvider scope = { __scopePopper } anchor = { anchor } onAnchorChange = { setAnchor } > { children } < /PopperProvider>); } ; Popper . displayName = POPPER_NAME ; const ANCHOR_NAME = 'PopperAnchor' ; type PopperAnchorElement = React . ElementRef < typeof Primitive . div > ; type PrimitiveDivProps = Radix . ComponentPropsWithoutRef < typeof Primitive . div > ; interface PopperAnchorProps extends PrimitiveDivProps { virtualRef ? : React . RefObject < Measurable > ; } const PopperAnchor = React . forwardRef < PopperAnchorElement , PopperAnchorProps > ( ( props , forwardedRef ) => { const { __scopePopper , virtualRef , ... anchorProps } = props ; const context = usePopperContext ( ANCHOR_NAME , __scopePopper ) ; const ref = React . useRef < PopperAnchorElement > ( null ) ; const composedRefs = useComposedRefs ( forwardedRef , ref ) ; React . useEffect ( ( ) => { context . onAnchorChange ( virtualRef ?. current || ref . current ) ; } ) ; return virtualRef ? null : < Primitive . div { ... anchorProps } ref = { composedRefs } / > ; } ) ; PopperAnchor . displayName = ANCHOR_NAME ; const CONTENT_NAME = 'PopperContent' ; type PopperContentContextValue = { arrowStyles : React . CSSProperties ; onArrowChange ( arrow ) : void ; onArrowOffsetChange ( offset ? ) : void ; } ; const [ PopperContentProvider , useContentContext ] = createPopperContext < PopperContentContextValue > ( CONTENT_NAME ) ; type PopperContentElement = React . ElementRef < typeof Primitive . div > ; interface PopperContentProps extends PrimitiveDivProps { side ? : Side ; sideOffset ? : number ; align ? : Align ; alignOffset ? : number ; collisionTolerance ? : number ; avoidCollisions ? : boolean ; } const PopperContent = React . forwardRef < PopperContentElement , PopperContentProps > ( ( props , forwardedRef ) => { const { __scopePopper , side = 'bottom' , sideOffset , align = 'center' , alignOffset , collisionTolerance , avoidCollisions = true , ... contentProps } = props ; const context = usePopperContext ( CONTENT_NAME , __scopePopper ) ; const [ arrowOffset , setArrowOffset ] = React . useState < number > ( ) ; const anchorRect = useRect ( context . anchor ) ; const [ content , setContent ] = React . useState < HTMLDivElement | null > ( null ) ; const contentSize = useSize ( content ) ; const [ arrow , setArrow ] = React . useState < HTMLSpanElement | null > ( null ) ; const arrowSize = useSize ( arrow ) ; const composedRefs = useComposedRefs ( forwardedRef , ( node ) => setContent ( node ) ) ; const windowSize = useWindowSize ( ) ; const collisionBoundariesRect = windowSize ? DOMRect . fromRect ( { ... windowSize , x : 0 , y : 0 } ) : undefined ; const { popperStyles , arrowStyles , placedSide , placedAlign } = getPlacementData ( { anchorRect , popperSize : contentSize , arrowSize , arrowOffset , side , sideOffset , align , alignOffset , shouldAvoidCollisions : avoidCollisions , collisionBoundariesRect , collisionTolerance , } ) ; const isPlaced = placedSide !== undefined ; return ( < div style = { popperStyles } data - radix - popper - content - wrapper = "" > < PopperContentProvider scope = { __scopePopper } arrowStyles = { arrowStyles } onArrowChange = { setArrow } onArrowOffsetChange = { setArrowOffset } > < Primitive . div data - side = { placedSide } data - align = { placedAlign } { ... contentProps } style = { { ... contentProps . style , animation : ! isPlaced ? 'none' : undefined , } } ref = { composedRefs } / > < /PopperContentProvider> < /div>); } ) ; PopperContent . displayName = CONTENT_NAME ; const ARROW_NAME = 'PopperArrow' ; type PopperArrowElement = React . ElementRef < typeof ArrowPrimitive . Root > ; type ArrowProps = Radix . ComponentPropsWithoutRef < typeof ArrowPrimitive . Root > ; interface PopperArrowProps extends ArrowProps { offset ? : number ; } const PopperArrow = React . forwardRef < PopperArrowElement , PopperArrowProps > ( function PopperArrow ( props , forwardedRef ) { const { __scopePopper , offset , ... arrowProps } = props ; const context = useContentContext ( ARROW_NAME , __scopePopper ) ; const { onArrowOffsetChange } = context ; React . useEffect ( ( ) => onArrowOffsetChange ( offset ) , [ onArrowOffsetChange , offset ] ) ; return ( < span style = { { ... context . arrowStyles , pointerEvents : 'none' } } > < span ref = { context . onArrowChange } style = { { display : 'inline-block' , verticalAlign : 'top' , pointerEvents : 'auto' , } } > < ArrowPrimitive . Root { ... arrowProps } ref = { forwardedRef } style = { { ... arrowProps . style , display : 'block' , } } /> < /span> < /span>); } ) ; PopperArrow . displayName = ARROW_NAME ; const WINDOW_RESIZE_DEBOUNCE_WAIT_IN_MS = 100 ; function useWindowSize ( ) { const [ windowSize , setWindowSize ] = React . useState < { width : number ; height : number ; } | undefined > ( undefined ) ; React . useEffect ( ( ) => { let debounceTimerId ; function updateWindowSize ( ) { setWindowSize ( { width : window . innerWidth , height : window . innerHeight } ) ; } function handleResize ( ) { window . clearTimeout ( debounceTimerId ) ; debounceTimerId = window . setTimeout ( updateWindowSize , WINDOW_RESIZE_DEBOUNCE_WAIT_IN_MS ) ; } updateWindowSize ( ) ; window . addEventListener ( 'resize' , handleResize ) ; return ( ) => window . removeEventListener ( 'resize' , handleResize ) ; } , [ ] ) ; return windowSize ; } const Root = Popper ; const Anchor = PopperAnchor ; const Content = PopperContent ; const Arrow = PopperArrow ; export { createPopperScope , Popper , PopperAnchor , PopperContent , PopperArrow , Root , Anchor , Content , Arrow , } ; export type { PopperProps , PopperAnchorProps , PopperContentProps , PopperArrowProps } ;