UNPKG

@ionic/core

Version:
103 lines (99 loc) 5.79 kB
/*! * (C) Ionic http://ionicframework.com - MIT License */ import { proxyCustomElement, HTMLElement, readTask, writeTask, h, Host } from '@stencil/core/internal/client'; import { b as getIonMode } from './ionic-global.js'; const rippleEffectCss = ":host{left:0;right:0;top:0;bottom:0;position:absolute;contain:strict;pointer-events:none}:host(.unbounded){contain:layout size style}.ripple-effect{border-radius:50%;position:absolute;background-color:currentColor;color:inherit;contain:strict;opacity:0;-webkit-animation:225ms rippleAnimation forwards, 75ms fadeInAnimation forwards;animation:225ms rippleAnimation forwards, 75ms fadeInAnimation forwards;will-change:transform, opacity;pointer-events:none}.fade-out{-webkit-transform:translate(var(--translate-end)) scale(var(--final-scale, 1));transform:translate(var(--translate-end)) scale(var(--final-scale, 1));-webkit-animation:150ms fadeOutAnimation forwards;animation:150ms fadeOutAnimation forwards}@-webkit-keyframes rippleAnimation{from{-webkit-animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);-webkit-transform:scale(1);transform:scale(1)}to{-webkit-transform:translate(var(--translate-end)) scale(var(--final-scale, 1));transform:translate(var(--translate-end)) scale(var(--final-scale, 1))}}@keyframes rippleAnimation{from{-webkit-animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);-webkit-transform:scale(1);transform:scale(1)}to{-webkit-transform:translate(var(--translate-end)) scale(var(--final-scale, 1));transform:translate(var(--translate-end)) scale(var(--final-scale, 1))}}@-webkit-keyframes fadeInAnimation{from{-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:0}to{opacity:0.16}}@keyframes fadeInAnimation{from{-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:0}to{opacity:0.16}}@-webkit-keyframes fadeOutAnimation{from{-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:0.16}to{opacity:0}}@keyframes fadeOutAnimation{from{-webkit-animation-timing-function:linear;animation-timing-function:linear;opacity:0.16}to{opacity:0}}"; const IonRippleEffectStyle0 = rippleEffectCss; const RippleEffect = /*@__PURE__*/ proxyCustomElement(class RippleEffect extends HTMLElement { constructor() { super(); this.__registerHost(); this.__attachShadow(); this.type = 'bounded'; } /** * Adds the ripple effect to the parent element. * * @param x The horizontal coordinate of where the ripple should start. * @param y The vertical coordinate of where the ripple should start. */ async addRipple(x, y) { return new Promise((resolve) => { readTask(() => { const rect = this.el.getBoundingClientRect(); const width = rect.width; const height = rect.height; const hypotenuse = Math.sqrt(width * width + height * height); const maxDim = Math.max(height, width); const maxRadius = this.unbounded ? maxDim : hypotenuse + PADDING; const initialSize = Math.floor(maxDim * INITIAL_ORIGIN_SCALE); const finalScale = maxRadius / initialSize; let posX = x - rect.left; let posY = y - rect.top; if (this.unbounded) { posX = width * 0.5; posY = height * 0.5; } const styleX = posX - initialSize * 0.5; const styleY = posY - initialSize * 0.5; const moveX = width * 0.5 - posX; const moveY = height * 0.5 - posY; writeTask(() => { const div = document.createElement('div'); div.classList.add('ripple-effect'); const style = div.style; style.top = styleY + 'px'; style.left = styleX + 'px'; style.width = style.height = initialSize + 'px'; style.setProperty('--final-scale', `${finalScale}`); style.setProperty('--translate-end', `${moveX}px, ${moveY}px`); const container = this.el.shadowRoot || this.el; container.appendChild(div); setTimeout(() => { resolve(() => { removeRipple(div); }); }, 225 + 100); }); }); }); } get unbounded() { return this.type === 'unbounded'; } render() { const mode = getIonMode(this); return (h(Host, { key: '40c7f73e7f5f67e29f83e1236a61c6e1c9943c42', role: "presentation", class: { [mode]: true, unbounded: this.unbounded, } })); } get el() { return this; } static get style() { return IonRippleEffectStyle0; } }, [1, "ion-ripple-effect", { "type": [1], "addRipple": [64] }]); const removeRipple = (ripple) => { ripple.classList.add('fade-out'); setTimeout(() => { ripple.remove(); }, 200); }; const PADDING = 10; const INITIAL_ORIGIN_SCALE = 0.5; function defineCustomElement() { if (typeof customElements === "undefined") { return; } const components = ["ion-ripple-effect"]; components.forEach(tagName => { switch (tagName) { case "ion-ripple-effect": if (!customElements.get(tagName)) { customElements.define(tagName, RippleEffect); } break; } }); } export { RippleEffect as R, defineCustomElement as d };