UNPKG

@linzjs/step-ag-grid

Version:

[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) > Reusable [ag-grid](https://www.ag-grid.com/) component for LINZ / Toitū te whenua.

85 lines (75 loc) 2.97 kB
import { MutableRefObject } from 'react'; import { parsePadding } from '../utils'; export const getPositionHelpers = ( containerRef: MutableRefObject<HTMLElement | undefined>, menuRef: MutableRefObject<HTMLElement>, menuScroll: Window | Element, boundingBoxPadding: string | undefined, ) => { const menuRect = menuRef.current.getBoundingClientRect(); const thisWindow = containerRef.current?.ownerDocument.defaultView ?? window; const containerRect = (containerRef.current ?? thisWindow.document.body).getBoundingClientRect(); const boundingRect = menuScroll === window || menuScroll === thisWindow ? { left: 0, top: 0, right: thisWindow.document.documentElement.clientWidth, bottom: thisWindow.innerHeight, } : (menuScroll as Element).getBoundingClientRect(); const padding = parsePadding(boundingBoxPadding); // For left and top, overflows are negative value. // For right and bottom, overflows are positive value. const getLeftOverflow = (x: number) => x + containerRect.left - boundingRect.left - padding.left; const getRightOverflow = (x: number) => x + containerRect.left + menuRect.width - boundingRect.right + padding.right; const getTopOverflow = (y: number) => y + containerRect.top - boundingRect.top - padding.top; const getBottomOverflow = (y: number) => y + containerRect.top + menuRect.height - boundingRect.bottom + padding.bottom; const confineHorizontally = (x: number) => { // If menu overflows to the left side, adjust x to have the menu contained within the viewport // and there is no need to check the right side; // if it doesn't overflow to the left, then check the right side let leftOverflow = getLeftOverflow(x); if (leftOverflow < 0) { x -= leftOverflow; } else { const rightOverflow = getRightOverflow(x); if (rightOverflow > 0) { x -= rightOverflow; // Check again to make sure menu doesn't overflow to the left // because it may go off-screen and cannot be scrolled into view. leftOverflow = getLeftOverflow(x); if (leftOverflow < 0) x -= leftOverflow; } } return x; }; const confineVertically = (y: number) => { // Similar logic to confineHorizontally above let topOverflow = getTopOverflow(y); if (topOverflow < 0) { y -= topOverflow; } else { const bottomOverflow = getBottomOverflow(y); if (bottomOverflow > 0) { y -= bottomOverflow; // Check again to make sure menu doesn't overflow to the bottom // because it may go off screen and cannot be scroll into view. topOverflow = getTopOverflow(y); if (topOverflow < 0) y -= topOverflow; } } return y; }; return { menuRect, containerRect, getLeftOverflow, getRightOverflow, getTopOverflow, getBottomOverflow, confineHorizontally, confineVertically, }; };