UNPKG

vue-material

Version:
155 lines (136 loc) 3.67 kB
import Vue from 'vue' export default { name: 'MdPortal', abstract: true, props: { mdAttachToParent: Boolean, mdTarget: { type: null, validator (value) { if (HTMLElement && value && value instanceof HTMLElement) { return true } Vue.util.warn('The md-target-el prop is invalid. You should pass a valid HTMLElement.', this) return false } } }, data: () => ({ leaveTimeout: null, originalParentEl: null }), computed: { transitionName () { const childrenComponent = this._vnode.componentOptions.children[0] if (childrenComponent) { const transition = childrenComponent.data.transition if (transition) { return transition.name } else { const transition = childrenComponent.componentOptions.propsData.name if (transition) { return transition } } } return 'v' }, leaveClass () { return this.transitionName + '-leave' }, leaveActiveClass () { return this.transitionName + '-leave-active' }, leaveToClass () { return this.transitionName + '-leave-to' } }, watch: { mdTarget (newTarget, oldTarget) { this.changeParentEl(newTarget) if (oldTarget) { this.$forceUpdate() } } }, methods: { getTransitionDuration (el) { const duration = getComputedStyle(el).transitionDuration const num = parseFloat(duration, 10) let unit = duration.match(/m?s/) let milliseconds = null if (unit) { unit = unit[0] } switch (unit) { case 's': milliseconds = num * 1000 break case 'ms': milliseconds = num break default: milliseconds = 0 break } return milliseconds }, killGhostElement (el) { if (el.parentNode) { this.changeParentEl(this.originalParentEl) this.$options._parentElm = this.originalParentEl el.parentNode.removeChild(el) } }, async initDestroy (manualCall) { let el = this.$el if (manualCall && this.$el.constructor.name.toLowerCase() === 'comment') { el = this.$vnode.elm } el.classList.add(this.leaveClass) el.classList.add(this.leaveActiveClass) await this.$nextTick() el.classList.add(this.leaveToClass) clearTimeout(this.leaveTimeout) this.leaveTimeout = setTimeout(() => { this.destroyElement(el) }, this.getTransitionDuration(el)) }, destroyElement (el) { requestAnimationFrame(() => { el.classList.remove(this.leaveClass) el.classList.remove(this.leaveActiveClass) el.classList.remove(this.leaveToClass) this.$emit('md-destroy') this.killGhostElement(el) }) }, changeParentEl (newTarget) { newTarget && newTarget.appendChild(this.$el) } }, mounted () { if (!this.originalParentEl) { this.originalParentEl = this.$el.parentNode this.$emit('md-initial-parent', this.$el.parentNode) } if (this.mdAttachToParent && this.$el.parentNode.parentNode) { this.changeParentEl(this.$el.parentNode.parentNode) } else if (document) { this.changeParentEl(this.mdTarget || document.body) } }, beforeDestroy () { if (this.$el.classList) { this.initDestroy() } else { this.killGhostElement(this.$el) } }, render (createElement) { const defaultSlot = this.$slots.default if (defaultSlot && defaultSlot[0]) { return defaultSlot[0] } } }