// packages/core/src/components/popover/popover-root.tsx import type { Middleware, Placement } from "@floating-ui/dom"; import { flip, offset, shift } from "@floating-ui/dom"; import type { Accessor, JSX } from "solid-js"; import { createSignal, createUniqueId } from "solid-js"; import { type CreateDisclosureStateOptions, createDisclosureState, } from "../../primitives/create-disclosure-state"; import { createFloating } from "../../primitives/create-floating"; import { InternalPopoverContextProvider, PopoverPublicContextProvider, type InternalPopoverContextValue, } from "./popover-context"; import type { PopoverRootProps } from "./popover.props"; export type { PopoverRootProps } from "./popover.props"; /** * Root component for Popover. Manages open state, floating positioning, * and provides context to all Popover parts. Renders no DOM elements. */ export function PopoverRoot(props: PopoverRootProps): JSX.Element { const disclosure = createDisclosureState({ get open() { return props.open; }, get defaultOpen() { return props.defaultOpen; }, get onOpenChange() { return props.onOpenChange; }, } as CreateDisclosureStateOptions); const contentId = createUniqueId(); const [triggerRef, setTriggerRef] = createSignal(null); const [contentRef, setContentRef] = createSignal(null); const floating = createFloating({ anchor: triggerRef, floating: contentRef, placement: (() => props.placement ?? "bottom") as Accessor, middleware: (() => [offset(8), flip(), shift({ padding: 8 })]) as Accessor, open: disclosure.isOpen, }); const internalCtx: InternalPopoverContextValue = { isOpen: disclosure.isOpen, setOpen: (open) => (open ? disclosure.open() : disclosure.close()), modal: () => props.modal ?? false, contentId: () => contentId, triggerRef, setTriggerRef, contentRef, setContentRef, floatingStyle: floating.style, }; return ( props.modal ?? false }} > {props.children} ); }