vuetify
Version:
Vue Material Component Framework
162 lines (140 loc) • 3.98 kB
text/typescript
// 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 mixins, { ExtractVue } from '../../util/mixins'
// Types
import { VNode } from 'vue'
const baseMixins = mixins(
Bootable,
GroupableFactory('windowGroup', 'v-window-item', 'v-window')
)
interface options extends ExtractVue<typeof baseMixins> {
$el: HTMLElement
windowGroup: InstanceType<typeof VWindow>
}
export default baseMixins.extend<options>().extend(
/* @vue/component */
).extend({
name: 'v-window-item',
directives: {
Touch,
},
props: {
disabled: Boolean,
reverseTransition: {
type: [Boolean, String],
default: undefined,
},
transition: {
type: [Boolean, String],
default: undefined,
},
value: {
required: false,
},
},
data () {
return {
isActive: false,
inTransition: false,
}
},
computed: {
classes (): object {
return this.groupClasses
},
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
},
},
methods: {
genDefaultSlot () {
return this.$slots.default
},
genWindowItem () {
return this.$createElement('div', {
staticClass: 'v-window-item',
class: this.classes,
directives: [{
name: 'show',
value: this.isActive,
}],
on: this.$listeners,
}, this.genDefaultSlot())
},
onAfterTransition () {
if (!this.inTransition) {
return
}
// Finalize transition state.
this.inTransition = false
if (this.windowGroup.transitionCount > 0) {
this.windowGroup.transitionCount--
// Remove container height if we are out of transition.
if (this.windowGroup.transitionCount === 0) {
this.windowGroup.transitionHeight = undefined
}
}
},
onBeforeTransition () {
if (this.inTransition) {
return
}
// Initialize transition state here.
this.inTransition = true
if (this.windowGroup.transitionCount === 0) {
// Set initial height for height transition.
this.windowGroup.transitionHeight = convertToUnit(this.windowGroup.$el.clientHeight)
}
this.windowGroup.transitionCount++
},
onTransitionCancelled () {
this.onAfterTransition() // This should have the same path as normal transition end.
},
onEnter (el: HTMLElement) {
if (!this.inTransition) {
return
}
this.$nextTick(() => {
// Do not set height if no transition or cancelled.
if (!this.computedTransition || !this.inTransition) {
return
}
// Set transition target height.
this.windowGroup.transitionHeight = convertToUnit(el.clientHeight)
})
},
},
render (h): VNode {
return h('transition', {
props: {
name: this.computedTransition,
},
on: {
// Handlers for enter windows.
beforeEnter: this.onBeforeTransition,
afterEnter: this.onAfterTransition,
enterCancelled: this.onTransitionCancelled,
// Handlers for leave windows.
beforeLeave: this.onBeforeTransition,
afterLeave: this.onAfterTransition,
leaveCancelled: this.onTransitionCancelled,
// Enter handler for height transition.
enter: this.onEnter,
},
}, this.showLazyContent(() => [this.genWindowItem()]))
},
})