/** * @summary aofl-drawer * @version 3.0.0 * @since 3.0.0 * @author Arian Khosravi <arian.khosravi@aofl.com> */ import {AoflElement} from '@aofl/element'; import styles from './drawer.css'; /** * @memberof module:@aofl/drawer * @extends {AoflElement} */ class AoflDrawer extends AoflElement { /** * Creates an instance of AoflDrawer. */ constructor() { super(); this.open = null; this.transitionEndCount = 0; this['transition-count'] = 1; } /** * @readonly * @type {String} */ static get is() { return 'aofl-drawer'; } /** * @readonly * @property {Boolean} open - state of drawer * @property {String} trigger - className that triggers animations * @property {String} opening - className of opening animation * @property {String} closing - className of closing animation */ static get properties() { return { 'open': {type: Boolean}, 'trigger': {type: String}, 'opening': {type: String}, 'closing': {type: String}, 'transition-count': {type: Number} }; } /** * */ connectedCallback(...args) { super.connectedCallback(...args); // Set defaults this.cancelOpen = null; this.trigger = this.trigger || 'animate'; this.animated = typeof this.opening !== 'undefined' && typeof this.closing !== 'undefined'; // Initialize class to prepare for next animation if (this.animated) { if (this.open) { this.classList.remove(this.opening); this.classList.add(this.closing); } else { this.classList.remove(this.closing); this.classList.add(this.opening); } this.addEventListener('animationend', this.animationEndHandler); this.addEventListener('transitionend', this.animationEndHandler); } } /** * @return {Object} */ render() { return super.render((ctx, html) => html`<slot></slot>`, [styles]); } /** * * @param {*} name * @param {*} oldValue * @param {*} newValue */ attributeChangedCallback(name, oldValue, newValue) { super.attributeChangedCallback(name, oldValue, newValue); /* istanbul ignore else */ if (name === 'open') { if (this.animated) { this.openChanged(this.open); } else { this.dispatchEvent(new CustomEvent('drawer-toggle', { composed: true, bubbles: true })); } } } /** * @param {Boolean} newVal * @private */ openChanged(newVal) { /* istanbul ignore else */ if (newVal === true) { this.cancelOpen = this.startOpeningAnimation(() => { this.transitionEndCount = 0; this.classList.remove(this.closing); this.classList.add(this.opening); this.classList.add(this.trigger); }); } else if (this.classList.contains(this.closing) || this.classList.contains(this.trigger)) { if (typeof this.cancelOpen === 'function') { this.cancelOpen(); this.cancelOpen = null; } this.classList.remove(this.opening); this.classList.add(this.closing); this.classList.add(this.trigger); this.classList.add('closing'); } } /** * Waits for display block to be present before adding animation * * @param {Function} callback * @return {Function} * @private */ startOpeningAnimation(callback) { let cancel = false; let max = 100; const testDisplayBlock = () => { const display = window.getComputedStyle(this).getPropertyValue('display'); /* istanbul ignore next */ if (display === 'block') { callback(); } else if (!cancel && max-- > 0) { window.requestAnimationFrame(testDisplayBlock); } }; testDisplayBlock(); return /* istanbul ignore next */ () => { cancel = true; }; } /** * Removes closed after drawer closes so display: none can be applied * * @private */ animationEndHandler(e) { /* istanbul ignore next */ if (e.target !== this) { return; } this.transitionEndCount += 1; if (this.transitionEndCount === this['transition-count']) { this.transitionEndCount = 0; this.classList.remove(this.trigger); if (this.classList.contains(this.opening)) { this.classList.remove(this.opening); this.classList.add(this.closing); this.cancelOpen = null; } else { this.classList.add(this.opening); this.classList.remove(this.closing); this.classList.remove('closing'); } setTimeout(() => { // queue micro task this.dispatchEvent(new CustomEvent('drawer-toggle', { composed: true, bubbles: true })); }); } } /** * */ disconnectedCallback(...args) { super.disconnectedCallback(...args); if (this.animated) { this.removeEventListener('animationend', this.animationEndHandler); this.removeEventListener('transitionend', this.animationEndHandler); } } } /* istanbul ignore else */ if (window.customElements.get(AoflDrawer.is) === void 0) { window.customElements.define(AoflDrawer.is, AoflDrawer); } export default AoflDrawer;