UNPKG

@react-md/utils

Version:
204 lines 8.59 kB
import { getAboveCoord, getBelowCoord, getBottomCoord, getCenterYCoord, getTopCoord, } from "./getCoord"; /** * Attempts to position the fixed element so that it will appear completely * above the container element but also within the viewport boundaries. When * swapping is enabled, it will attempt to swap to the below position if it * can't fit within the viewport above the container element. If it can't fit in * the viewport even after being swapped below or swapping is disabled, it will * be positioned to the top viewport boundary. * * @internal */ export function createAnchoredAbove(config) { var yMargin = config.yMargin, vhMargin = config.vhMargin, screenBottom = config.screenBottom, elHeight = config.elHeight, containerRect = config.containerRect, preventOverlap = config.preventOverlap, disableSwapping = config.disableSwapping, disableVHBounds = config.disableVHBounds; var top = getAboveCoord(config); var actualY = "above"; if (disableVHBounds) { // can't actually allow a top value as a negative number since browsers // won't scroll upwards past the normal page top return { actualY: actualY, top: Math.max(0, top) }; } if (top > vhMargin) { // don't need to do anything else since the top is still in the viewport and // since it's positioned above, we already know it can't overlap the // container element return { actualY: actualY, top: top }; } var swappedTop = getBelowCoord(config); if (disableSwapping || swappedTop + elHeight > screenBottom) { top = Math.min(top, vhMargin); } else { actualY = "below"; top = swappedTop; } var bottom; if (preventOverlap && // can't overlap if it's positioned below actualY === "above" && top + elHeight > containerRect.top) { bottom = screenBottom - containerRect.top + yMargin; } return { actualY: actualY, top: top, bottom: bottom }; } /** * Attempts to position the fixed element so that it will appear fixed to the * top of the container element but also within the viewport boundaries. When * swapping is enabled, it will attempt to swap to the bottom position if it * can't fit within the viewport. If it can't fit in the viewport even after * being swapped to the bottom position or swapping is disabled, it will be * positioned to the top viewport boundary. * * @internal */ export function createAnchoredTop(config) { var vhMargin = config.vhMargin, screenBottom = config.screenBottom, elHeight = config.elHeight, disableSwapping = config.disableSwapping, disableVHBounds = config.disableVHBounds; var top = getTopCoord(config); var actualY = "top"; if (disableVHBounds || top + elHeight <= screenBottom) { return { actualY: actualY, top: top }; } var swappedTop = getBottomCoord(config); if (disableSwapping || swappedTop < vhMargin) { top = Math.max(top, vhMargin); } else { actualY = "bottom"; top = swappedTop; } return { actualY: actualY, top: top }; } /** * Attempts to position the fixed element so that it will appear at the center * of the container element but also within the viewport boundaries. If the * entered element can't fit within the viewport, it'll update the top value * to either be the vhMargin or position to the screen bottom boundary * * @internal */ export function createAnchoredCenter(config) { var vhMargin = config.vhMargin, screenBottom = config.screenBottom, elHeight = config.elHeight, disableVHBounds = config.disableVHBounds; var top = getCenterYCoord(config); var actualY = "center"; if (disableVHBounds) { return { actualY: actualY, top: Math.max(0, top) }; } top = Math.max(vhMargin, top); if (top + elHeight > screenBottom) { top = screenBottom - elHeight; } return { actualY: actualY, top: top }; } /** * Attempts to position the fixed element so that it will appear fixed to the * bottom of the container element but also within the viewport boundaries. When * swapping is enabled, it will attempt to swap to the top position if it can't * fit within the viewport. If it can't fit in the viewport even after being * swapped to the top position or swapping is disabled, it will be positioned to * the bottom viewport boundary. * * @internal */ export function createAnchoredBottom(config) { var vhMargin = config.vhMargin, screenBottom = config.screenBottom, elHeight = config.elHeight, disableSwapping = config.disableSwapping, disableVHBounds = config.disableVHBounds; var top = getBottomCoord(config); var actualY = "bottom"; if (disableVHBounds || top > vhMargin) { return { actualY: actualY, top: top }; } var swappedTop = getTopCoord(config); if (disableSwapping || swappedTop + elHeight > screenBottom) { top = Math.min(top, screenBottom - elHeight); } else { actualY = "top"; top = swappedTop; } return { actualY: actualY, top: top }; } /** * Attempts to position the fixed element so that it will appear completely * below the container element but also within the viewport boundaries. When * swapping is enabled, it will attempt to swap to the above position if it * can't fit within the viewport below the container element. If it can't fit in * the viewport even after being swapped above or swapping is disabled, it will * be positioned to the bottom viewport boundary. * * @internal */ export function createAnchoredBelow(config) { var yMargin = config.yMargin, vhMargin = config.vhMargin, elHeight = config.elHeight, screenBottom = config.screenBottom, containerRect = config.containerRect, preventOverlap = config.preventOverlap, disableSwapping = config.disableSwapping, disableVHBounds = config.disableVHBounds; var top = getBelowCoord(config); var actualY = "below"; if (disableVHBounds || top + elHeight <= screenBottom) { return { actualY: actualY, top: top }; } if (preventOverlap) { var availableTop = containerRect.top - yMargin; if (disableSwapping || availableTop < screenBottom - top) { return { actualY: actualY, top: top, bottom: vhMargin, }; } return { actualY: "above", top: Math.max(vhMargin, availableTop - elHeight), // this makes it so that the bottom of the fixed element is the top of the container // element. this ensures that it won't ever overlap the container element bottom: window.innerHeight - availableTop, }; } var swappedTop = getAboveCoord(config); if (disableSwapping || swappedTop < vhMargin) { top = Math.min(top, screenBottom - elHeight); } else { actualY = "above"; top = swappedTop; } return { actualY: actualY, top: top }; } /** * Creates the vertical position for a fixed element with the provided options. * * @internal */ export function createVerticalPosition(options) { var y = options.y, vh = options.vh, vhMargin = options.vhMargin, yMargin = options.yMargin, elHeight = options.elHeight, initialY = options.initialY, containerRect = options.containerRect, disableSwapping = options.disableSwapping, preventOverlap = options.preventOverlap, disableVHBounds = options.disableVHBounds; if (!disableVHBounds && !preventOverlap && elHeight > vh - vhMargin * 2) { // the element is too big to be displayed in the viewport, so just span the // full viewport excluding margins return { top: vhMargin, bottom: vhMargin, actualY: "center", transformOriginY: containerRect.top, }; } var config = { vhMargin: vhMargin, yMargin: yMargin, elHeight: elHeight, initialY: initialY, containerRect: containerRect, screenBottom: vh - vhMargin, preventOverlap: preventOverlap, disableSwapping: disableSwapping, disableVHBounds: disableVHBounds, }; switch (y) { case "above": return createAnchoredAbove(config); case "top": return createAnchoredTop(config); case "center": return createAnchoredCenter(config); case "bottom": return createAnchoredBottom(config); case "below": return createAnchoredBelow(config); } } //# sourceMappingURL=createVerticalPosition.js.map