UNPKG

@zohodesk/hooks

Version:

Unified Component Library - Hooks

210 lines (206 loc) 9.11 kB
import getViewPortEle from "./getViewPortEle"; import frameRelativeRects from "./frameRelativeRects"; export default function possibilities(el, relativeBox, customFrame) { let { needArrow, isAbsolute } = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; if (!el) { return; } const elViewPortEle = getViewPortEle(el); const elRects = frameRelativeRects(el, customFrame, elViewPortEle); const { rect } = elRects; const relativeBoxViewPortEle = getViewPortEle(relativeBox); const relativeBoxRects = frameRelativeRects(relativeBox, customFrame, relativeBoxViewPortEle); const { rectGap: relativeBoxGap, rect: relativeBoxRect } = relativeBoxRects; const relativeBoxDocumentRects = frameRelativeRects(relativeBox, customFrame); const { rectGap: documentGap } = relativeBoxDocumentRects; // rect => PopOverContainer, relativeBoxGap => PopOverTarget // Horizontal ~ ----- X axis // Vertical ~ ||||||| Y axis const paddingSpace = 5; // space between target and relative element const arrowSize = needArrow ? 10 : 0; rect.height += needArrow ? arrowSize : paddingSpace; rect.width += needArrow ? arrowSize : paddingSpace; const arrowHorizontalBalancePx = !isAbsolute && needArrow ? 30 : 0; const arrowVerticalBalancePx = !isAbsolute && needArrow ? 27 : 0; const bottomOverFlow = rect.height > relativeBoxGap.bottom; const topOverFlow = rect.height > relativeBoxGap.top; const rightOverFlow = rect.width > relativeBoxGap.right; const leftOverFlow = rect.width > relativeBoxGap.left; const horizontalCenterOverFlow = rect.width / 2 > relativeBoxGap.center.right || rect.width / 2 > relativeBoxGap.center.left; const verticalCenterOverFlow = rect.height / 2 > relativeBoxGap.center.top || rect.height / 2 > relativeBoxGap.center.bottom; const horizontalLeftToRightOverFlow = rect.width > relativeBoxRect.width + relativeBoxGap.right; const horizontalCenterToRightOverFlow = rect.width > relativeBoxGap.center.right || arrowHorizontalBalancePx > relativeBoxGap.center.left; const horizontalRightToLeft = rect.width > relativeBoxRect.width + relativeBoxGap.left; const horizontalCenterToLeft = rect.width > relativeBoxGap.center.left || arrowHorizontalBalancePx > relativeBoxGap.center.right; const verticalTopToBottomOverFlow = rect.height > relativeBoxRect.height + relativeBoxGap.bottom; const verticalCenterToBottomOverFlow = rect.height > relativeBoxGap.center.bottom || arrowVerticalBalancePx > relativeBoxGap.center.top; const verticalBottomToTopOverFlow = rect.height > relativeBoxRect.height + relativeBoxGap.top; const verticalCenterToTopOverFlow = rect.height > relativeBoxGap.center.top || arrowVerticalBalancePx > relativeBoxGap.center.bottom; const views = { bottomCenter: !(bottomOverFlow || horizontalCenterOverFlow), bottomLeftToRight: !(bottomOverFlow || horizontalLeftToRightOverFlow), bottomCenterToRight: !(bottomOverFlow || horizontalCenterToRightOverFlow), bottomRight: !(bottomOverFlow || rightOverFlow || arrowHorizontalBalancePx > relativeBoxRect.right), bottomRightToLeft: !(bottomOverFlow || horizontalRightToLeft), bottomCenterToLeft: !(bottomOverFlow || horizontalCenterToLeft), bottomLeft: !(bottomOverFlow || leftOverFlow || arrowHorizontalBalancePx > relativeBoxGap.right + relativeBoxRect.width), topCenter: !(topOverFlow || horizontalCenterOverFlow), topLeftToRight: !(topOverFlow || horizontalLeftToRightOverFlow), topCenterToRight: !(topOverFlow || horizontalCenterToRightOverFlow), topRight: !(topOverFlow || rightOverFlow || arrowHorizontalBalancePx > relativeBoxRect.right), topRightToLeft: !(topOverFlow || horizontalRightToLeft), topCenterToLeft: !(topOverFlow || horizontalCenterToLeft), topLeft: !(topOverFlow || leftOverFlow || arrowHorizontalBalancePx > relativeBoxGap.right + relativeBoxRect.width), rightCenter: !(rightOverFlow || verticalCenterOverFlow), rightTopToBottom: !(rightOverFlow || verticalTopToBottomOverFlow), rightCenterToBottom: !(rightOverFlow || verticalCenterToBottomOverFlow), rightBottom: !(rightOverFlow || bottomOverFlow || arrowVerticalBalancePx > relativeBoxRect.bottom), rightBottomToTop: !(rightOverFlow || verticalBottomToTopOverFlow), rightCenterToTop: !(rightOverFlow || verticalCenterToTopOverFlow), rightTop: !(rightOverFlow || topOverFlow || arrowVerticalBalancePx > relativeBoxGap.bottom + relativeBoxRect.height), leftCenter: !(leftOverFlow || verticalCenterOverFlow), leftTopToBottom: !(leftOverFlow || verticalTopToBottomOverFlow), leftCenterToBottom: !(leftOverFlow || verticalCenterToBottomOverFlow), leftBottom: !(leftOverFlow || bottomOverFlow || arrowVerticalBalancePx > relativeBoxRect.bottom), leftBottomToTop: !(leftOverFlow || verticalBottomToTopOverFlow), leftCenterToTop: !(leftOverFlow || verticalCenterToTopOverFlow), leftTop: !(leftOverFlow || topOverFlow || arrowVerticalBalancePx > relativeBoxGap.bottom + relativeBoxRect.height) }; const horizontalCenter = relativeBoxGap.left + relativeBoxRect.width / 2; const horizontalLeft = relativeBoxGap.left; const horizontalRight = relativeBoxGap.left + relativeBoxRect.width; const verticalBottom = relativeBoxGap.top + relativeBoxRect.height; const verticalTop = relativeBoxGap.top; const verticalCenter = relativeBoxGap.top + relativeBoxRect.height / 2; const horizontalTop = documentGap.bottom + relativeBoxRect.height; const verticalCenterToTop = documentGap.bottom + relativeBoxRect.height / 2; const viewsOffset = { bottomCenter: { left: horizontalCenter - rect.width / 2, top: verticalBottom + arrowSize }, bottomLeftToRight: { left: horizontalLeft, top: verticalBottom + arrowSize }, bottomCenterToRight: { left: horizontalCenter - arrowHorizontalBalancePx, top: verticalBottom + arrowSize }, bottomRight: { left: horizontalRight - arrowHorizontalBalancePx, top: verticalBottom + arrowSize }, bottomRightToLeft: { left: horizontalRight - rect.width, top: verticalBottom + arrowSize }, bottomCenterToLeft: { left: horizontalCenter - rect.width + arrowHorizontalBalancePx, top: verticalBottom + arrowSize }, bottomLeft: { left: horizontalLeft - rect.width + arrowHorizontalBalancePx, top: verticalBottom + arrowSize }, topCenter: { left: horizontalCenter - rect.width / 2, bottom: horizontalTop + arrowSize }, topLeftToRight: { left: horizontalLeft, bottom: horizontalTop + arrowSize }, topCenterToRight: { left: horizontalCenter - arrowHorizontalBalancePx, bottom: horizontalTop + arrowSize }, topRight: { left: horizontalRight - arrowHorizontalBalancePx, bottom: horizontalTop + arrowSize }, topRightToLeft: { left: horizontalRight - rect.width, bottom: horizontalTop + arrowSize }, topCenterToLeft: { left: horizontalCenter - rect.width + arrowHorizontalBalancePx, bottom: horizontalTop + arrowSize }, topLeft: { left: horizontalLeft - rect.width + arrowHorizontalBalancePx, top: verticalTop - (rect.height + arrowSize) }, rightCenter: { left: horizontalRight + arrowSize, top: verticalCenter - rect.height / 2 }, rightTopToBottom: { left: horizontalRight + arrowSize, top: verticalTop }, rightCenterToBottom: { left: horizontalRight + arrowSize, top: verticalCenter - arrowVerticalBalancePx }, rightBottom: { left: horizontalRight + arrowSize, top: verticalBottom - arrowVerticalBalancePx }, rightBottomToTop: { left: horizontalRight + arrowSize, bottom: documentGap.bottom }, rightCenterToTop: { left: horizontalRight + arrowSize, bottom: verticalCenterToTop - arrowVerticalBalancePx }, rightTop: { left: horizontalRight + arrowSize, bottom: horizontalTop - arrowVerticalBalancePx }, leftCenter: { left: horizontalLeft - (rect.width + arrowSize), top: verticalCenter - rect.height / 2 }, leftTopToBottom: { left: horizontalLeft - (rect.width + arrowSize), top: verticalTop }, leftCenterToBottom: { left: horizontalLeft - (rect.width + arrowSize), top: verticalCenter - arrowVerticalBalancePx }, leftBottom: { left: horizontalLeft - (rect.width + arrowSize), top: verticalBottom - arrowVerticalBalancePx }, leftBottomToTop: { left: horizontalLeft - (rect.width + arrowSize), bottom: documentGap.bottom }, leftCenterToTop: { left: horizontalLeft - (rect.width + arrowSize), bottom: verticalCenterToTop - arrowVerticalBalancePx }, leftTop: { left: horizontalLeft - (rect.width + arrowSize), bottom: horizontalTop - arrowVerticalBalancePx } }; return { views, viewsOffset, targetOffset: relativeBoxRect, popupOffset: rect }; }