@shopify/polaris
Version:
Shopify’s product component library
66 lines (65 loc) • 3.32 kB
JavaScript
export function calculateVerticalPosition(activatorRect, overlayRect, overlayMargins, scrollableContainerRect, containerRect, preferredPosition, fixed) {
const activatorTop = activatorRect.top;
const activatorBottom = activatorTop + activatorRect.height;
const spaceAbove = activatorRect.top;
const spaceBelow = containerRect.height - activatorRect.top - activatorRect.height;
const desiredHeight = overlayRect.height;
const verticalMargins = overlayMargins.activator + overlayMargins.container;
const minimumSpaceToScroll = overlayMargins.container;
const distanceToTopScroll = activatorRect.top - Math.max(scrollableContainerRect.top, 0);
const distanceToBottomScroll = containerRect.top +
Math.min(containerRect.height, scrollableContainerRect.top + scrollableContainerRect.height) -
(activatorRect.top + activatorRect.height);
const enoughSpaceFromTopScroll = distanceToTopScroll >= minimumSpaceToScroll;
const enoughSpaceFromBottomScroll = distanceToBottomScroll >= minimumSpaceToScroll;
const heightIfBelow = Math.min(spaceBelow, desiredHeight);
const heightIfAbove = Math.min(spaceAbove, desiredHeight);
const containerRectTop = fixed ? 0 : containerRect.top;
const positionIfAbove = {
height: heightIfAbove - verticalMargins,
top: activatorTop + containerRectTop - heightIfAbove,
positioning: 'above',
};
const positionIfBelow = {
height: heightIfBelow - verticalMargins,
top: activatorBottom + containerRectTop,
positioning: 'below',
};
if (preferredPosition === 'above') {
return (enoughSpaceFromTopScroll ||
(distanceToTopScroll >= distanceToBottomScroll &&
!enoughSpaceFromBottomScroll)) &&
(spaceAbove > desiredHeight || spaceAbove > spaceBelow)
? positionIfAbove
: positionIfBelow;
}
if (preferredPosition === 'below') {
return (enoughSpaceFromBottomScroll ||
(distanceToBottomScroll >= distanceToTopScroll &&
!enoughSpaceFromTopScroll)) &&
(spaceBelow > desiredHeight || spaceBelow > spaceAbove)
? positionIfBelow
: positionIfAbove;
}
if (enoughSpaceFromTopScroll && enoughSpaceFromBottomScroll) {
return spaceAbove > spaceBelow ? positionIfAbove : positionIfBelow;
}
return distanceToTopScroll > minimumSpaceToScroll
? positionIfAbove
: positionIfBelow;
}
export function calculateHorizontalPosition(activatorRect, overlayRect, containerRect, overlayMargins, preferredAlignment) {
const maximum = containerRect.width - overlayRect.width;
if (preferredAlignment === 'left') {
return Math.min(maximum, Math.max(0, activatorRect.left - overlayMargins.horizontal));
}
else if (preferredAlignment === 'right') {
const activatorRight = activatorRect.left + activatorRect.width;
return Math.min(maximum, Math.max(0, activatorRight - overlayRect.width + overlayMargins.horizontal));
}
return Math.min(maximum, Math.max(0, activatorRect.center.x - overlayRect.width / 2));
}
export function rectIsOutsideOfRect(inner, outer) {
const { center } = inner;
return center.y < outer.top || center.y > outer.top + outer.height;
}