UNPKG

@uiw/react-overlay-trigger

Version:

OverlayTrigger component

150 lines (145 loc) 5.81 kB
import _extends from "@babel/runtime/helpers/extends"; import { getScroll } from '@uiw/utils'; import getBoundingClientRect from './util/getBoundingClientRect'; import getOuterSizes from './util/getOuterSizes'; export function getStyle(options) { var { trigger: triggerDom, popup: popupDom, placement, usePortal, autoAdjustOverflow } = options || {}; var sty = { left: 0, top: 0, placement }; if (!triggerDom || !popupDom || !document) { return sty; } var winSizeHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); var winSizeWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); sty.placement = placement; var scrollTop = getScroll(triggerDom.ownerDocument.documentElement, true); var scrollLeft = getScroll(triggerDom.ownerDocument.documentElement); var trigger = _extends({}, getBoundingClientRect(triggerDom), getOuterSizes(triggerDom)); var popup = _extends({}, getBoundingClientRect(popupDom), getOuterSizes(popupDom)); var bottom = winSizeHeight - trigger.bottom; var right = winSizeWidth - trigger.left - trigger.width; sty.top = trigger.top + scrollTop; sty.left = trigger.left; if (!usePortal) { sty.top = trigger.offsetTop; sty.left = trigger.offsetLeft; } if (placement && /^(top)/.test(placement)) { sty.top -= popup.height; } if (placement && /^(right)/.test(placement)) { sty.left += trigger.width; } if (placement && /^(bottom)/.test(placement)) { sty.top += trigger.height; } if (placement && /^(left)/.test(placement)) { sty.left -= popup.width; } switch (sty.placement) { case 'bottomLeft': case 'topLeft': break; case 'bottom': // eslint-disable-next-line case 'top': sty.left = sty.left - (popup.width - trigger.width) / 2; break; case 'bottomRight': case 'topRight': sty.left = sty.left + scrollLeft + trigger.width - popup.width; break; case 'rightTop': case 'leftTop': break; case 'right': // eslint-disable-next-line case 'left': sty.top = sty.top - (popup.height - trigger.height) / 2; break; case 'rightBottom': case 'leftBottom': sty.top = sty.top - popup.height + trigger.height; break; default: break; } if (autoAdjustOverflow) { if (placement && /^(top)/.test(placement) && trigger.top < popup.height && bottom > popup.height) { sty.placement = placement.replace(/^top/, 'bottom'); sty.top = sty.top + popup.height + trigger.height; } if (placement && /^(bottom)/.test(placement) && bottom < popup.height && trigger.top > popup.height) { sty.placement = placement.replace(/^bottom/, 'top'); sty.top = sty.top - popup.height - trigger.height; } if (placement && /^(right)/.test(placement) && right < popup.width) { sty.placement = placement.replace(/^right/, 'left'); sty.left = sty.left - trigger.width - popup.width; } if (placement && /^(left)/.test(placement) && trigger.left < popup.width) { sty.placement = placement.replace(/^left/, 'right'); sty.left = sty.left + trigger.width + popup.width; } if (placement && /^(left|right)/.test(placement) && usePortal) { // Top if (/(Top)$/.test(placement) && trigger.top < 0 || /(right|left)$/.test(placement) && trigger.top + trigger.height / 2 < popup.height / 2 || /(Bottom)$/.test(placement) && trigger.top + trigger.height < popup.height) { sty.top = scrollTop; } } else { // Top if (placement && /(Top)$/.test(placement) && trigger.top < 0) { sty.top -= trigger.top; } if (placement && /(Bottom)$/.test(placement) && trigger.bottom < popup.height) { // eslint-disable-next-line sty.top = sty.top + (popup.height - trigger.bottom); } if (placement && /(right|left)$/.test(placement) && trigger.bottom - trigger.height / 2 < popup.height / 2) { sty.top = sty.top + popup.height / 2 - (trigger.bottom - trigger.height / 2); } } // Bottom Public Part if (placement && /^(left|right)/.test(placement)) { if (/(Top)$/.test(placement) && bottom + trigger.height < popup.height) { sty.top = sty.top - (popup.height - bottom - trigger.height); // eslint-disable-line } if (/(right|left)$/.test(placement) && bottom + trigger.height / 2 < popup.height / 2) { sty.top = sty.top - (popup.height / 2 - bottom - trigger.height / 2); // eslint-disable-line } if (/(Bottom)$/.test(placement) && bottom < 0) { sty.top = sty.top + bottom; // eslint-disable-line } } if (placement && /^(top|bottom)/.test(placement) && usePortal) { // left if (/(Left)$/.test(placement) && trigger.left < 0 || /(top|bottom)$/.test(placement) && trigger.left + trigger.width / 2 < popup.width / 2 || /(Right)$/.test(placement) && trigger.left + trigger.width < popup.width) { sty.left = scrollLeft; } // right if (/(top|bottom)$/.test(placement) && right + trigger.width / 2 < popup.width / 2) { sty.left = trigger.left + trigger.width + right - popup.width; } } else if (placement && /(top|bottom)$/.test(placement) && right + trigger.width / 2 < popup.width / 2) { sty.left = sty.left + (right + trigger.width / 2 - popup.width / 2); // eslint-disable-line } if (placement && /^(top|bottom)/.test(placement)) { if (/(Left)$/.test(placement) && trigger.width + right < popup.width) { sty.left = sty.left - (popup.width - trigger.width - right); } if (/(Right)$/.test(placement) && right < 0) { sty.left = sty.left + right; // eslint-disable-line } } } return sty; }