"use client" import * as React from "react" export type PopoverFlipSide = "top" | "bottom" const VIEWPORT_PADDING = 16 /** * Pick top vs bottom for tall popovers (calendars, long menus) when Radix * collision alone leaves the content clipped at the viewport edge. */ export function usePopoverFlipSide( open: boolean, anchorRef: React.RefObject, estimatedHeight: number, ): PopoverFlipSide { const [side, setSide] = React.useState("bottom") React.useLayoutEffect(() => { if (!open) { setSide("bottom") return } const update = () => { const el = anchorRef.current if (!el) return const rect = el.getBoundingClientRect() const below = window.innerHeight - rect.bottom - VIEWPORT_PADDING const above = rect.top - VIEWPORT_PADDING if (below >= estimatedHeight) { setSide("bottom") } else if (above >= estimatedHeight) { setSide("top") } else { setSide(above > below ? "top" : "bottom") } } update() window.addEventListener("resize", update) window.addEventListener("scroll", update, { capture: true, passive: true }) return () => { window.removeEventListener("resize", update) window.removeEventListener("scroll", update, true) } }, [open, anchorRef, estimatedHeight]) return side }