@uiw/react-overlay-trigger
Version:
OverlayTrigger component
150 lines (145 loc) • 5.81 kB
JavaScript
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;
}