import { FloatingArrow } from "@floating-ui/react"; import { clsx } from "clsx"; import React, { createElement, useEffect } from "react"; import Portal from "./portal"; import TabLoop from "./tab_loop"; import withFloating from "./with_floating"; import type { FloatingProps } from "./with_floating"; import type { ReactNode } from "react"; interface PortalProps extends Omit< React.ComponentPropsWithoutRef, "children" > {} interface TabLoopProps extends Omit< React.ComponentPropsWithoutRef, "children" > {} interface PopperComponentProps extends Omit, TabLoopProps, FloatingProps { className?: string; wrapperClassName?: string; popperComponent: React.ReactNode; popperContainer?: React.FC<{ children?: ReactNode | undefined }>; targetComponent: React.ReactNode; popperOnKeyDown: React.KeyboardEventHandler; showArrow?: boolean; portalId?: PortalProps["portalId"]; popperTargetRef?: React.RefObject; monthHeaderPosition?: "top" | "middle" | "bottom"; } // Exported for testing purposes export const PopperComponent: React.FC = (props) => { const { className, wrapperClassName, hidePopper = true, popperComponent, targetComponent, enableTabLoop, popperOnKeyDown, portalId, portalHost, popperProps, showArrow, popperTargetRef, monthHeaderPosition, } = props; // When a custom popperTargetRef is provided, use it as the position reference // This allows the popper to be positioned relative to a specific element // within the custom input, rather than the wrapper div useEffect(() => { if (popperTargetRef?.current) { popperProps.refs.setPositionReference(popperTargetRef.current); } }, [popperTargetRef, popperProps.refs]); let popper: React.ReactElement | undefined = undefined; if (!hidePopper) { const classes = clsx( "react-datepicker-popper", !showArrow && "react-datepicker-popper-offset", monthHeaderPosition === "middle" && "react-datepicker-popper--header-middle", monthHeaderPosition === "bottom" && "react-datepicker-popper--header-bottom", className, ); popper = ( {/* eslint-disable react-hooks/refs -- Floating UI values are designed to be used during render */}
{popperComponent} {showArrow && ( )}
{/* eslint-enable react-hooks/refs */}
); } if (props.popperContainer) { popper = createElement(props.popperContainer, {}, popper); } if (portalId && !hidePopper) { popper = ( {popper} ); } const wrapperClasses = clsx("react-datepicker-wrapper", wrapperClassName); return ( <> {/* eslint-disable-next-line react-hooks/refs -- Floating UI refs are designed to be used during render */}
{targetComponent}
{popper} ); }; export default withFloating(PopperComponent);