@ionic/core
Version:
Base components for Ionic
93 lines (92 loc) • 3.73 kB
JavaScript
import { createAnimation } from '../../../utils/animation/animation';
/**
* Md Popover Enter Animation
*/
export const mdEnterAnimation = (baseEl, ev) => {
const POPOVER_MD_BODY_PADDING = 12;
const doc = baseEl.ownerDocument;
const isRTL = doc.dir === 'rtl';
let originY = 'top';
let originX = isRTL ? 'right' : 'left';
const contentEl = baseEl.querySelector('.popover-content');
const contentDimentions = contentEl.getBoundingClientRect();
const contentWidth = contentDimentions.width;
const contentHeight = contentDimentions.height;
const bodyWidth = doc.defaultView.innerWidth;
const bodyHeight = doc.defaultView.innerHeight;
// If ev was passed, use that for target element
const targetDim = ev && ev.target && ev.target.getBoundingClientRect();
// As per MD spec, by default position the popover below the target (trigger) element
const targetTop = targetDim != null && 'bottom' in targetDim
? targetDim.bottom
: bodyHeight / 2 - contentHeight / 2;
const targetLeft = targetDim != null && 'left' in targetDim
? isRTL
? targetDim.left - contentWidth + targetDim.width
: targetDim.left
: bodyWidth / 2 - contentWidth / 2;
const targetHeight = (targetDim && targetDim.height) || 0;
const popoverCSS = {
top: targetTop,
left: targetLeft
};
// If the popover left is less than the padding it is off screen
// to the left so adjust it, else if the width of the popover
// exceeds the body width it is off screen to the right so adjust
if (popoverCSS.left < POPOVER_MD_BODY_PADDING) {
popoverCSS.left = POPOVER_MD_BODY_PADDING;
// Same origin in this case for both LTR & RTL
// Note: in LTR, originX is already 'left'
originX = 'left';
}
else if (contentWidth + POPOVER_MD_BODY_PADDING + popoverCSS.left >
bodyWidth) {
popoverCSS.left = bodyWidth - contentWidth - POPOVER_MD_BODY_PADDING;
// Same origin in this case for both LTR & RTL
// Note: in RTL, originX is already 'right'
originX = 'right';
}
// If the popover when popped down stretches past bottom of screen,
// make it pop up if there's room above
if (targetTop + targetHeight + contentHeight > bodyHeight &&
targetTop - contentHeight > 0) {
popoverCSS.top = targetTop - contentHeight - targetHeight;
baseEl.className = baseEl.className + ' popover-bottom';
originY = 'bottom';
// If there isn't room for it to pop up above the target cut it off
}
else if (targetTop + targetHeight + contentHeight > bodyHeight) {
contentEl.style.bottom = POPOVER_MD_BODY_PADDING + 'px';
}
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();
const contentAnimation = createAnimation();
const viewportAnimation = createAnimation();
backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop'))
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);
wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper'))
.fromTo('opacity', 0.01, 1);
contentAnimation
.addElement(contentEl)
.beforeStyles({
'top': `${popoverCSS.top}px`,
'left': `${popoverCSS.left}px`,
'transform-origin': `${originY} ${originX}`
})
.fromTo('transform', 'scale(0.001)', 'scale(1)');
viewportAnimation
.addElement(baseEl.querySelector('.popover-viewport'))
.fromTo('opacity', 0.01, 1);
return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(300)
.addAnimation([backdropAnimation, wrapperAnimation, contentAnimation, viewportAnimation]);
};