@linzjs/step-ag-grid
Version:
[](https://github.com/semantic-release/semantic-release) > Reusable [ag-grid](https://www.ag-grid.com/) component for LINZ / Toitū te whenua.
62 lines (55 loc) • 1.75 kB
text/typescript
import { MenuDirection } from '../types';
import { getPositionHelpers } from './getPositionHelpers';
export const positionContextMenu = ({
positionHelpers,
anchorPoint,
}: {
positionHelpers: ReturnType<typeof getPositionHelpers>;
anchorPoint: { x: number; y: number };
}): {
x: number;
y: number;
computedDirection: MenuDirection;
} => {
const {
menuRect,
containerRect,
getLeftOverflow,
getRightOverflow,
getTopOverflow,
getBottomOverflow,
confineHorizontally,
confineVertically,
} = positionHelpers;
let x, y;
// position the menu with cursor pointing to its top-left corner
x = anchorPoint.x - containerRect.left;
y = anchorPoint.y - containerRect.top;
// If menu overflows to the right of viewport,
// try to reposition it on the left side of cursor.
// If menu overflows to the left of viewport after repositioning,
// choose a side which has less overflow
// and adjust x to have it contained within the viewport.
const rightOverflow = getRightOverflow(x);
if (rightOverflow > 0) {
const adjustedX = x - menuRect.width;
const leftOverflow = getLeftOverflow(adjustedX);
if (leftOverflow >= 0 || -leftOverflow < rightOverflow) {
x = adjustedX;
}
x = confineHorizontally(x);
}
// Similar logic to the left and right side above.
let computedDirection: MenuDirection = 'bottom';
const bottomOverflow = getBottomOverflow(y);
if (bottomOverflow > 0) {
const adjustedY = y - menuRect.height;
const topOverflow = getTopOverflow(adjustedY);
if (topOverflow >= 0 || -topOverflow < bottomOverflow) {
y = adjustedY;
computedDirection = 'top';
}
y = confineVertically(y);
}
return { x, y, computedDirection };
};