export type AnchoredSide = 'top' | 'right' | 'bottom' | 'left'; export type AnchoredAlign = 'start' | 'center' | 'end'; export interface AnchoredPositionInput { anchorRect: Pick; popupWidth: number; popupHeight: number; side: AnchoredSide; align: AnchoredAlign; sideOffsetPx: number; alignOffsetPx: number; viewportPadPx: number; viewportWidth: number; viewportHeight: number; } export interface AnchoredPosition { x: number; y: number; /** Side actually used, which differs from the request when placement flipped. */ resolvedSide: AnchoredSide; } /** * Pure viewport-fixed anchored-popup layout math shared by every element-anchored * overlay: menus, selects, tooltips, and anchored toasts. * * `side` is preferred. When the popup spills past the padded viewport there and * the opposite side spills less, placement flips on the main axis; the result is * then clamped into the viewport on both axes. Cross-axis `align` is applied * before clamping so `alignOffsetPx` stays an additive nudge. * * Callers own their own anchor semantics — inner-cell alignment offsets and * minimum widths belong to the calling component, not here. * @see choice-popup-alignment.ts for the choice-cell alignment transform. */ export declare function computeAnchoredPosition(input: AnchoredPositionInput): AnchoredPosition;