UNPKG

@ionic/core

Version:

Base components for Ionic

93 lines (92 loc) • 3.73 kB
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]); };