"use client"; // packages/react/popper/src/Popper.tsx import * as React from "react"; import { useFloating, autoUpdate, offset, shift, limitShift, hide, arrow as floatingUIarrow, flip, size } from "@floating-ui/react-dom"; import * as ArrowPrimitive from "@radix-ui/react-arrow"; import { useComposedRefs } from "@radix-ui/react-compose-refs"; import { createContextScope } from "@radix-ui/react-context"; import { Primitive } from "@radix-ui/react-primitive"; import { useCallbackRef } from "@radix-ui/react-use-callback-ref"; import { useLayoutEffect } from "@radix-ui/react-use-layout-effect"; import { useSize } from "@radix-ui/react-use-size"; import { jsx } from "react/jsx-runtime"; var SIDE_OPTIONS = ["top", "right", "bottom", "left"]; var ALIGN_OPTIONS = ["start", "center", "end"]; var POPPER_NAME = "Popper"; var [createPopperContext, createPopperScope] = createContextScope(POPPER_NAME); var [PopperProvider, usePopperContext] = createPopperContext(POPPER_NAME); var Popper = (props) => { const { __scopePopper, children } = props; const [anchor, setAnchor] = React.useState(null); return /* @__PURE__ */ jsx(PopperProvider, { scope: __scopePopper, anchor, onAnchorChange: setAnchor, children }); }; Popper.displayName = POPPER_NAME; var ANCHOR_NAME = "PopperAnchor"; var PopperAnchor = React.forwardRef( (props, forwardedRef) => { const { __scopePopper, virtualRef, ...anchorProps } = props; const context = usePopperContext(ANCHOR_NAME, __scopePopper); const ref = React.useRef(null); const composedRefs = useComposedRefs(forwardedRef, ref); React.useEffect(() => { context.onAnchorChange(virtualRef?.current || ref.current); }); return virtualRef ? null : /* @__PURE__ */ jsx(Primitive.div, { ...anchorProps, ref: composedRefs }); } ); PopperAnchor.displayName = ANCHOR_NAME; var CONTENT_NAME = "PopperContent"; var [PopperContentProvider, useContentContext] = createPopperContext(CONTENT_NAME); var PopperContent = React.forwardRef( (props, forwardedRef) => { const { __scopePopper, side = "bottom", sideOffset = 0, align = "center", alignOffset = 0, arrowPadding = 0, avoidCollisions = true, collisionBoundary = [], collisionPadding: collisionPaddingProp = 0, sticky = "partial", hideWhenDetached = false, updatePositionStrategy = "optimized", onPlaced, ...contentProps } = props; const context = usePopperContext(CONTENT_NAME, __scopePopper); const [content, setContent] = React.useState(null); const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node)); const [arrow, setArrow] = React.useState(null); const arrowSize = useSize(arrow); const arrowWidth = arrowSize?.width ?? 0; const arrowHeight = arrowSize?.height ?? 0; const desiredPlacement = side + (align !== "center" ? "-" + align : ""); const collisionPadding = typeof collisionPaddingProp === "number" ? collisionPaddingProp : { top: 0, right: 0, bottom: 0, left: 0, ...collisionPaddingProp }; const boundary = Array.isArray(collisionBoundary) ? collisionBoundary : [collisionBoundary]; const hasExplicitBoundaries = boundary.length > 0; const detectOverflowOptions = { padding: collisionPadding, boundary: boundary.filter(isNotNull), // with `strategy: 'fixed'`, this is the only way to get it to respect boundaries altBoundary: hasExplicitBoundaries }; const { refs, floatingStyles, placement, isPositioned, middlewareData } = useFloating({ // default to `fixed` strategy so users don't have to pick and we also avoid focus scroll issues strategy: "fixed", placement: desiredPlacement, whileElementsMounted: (...args) => { const cleanup = autoUpdate(...args, { animationFrame: updatePositionStrategy === "always" }); return cleanup; }, elements: { reference: context.anchor }, middleware: [ offset({ mainAxis: sideOffset + arrowHeight, alignmentAxis: alignOffset }), avoidCollisions && shift({ mainAxis: true, crossAxis: false, limiter: sticky === "partial" ? limitShift() : void 0, ...detectOverflowOptions }), avoidCollisions && flip({ ...detectOverflowOptions }), size({ ...detectOverflowOptions, apply: ({ elements, rects, availableWidth, availableHeight }) => { const { width: anchorWidth, height: anchorHeight } = rects.reference; const contentStyle = elements.floating.style; contentStyle.setProperty("--radix-popper-available-width", `${availableWidth}px`); contentStyle.setProperty("--radix-popper-available-height", `${availableHeight}px`); contentStyle.setProperty("--radix-popper-anchor-width", `${anchorWidth}px`); contentStyle.setProperty("--radix-popper-anchor-height", `${anchorHeight}px`); } }), arrow && floatingUIarrow({ element: arrow, padding: arrowPadding }), transformOrigin({ arrowWidth, arrowHeight }), hideWhenDetached && hide({ strategy: "referenceHidden", ...detectOverflowOptions }) ] }); const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement); const handlePlaced = useCallbackRef(onPlaced); useLayoutEffect(() => { if (isPositioned) { handlePlaced?.(); } }, [isPositioned, handlePlaced]); const arrowX = middlewareData.arrow?.x; const arrowY = middlewareData.arrow?.y; const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0; const [contentZIndex, setContentZIndex] = React.useState(); useLayoutEffect(() => { if (content) setContentZIndex(window.getComputedStyle(content).zIndex); }, [content]); return /* @__PURE__ */ jsx( "div", { ref: refs.setFloating, "data-radix-popper-content-wrapper": "", style: { ...floatingStyles, transform: isPositioned ? floatingStyles.transform : "translate(0, -200%)", // keep off the page when measuring minWidth: "max-content", zIndex: contentZIndex, ["--radix-popper-transform-origin"]: [ middlewareData.transformOrigin?.x, middlewareData.transformOrigin?.y ].join(" "), // hide the content if using the hide middleware and should be hidden // set visibility to hidden and disable pointer events so the UI behaves // as if the PopperContent isn't there at all ...middlewareData.hide?.referenceHidden && { visibility: "hidden", pointerEvents: "none" } }, dir: props.dir, children: /* @__PURE__ */ jsx( PopperContentProvider, { scope: __scopePopper, placedSide, onArrowChange: setArrow, arrowX, arrowY, shouldHideArrow: cannotCenterArrow, children: /* @__PURE__ */ jsx( Primitive.div, { "data-side": placedSide, "data-align": placedAlign, ...contentProps, ref: composedRefs, style: { ...contentProps.style, // if the PopperContent hasn't been placed yet (not all measurements done) // we prevent animations so that users's animation don't kick in too early referring wrong sides animation: !isPositioned ? "none" : void 0 } } ) } ) } ); } ); PopperContent.displayName = CONTENT_NAME; var ARROW_NAME = "PopperArrow"; var OPPOSITE_SIDE = { top: "bottom", right: "left", bottom: "top", left: "right" }; var PopperArrow = React.forwardRef(function PopperArrow2(props, forwardedRef) { const { __scopePopper, ...arrowProps } = props; const contentContext = useContentContext(ARROW_NAME, __scopePopper); const baseSide = OPPOSITE_SIDE[contentContext.placedSide]; return ( // we have to use an extra wrapper because `ResizeObserver` (used by `useSize`) // doesn't report size as we'd expect on SVG elements. // it reports their bounding box which is effectively the largest path inside the SVG. /* @__PURE__ */ jsx( "span", { ref: contentContext.onArrowChange, style: { position: "absolute", left: contentContext.arrowX, top: contentContext.arrowY, [baseSide]: 0, transformOrigin: { top: "", right: "0 0", bottom: "center 0", left: "100% 0" }[contentContext.placedSide], transform: { top: "translateY(100%)", right: "translateY(50%) rotate(90deg) translateX(-50%)", bottom: `rotate(180deg)`, left: "translateY(50%) rotate(-90deg) translateX(50%)" }[contentContext.placedSide], visibility: contentContext.shouldHideArrow ? "hidden" : void 0 }, children: /* @__PURE__ */ jsx( ArrowPrimitive.Root, { ...arrowProps, ref: forwardedRef, style: { ...arrowProps.style, // ensures the element can be measured correctly (mostly for if SVG) display: "block" } } ) } ) ); }); PopperArrow.displayName = ARROW_NAME; function isNotNull(value) { return value !== null; } var transformOrigin = (options) => ({ name: "transformOrigin", options, fn(data) { const { placement, rects, middlewareData } = data; const cannotCenterArrow = middlewareData.arrow?.centerOffset !== 0; const isArrowHidden = cannotCenterArrow; const arrowWidth = isArrowHidden ? 0 : options.arrowWidth; const arrowHeight = isArrowHidden ? 0 : options.arrowHeight; const [placedSide, placedAlign] = getSideAndAlignFromPlacement(placement); const noArrowAlign = { start: "0%", center: "50%", end: "100%" }[placedAlign]; const arrowXCenter = (middlewareData.arrow?.x ?? 0) + arrowWidth / 2; const arrowYCenter = (middlewareData.arrow?.y ?? 0) + arrowHeight / 2; let x = ""; let y = ""; if (placedSide === "bottom") { x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`; y = `${-arrowHeight}px`; } else if (placedSide === "top") { x = isArrowHidden ? noArrowAlign : `${arrowXCenter}px`; y = `${rects.floating.height + arrowHeight}px`; } else if (placedSide === "right") { x = `${-arrowHeight}px`; y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`; } else if (placedSide === "left") { x = `${rects.floating.width + arrowHeight}px`; y = isArrowHidden ? noArrowAlign : `${arrowYCenter}px`; } return { data: { x, y } }; } }); function getSideAndAlignFromPlacement(placement) { const [side, align = "center"] = placement.split("-"); return [side, align]; } var Root2 = Popper; var Anchor = PopperAnchor; var Content = PopperContent; var Arrow = PopperArrow; export { ALIGN_OPTIONS, Anchor, Arrow, Content, Popper, PopperAnchor, PopperArrow, PopperContent, Root2 as Root, SIDE_OPTIONS, createPopperScope }; //# sourceMappingURL=index.mjs.map