@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.
94 lines (86 loc) • 2.63 kB
text/typescript
import { MutableRefObject } from 'react';
import { MenuDirection } from '../types';
import { getPositionHelpers } from './getPositionHelpers';
import { placeArrowVertical } from './placeArrowVertical';
export interface placeLeftorRightParams {
anchorRect: DOMRect;
placeLeftorRightY: number;
placeLeftX: number;
placeRightX: number;
arrowRef: MutableRefObject<HTMLElement | null>;
arrow?: boolean;
direction: MenuDirection;
position: 'auto' | 'anchor' | 'initial';
}
export const placeLeftorRight = (
props: ReturnType<typeof getPositionHelpers> & placeLeftorRightParams,
): { arrowY: number | undefined; x: number; y: number; computedDirection: MenuDirection } => {
const {
anchorRect,
containerRect,
menuRect,
placeLeftorRightY,
placeLeftX,
placeRightX,
getLeftOverflow,
getRightOverflow,
confineHorizontally,
confineVertically,
arrowRef,
arrow,
direction,
position,
} = props;
let computedDirection = direction;
let y = placeLeftorRightY;
if (position !== 'initial') {
y = confineVertically(y);
if (position === 'anchor') {
// restrict menu to the edge of anchor element
y = Math.min(y, anchorRect.bottom - containerRect.top);
y = Math.max(y, anchorRect.top - containerRect.top - menuRect.height);
}
}
let x, leftOverflow, rightOverflow;
if (computedDirection === 'left') {
x = placeLeftX;
if (position !== 'initial') {
// if menu overflows to the left,
// try to reposition it to the right of the anchor.
leftOverflow = getLeftOverflow(x);
if (leftOverflow < 0) {
// if menu overflows to the right after repositioning,
// choose a side which has less overflow
rightOverflow = getRightOverflow(placeRightX);
if (rightOverflow <= 0 || -leftOverflow > rightOverflow) {
x = placeRightX;
computedDirection = 'right';
}
}
}
} else {
// Opposite logic to the 'left' direction above
x = placeRightX;
if (position !== 'initial') {
rightOverflow = getRightOverflow(x);
if (rightOverflow > 0) {
leftOverflow = getLeftOverflow(placeLeftX);
if (leftOverflow >= 0 || -leftOverflow < rightOverflow) {
x = placeLeftX;
computedDirection = 'left';
}
}
}
}
if (position === 'auto') x = confineHorizontally(x);
const arrowY = arrow
? placeArrowVertical({
menuY: y,
arrowRef,
anchorRect,
containerRect,
menuRect,
})
: undefined;
return { arrowY, x, y, computedDirection };
};