@zag-js/popper
Version:
Dynamic positioning logic for ui machines
133 lines (130 loc) • 4.85 kB
text/typescript
import { VirtualElement, Placement, Boundary, AutoUpdateOptions, ComputePositionReturn } from '@floating-ui/dom';
export { AutoUpdateOptions, Boundary, ComputePositionReturn, Placement } from '@floating-ui/dom';
type MaybeRectElement = HTMLElement | VirtualElement | null;
type MaybeElement = HTMLElement | null;
type MaybeFn<T> = T | (() => T);
type PlacementSide = "top" | "right" | "bottom" | "left";
type PlacementAlign = "start" | "center" | "end";
interface AnchorRect {
x?: number | undefined;
y?: number | undefined;
width?: number | undefined;
height?: number | undefined;
}
interface PositioningOptions {
/**
* Whether styles applied by the positioning utility should be restored on cleanup.
*/
restoreStyles?: boolean | undefined;
/**
* Whether to apply computed position styles (`--x`, `--y`, `--z-index`) to the floating element.
* Set to `false` when the consumer applies these from context (e.g. for exit animations).
* @default true
*/
applyStyles?: boolean | undefined;
/**
* Whether the popover should be hidden when the reference element is detached
*/
hideWhenDetached?: boolean | undefined;
/**
* The strategy to use for positioning
*/
strategy?: "absolute" | "fixed" | undefined;
/**
* The initial placement of the floating element
*/
placement?: Placement | undefined;
/**
* The offset of the floating element
*/
offset?: {
mainAxis?: number | undefined;
crossAxis?: number | undefined;
} | undefined;
/**
* The main axis offset or gap between the reference and floating elements
*/
gutter?: number | undefined;
/**
* The secondary axis offset or gap between the reference and floating elements
*/
shift?: number | undefined;
/**
* The virtual padding around the viewport edges to check for overflow
*/
overflowPadding?: number | undefined;
/**
* The minimum padding between the arrow and the floating element's corner.
* @default 4
*/
arrowPadding?: number | undefined;
/**
* Whether to flip the placement
*/
flip?: boolean | Placement[] | undefined;
/**
* Whether the popover should slide when it overflows.
*/
slide?: boolean | undefined;
/**
* Whether the floating element can overlap the reference element
* @default false
*/
overlap?: boolean | undefined;
/**
* Whether to make the floating element same width as the reference element
*/
sameWidth?: boolean | undefined;
/**
* Whether the popover should fit the viewport.
*/
fitViewport?: boolean | undefined;
/**
* Whether to use the size middleware from Floating UI.
* It computes and sets CSS variables (`--reference-width`, `--reference-height`, `--available-width`, `--available-height`) used by `sameWidth` and `fitViewport`.
*
* Disabling it improves scroll performance with heavy content by avoiding layout thrashing on each update.
* Only applies when both `sameWidth` and `fitViewport` are false — the middleware is always used when either is enabled.
* @default true
*/
sizeMiddleware?: boolean | undefined;
/**
* The overflow boundary of the reference element
* Accepts a function returning a Boundary, a Boundary directly,
* or the shorthand string 'clipping-ancestors' which maps to Floating UI's 'clippingAncestors'.
*/
boundary?: (() => Boundary) | Boundary | "clipping-ancestors" | undefined;
/**
* Options to activate auto-update listeners
*/
listeners?: boolean | AutoUpdateOptions | undefined;
/**
* Function called when the placement is computed
*/
onComplete?: ((data: ComputePositionReturn) => void) | undefined;
/**
* Function called when the floating element is positioned or not
*/
onPositioned?: ((data: {
placed: boolean;
}) => void) | undefined;
/**
* Function that returns the anchor element.
* Useful when you want to use a different element as the anchor.
*/
getAnchorElement?: (() => HTMLElement | VirtualElement | null) | undefined;
/**
* Function that returns the anchor rect
* @deprecated Use `getAnchorElement` instead
*/
getAnchorRect?: ((element: HTMLElement | VirtualElement | null) => AnchorRect | null) | undefined;
/**
* A callback that will be called when the popover needs to calculate its
* position.
*/
updatePosition?: ((data: {
updatePosition: () => Promise<void>;
floatingElement: HTMLElement | null;
}) => void | Promise<void>) | undefined;
}
export type { AnchorRect, MaybeElement, MaybeFn, MaybeRectElement, PlacementAlign, PlacementSide, PositioningOptions };