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.

95 lines (87 loc) 2.76 kB
import { MutableRefObject } from 'react'; import { MenuDirection } from '../types'; import { getPositionHelpers } from './getPositionHelpers'; import { placeArrowHorizontal } from './placeArrowHorizontal'; export interface placeToporBottomParams { anchorRect: DOMRect; placeToporBottomX: number; placeTopY: number; placeBottomY: number; arrowRef: MutableRefObject<HTMLElement | null>; arrow?: boolean; direction: 'left' | 'right' | 'top' | 'bottom'; position: 'auto' | 'anchor' | 'initial'; } export const placeToporBottom = ( props: ReturnType<typeof getPositionHelpers> & placeToporBottomParams, ): { arrowX?: number | undefined; x: number; y: number; computedDirection: MenuDirection } => { const { anchorRect, containerRect, menuRect, placeToporBottomX, placeTopY, placeBottomY, getTopOverflow, getBottomOverflow, confineHorizontally, confineVertically, arrowRef, arrow, direction, position, } = props; // make sure invalid direction is treated as 'bottom' let computedDirection: MenuDirection = direction === 'top' ? 'top' : 'bottom'; let x = placeToporBottomX; if (position !== 'initial') { x = confineHorizontally(x); if (position === 'anchor') { // restrict menu to the edge of anchor element x = Math.min(x, anchorRect.right - containerRect.left); x = Math.max(x, anchorRect.left - containerRect.left - menuRect.width); } } let y, topOverflow, bottomOverflow; if (computedDirection === 'top') { y = placeTopY; if (position !== 'initial') { // if menu overflows to the top, // try to reposition it to the bottom of the anchor. topOverflow = getTopOverflow(y); if (topOverflow < 0) { // if menu overflows to the bottom after repositioning, // choose a side which has less overflow bottomOverflow = getBottomOverflow(placeBottomY); if (bottomOverflow <= 0 || -topOverflow > bottomOverflow) { y = placeBottomY; computedDirection = 'bottom'; } } } } else { // Opposite logic to the 'top' direction above y = placeBottomY; if (position !== 'initial') { bottomOverflow = getBottomOverflow(y); if (bottomOverflow > 0) { topOverflow = getTopOverflow(placeTopY); if (topOverflow >= 0 || -topOverflow < bottomOverflow) { y = placeTopY; computedDirection = 'top'; } } } } if (position === 'auto') y = confineVertically(y); const arrowX = arrow ? placeArrowHorizontal({ menuX: x, arrowRef, anchorRect, containerRect, menuRect, }) : undefined; return { arrowX, x, y, computedDirection }; };