@ionic/core
Version:
Base components for Ionic
92 lines (91 loc) • 3.43 kB
JavaScript
/*!
* (C) Ionic http://ionicframework.com - MIT License
*/
import { win } from "../../../utils/browser/index";
import { printIonWarning } from "../../../utils/logging/index";
/**
* Calculate the CSS top and bottom position of the toast, to be used
* as starting points for the animation keyframes.
*
* The default animations for both MD and iOS
* use translateY, which calculates from the
* top edge of the screen. This behavior impacts
* how we compute the offset when a toast has
* position='bottom' since we need to calculate from
* the bottom edge of the screen instead.
*
* @param position The value of the toast's position prop.
* @param positionAnchor The element the toast should be anchored to,
* if applicable.
* @param mode The toast component's mode (md, ios, etc).
* @param toast A reference to the toast element itself.
*/
export function getAnimationPosition(position, positionAnchor, mode, toast) {
/**
* Start with a predefined offset from the edge the toast will be
* positioned relative to, whether on the screen or anchor element.
*/
let offset;
if (mode === 'md') {
offset = position === 'top' ? 8 : -8;
}
else {
offset = position === 'top' ? 10 : -10;
}
/**
* If positionAnchor is defined, add in the distance from the target
* screen edge to the target anchor edge. For position="top", the
* bottom anchor edge is targeted. For position="bottom", the top
* anchor edge is targeted.
*/
if (positionAnchor && win) {
warnIfAnchorIsHidden(positionAnchor, toast);
const box = positionAnchor.getBoundingClientRect();
if (position === 'top') {
offset += box.bottom;
}
else if (position === 'bottom') {
/**
* Just box.top is the distance from the top edge of the screen
* to the top edge of the anchor. We want to calculate from the
* bottom edge of the screen instead.
*/
offset -= win.innerHeight - box.top;
}
/**
* We don't include safe area here because that should already be
* accounted for when checking the position of the anchor.
*/
return {
top: `${offset}px`,
bottom: `${offset}px`,
};
}
else {
return {
top: `calc(${offset}px + var(--ion-safe-area-top, 0px))`,
bottom: `calc(${offset}px - var(--ion-safe-area-bottom, 0px))`,
};
}
}
/**
* If the anchor element is hidden, getBoundingClientRect()
* will return all 0s for it, which can cause unexpected
* results in the position calculation when animating.
*/
function warnIfAnchorIsHidden(positionAnchor, toast) {
if (positionAnchor.offsetParent === null) {
printIonWarning('The positionAnchor element for ion-toast was found in the DOM, but appears to be hidden. This may lead to unexpected positioning of the toast.', toast);
}
}
/**
* Returns the top offset required to place
* the toast in the middle of the screen.
* Only needed when position="toast".
* @param toastHeight - The height of the ion-toast element
* @param wrapperHeight - The height of the .toast-wrapper element
* inside the toast's shadow root.
*/
export const getOffsetForMiddlePosition = (toastHeight, wrapperHeight) => {
return Math.floor(toastHeight / 2 - wrapperHeight / 2);
};