UNPKG

vuetify

Version:

Vue.js 2 Semantic Component Framework

160 lines (136 loc) 3.74 kB
// Components import VWindow from './VWindow' // Mixins import Bootable from '../../mixins/bootable' import { factory as GroupableFactory } from '../../mixins/groupable' // Directives import Touch from '../../directives/touch' // Utilities import { convertToUnit } from '../../util/helpers' import { ExtractVue } from './../../util/mixins' import mixins from '../../util/mixins' // Types import Vue from 'vue' import { VNode, VNodeDirective } from 'vue/types' type VBaseWindow = InstanceType<typeof VWindow> interface options extends Vue { windowGroup: VBaseWindow } export default mixins<options & ExtractVue<[typeof Bootable]>>( Bootable, GroupableFactory('windowGroup', 'v-window-item', 'v-window') /* @vue/component */ ).extend({ name: 'v-window-item', directives: { Touch }, props: { reverseTransition: { type: [Boolean, String], default: undefined }, transition: { type: [Boolean, String], default: undefined }, value: { required: false } }, data () { return { done: null as null | (() => void), isActive: false, wasCancelled: false } }, computed: { computedTransition (): string | boolean { if (!this.windowGroup.internalReverse) { return typeof this.transition !== 'undefined' ? this.transition || '' : this.windowGroup.computedTransition } return typeof this.reverseTransition !== 'undefined' ? this.reverseTransition || '' : this.windowGroup.computedTransition } }, mounted () { this.$el.addEventListener('transitionend', this.onTransitionEnd, false) }, beforeDestroy () { this.$el.removeEventListener('transitionend', this.onTransitionEnd, false) }, methods: { genDefaultSlot () { return this.$slots.default }, onAfterEnter () { if (this.wasCancelled) { this.wasCancelled = false return } requestAnimationFrame(() => { this.windowGroup.internalHeight = undefined this.windowGroup.isActive = false }) }, onBeforeEnter () { this.windowGroup.isActive = true }, onLeave (el: HTMLElement) { this.windowGroup.internalHeight = convertToUnit(el.clientHeight) }, onEnterCancelled () { this.wasCancelled = true }, onEnter (el: HTMLElement, done: () => void) { const isBooted = this.windowGroup.isBooted if (isBooted) this.done = done requestAnimationFrame(() => { if (!this.computedTransition) return done() this.windowGroup.internalHeight = convertToUnit(el.clientHeight) // On initial render, there is no transition // Vue leaves a `enter` transition class // if done is called too fast !isBooted && setTimeout(done, 100) }) }, onTransitionEnd (e: TransitionEvent) { // This ensures we only call done // when the element transform // completes if ( e.propertyName !== 'transform' || e.target !== this.$el || !this.done ) return this.done() this.done = null } }, render (h): VNode { const div = h('div', { staticClass: 'v-window-item', directives: [{ name: 'show', value: this.isActive }] as VNodeDirective[], on: this.$listeners }, this.showLazyContent(this.genDefaultSlot())) return h('transition', { props: { name: this.computedTransition }, on: { afterEnter: this.onAfterEnter, beforeEnter: this.onBeforeEnter, leave: this.onLeave, enter: this.onEnter, enterCancelled: this.onEnterCancelled } }, [div]) } })