packages/core/src/computeCoordsFromPlacement.ts
import type {Coords, ElementRects, Placement} from '@floating-ui/utils';
import {
getAlignment,
getAlignmentAxis,
getAxisLength,
getSide,
getSideAxis,
} from '@floating-ui/utils';
export function computeCoordsFromPlacement(
{reference, floating}: ElementRects,
placement: Placement,
rtl?: boolean,
): Coords {
const sideAxis = getSideAxis(placement);
const alignmentAxis = getAlignmentAxis(placement);
const alignLength = getAxisLength(alignmentAxis);
const side = getSide(placement);
const isVertical = sideAxis === 'y';
const commonX = reference.x + reference.width / 2 - floating.width / 2;
const commonY = reference.y + reference.height / 2 - floating.height / 2;
const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
let coords: Coords;
switch (side) {
case 'top':
coords = {x: commonX, y: reference.y - floating.height};
break;
case 'bottom':
coords = {x: commonX, y: reference.y + reference.height};
break;
case 'right':
coords = {x: reference.x + reference.width, y: commonY};
break;
case 'left':
coords = {x: reference.x - floating.width, y: commonY};
break;
default:
coords = {x: reference.x, y: reference.y};
}
switch (getAlignment(placement)) {
case 'start':
coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
break;
case 'end':
coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
break;
default:
}
return coords;
}