UNPKG

@nex-ui/react

Version:

🎉 A beautiful, modern, and reliable React component library.

52 lines (49 loc) • 2.27 kB
import { ownerWindow } from '@nex-ui/utils'; import { isHTMLElement, toClientRect, getRectRelativeToViewport } from './dom.mjs'; import { getOffsetParent } from './getOffsetParent.mjs'; import { getOverflowAncestors } from './getOverflowAncestors.mjs'; const detectOverflow = (state)=>{ const { elements, rects } = state; const win = ownerWindow(elements.popper); const clippingAncestors = getOverflowAncestors(elements.popper).filter(isHTMLElement); const clippingAncestorRects = clippingAncestors.map((el)=>toClientRect(el.getBoundingClientRect())); const { visualViewport } = win; if (visualViewport) { clippingAncestorRects.push(toClientRect({ x: visualViewport.offsetLeft, y: visualViewport.offsetTop, width: visualViewport.width, height: visualViewport.height })); } // Compute the actually visible clipping region of the element under the combined effect // of all clipping ancestors by taking intersections sequentially. const clippingRect = clippingAncestorRects.reduce((accRect, rect)=>{ accRect.top = Math.max(rect.top, accRect.top); accRect.right = Math.min(rect.right, accRect.right); accRect.bottom = Math.min(rect.bottom, accRect.bottom); accRect.left = Math.max(rect.left, accRect.left); return accRect; }, { top: -Infinity, right: Infinity, bottom: Infinity, left: -Infinity }); const clippingClientRect = toClientRect({ x: clippingRect.left, y: clippingRect.top, width: clippingRect.right - clippingRect.left, height: clippingRect.bottom - clippingRect.top }); const elementClientRect = toClientRect(getRectRelativeToViewport(rects.popper, getOffsetParent(elements.popper))); // The overflow situation of the element in the four directions (top, bottom, left, right) // relative to the clipping boundary. return { top: clippingClientRect.top - elementClientRect.top, bottom: elementClientRect.bottom - clippingClientRect.bottom, left: clippingClientRect.left - elementClientRect.left, right: elementClientRect.right - clippingClientRect.right }; }; export { detectOverflow };