import React from 'react'; import { PositionStrategy } from './PopperContainer'; /** * Base directions for popper positioning. * These are the primary axes around which the popper can be placed. * * @default 'bottom' (when used as anchorPos) * @example * ```tsx * type Direction = 'top' | 'bottom' | 'left' | 'right'; * ``` */ export type Direction = 'top' | 'left' | 'right' | 'bottom'; /** * Auto placement modifiers that enable intelligent positioning. * The popper will automatically choose the best placement that fits in the viewport. * - `auto`: Dynamically selects the optimal direction * - `auto-top`, `auto-bottom`, `auto-left`, `auto-right`: Auto placement with priority given to the specified direction * * @example * ```tsx * // Will try to place on top first, but will flip if needed * ... * * // Will try all directions equally * ... * ``` */ export type AutoModifier = 'auto' | 'auto-top' | 'auto-bottom' | 'auto-left' | 'auto-right'; /** * Precise placement modifiers for fine-tuned positioning. * These combine a base direction with specific alignment options: * - `start`/`end`: Aligns to the beginning or end of the anchor (useful for RTL layouts) * - `left`/`right`: Horizontal alignment for vertical placements * - `top`/`bottom`: Vertical alignment for horizontal placements * * @example * ```tsx * // Corner placements * Aligns to top-left corner * * // Logical placements (RTL-friendly) * Aligns to bottom edge, start side * * // Side alignments * Aligns to left side, top edge * ``` */ export type Modifier = 'top-start' | 'top-end' | 'top-left' | 'top-right' | 'bottom-end' | 'bottom-start' | 'bottom-right' | 'bottom-left' | 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom' | 'bottom-fill' | 'top-fill'; /** * Available placement options for the popper. * Combines basic directions, precise modifiers, and auto-placement options * to provide full control over popper positioning. * * Categories: * - **Basic directions**: `top`, `bottom`, `left`, `right` - Centered placement * - **Corner placements**: `top-left`, `top-right`, `bottom-left`, `bottom-right` - Aligned to corners * - **Logical placements**: `top-start`, `top-end`, `bottom-start`, `bottom-end` - RTL-aware alignment * - **Side alignments**: `left-top`, `left-bottom`, `right-top`, `right-bottom` - Edge-aligned * - **Auto placements**: `auto`, `auto-top`, `auto-bottom`, `auto-left`, `auto-right` - Intelligent positioning * * @default 'bottom' * @example * ```tsx * // Basic centered placement * Centered below anchor * * // Corner placement * Attached to top-right corner * * // Auto placement with priority * Try left first, then find best fit * * // RTL-aware placement * Respects text direction * ``` */ export type AnchorPos = Direction | Modifier | AutoModifier; export interface UsePopperProps { readonly anchorElement: HTMLElement | null; readonly anchorPos?: AnchorPos; readonly alternativePlacements?: readonly AnchorPos[]; readonly positionStrategy?: PositionStrategy; readonly autoFlip?: boolean; readonly offset?: number; readonly viewportMargin?: number; readonly isOpen?: boolean; } export interface UsePopperResult { readonly actualPlacement: AnchorPos; readonly style: React.CSSProperties | null; readonly popperRef: React.MutableRefObject; readonly isVisible: boolean; readonly calculatePosition: () => void; readonly scrollableAncestor: HTMLElement | Window | null; readonly setActualPlacement: React.Dispatch>; readonly setStyle: React.Dispatch>; readonly setIsVisible: React.Dispatch>; } /** * Finds the closest scrollable ancestor of an element. * A scrollable element is one that has overflow set to auto, scroll, or overlay * and has content that overflows, allowing scrolling. * * @param element - The element to start searching from * @param includeHidden - Whether to consider elements with overflow: hidden * @returns The closest scrollable ancestor or window if none found */ export declare const findScrollableAncestor: (element: HTMLElement | null, includeHidden?: boolean) => HTMLElement | Window | null; export declare const usePopper: (props: UsePopperProps) => UsePopperResult; export default usePopper;