1
|
|
// Components
|
2
|
1
|
import {
|
3
|
|
VTabTransition,
|
4
|
|
VTabReverseTransition,
|
5
|
|
} from '../transitions'
|
6
|
|
|
7
|
|
// Mixins
|
8
|
1
|
import { inject as RegistrableInject } from '../../mixins/registrable'
|
9
|
|
|
10
|
|
// Helpers
|
11
|
1
|
import { convertToUnit } from '../../util/helpers'
|
12
|
|
|
13
|
|
// Utilities
|
14
|
1
|
import mixins from '../../util/mixins'
|
15
|
|
|
16
|
|
// Types
|
17
|
|
import { VNode, FunctionalComponentOptions, VNodeData } from 'vue'
|
18
|
|
|
19
|
1
|
const baseMixins = mixins(
|
20
|
|
RegistrableInject('stepper', 'v-stepper-content', 'v-stepper')
|
21
|
|
)
|
22
|
|
|
23
|
|
interface options extends InstanceType<typeof baseMixins> {
|
24
|
|
$refs: {
|
25
|
|
wrapper: HTMLElement
|
26
|
|
}
|
27
|
|
isVerticalProvided: boolean
|
28
|
|
}
|
29
|
|
|
30
|
|
/* @vue/component */
|
31
|
1
|
export default baseMixins.extend<options>().extend({
|
32
|
|
name: 'v-stepper-content',
|
33
|
|
|
34
|
|
inject: {
|
35
|
|
isVerticalProvided: {
|
36
|
|
from: 'isVertical',
|
37
|
|
},
|
38
|
|
},
|
39
|
|
|
40
|
|
props: {
|
41
|
|
step: {
|
42
|
|
type: [Number, String],
|
43
|
|
required: true,
|
44
|
|
},
|
45
|
|
},
|
46
|
|
|
47
|
1
|
data () {
|
48
|
1
|
return {
|
49
|
|
height: 0 as number | string,
|
50
|
|
// Must be null to allow
|
51
|
|
// previous comparison
|
52
|
|
isActive: null as boolean | null,
|
53
|
|
isReverse: false,
|
54
|
|
isVertical: this.isVerticalProvided,
|
55
|
|
}
|
56
|
|
},
|
57
|
|
|
58
|
|
computed: {
|
59
|
1
|
computedTransition (): FunctionalComponentOptions {
|
60
|
|
// Fix for #8978
|
61
|
1
|
const reverse = this.$vuetify.rtl ? !this.isReverse : this.isReverse
|
62
|
|
|
63
|
1
|
return reverse
|
64
|
1
|
? VTabReverseTransition
|
65
|
1
|
: VTabTransition
|
66
|
|
},
|
67
|
1
|
styles (): object {
|
68
|
1
|
if (!this.isVertical) return {}
|
69
|
|
|
70
|
1
|
return {
|
71
|
|
height: convertToUnit(this.height),
|
72
|
|
}
|
73
|
|
},
|
74
|
|
},
|
75
|
|
|
76
|
|
watch: {
|
77
|
1
|
isActive (current, previous) {
|
78
|
|
// If active and the previous state
|
79
|
|
// was null, is just booting up
|
80
|
1
|
if (current && previous == null) {
|
81
|
1
|
this.height = 'auto'
|
82
|
1
|
return
|
83
|
|
}
|
84
|
|
|
85
|
1
|
if (!this.isVertical) return
|
86
|
|
|
87
|
1
|
if (this.isActive) this.enter()
|
88
|
1
|
else this.leave()
|
89
|
|
},
|
90
|
|
},
|
91
|
|
|
92
|
1
|
mounted () {
|
93
|
1
|
this.$refs.wrapper.addEventListener(
|
94
|
|
'transitionend',
|
95
|
|
this.onTransition,
|
96
|
|
false
|
97
|
|
)
|
98
|
1
|
this.stepper && this.stepper.register(this)
|
99
|
|
},
|
100
|
|
|
101
|
1
|
beforeDestroy () {
|
102
|
1
|
this.$refs.wrapper.removeEventListener(
|
103
|
|
'transitionend',
|
104
|
|
this.onTransition,
|
105
|
|
false
|
106
|
|
)
|
107
|
1
|
this.stepper && this.stepper.unregister(this)
|
108
|
|
},
|
109
|
|
|
110
|
|
methods: {
|
111
|
1
|
onTransition (e: TransitionEvent) {
|
112
|
1
|
if (!this.isActive ||
|
113
|
1
|
e.propertyName !== 'height'
|
114
|
1
|
) return
|
115
|
|
|
116
|
1
|
this.height = 'auto'
|
117
|
|
},
|
118
|
1
|
enter () {
|
119
|
1
|
let scrollHeight = 0
|
120
|
|
|
121
|
|
// Render bug with height
|
122
|
1
|
requestAnimationFrame(() => {
|
123
|
1
|
scrollHeight = this.$refs.wrapper.scrollHeight
|
124
|
|
})
|
125
|
|
|
126
|
1
|
this.height = 0
|
127
|
|
|
128
|
|
// Give the collapsing element time to collapse
|
129
|
1
|
setTimeout(() => this.isActive && (this.height = (scrollHeight || 'auto')), 450)
|
130
|
|
},
|
131
|
1
|
leave () {
|
132
|
1
|
this.height = this.$refs.wrapper.clientHeight
|
133
|
1
|
setTimeout(() => (this.height = 0), 10)
|
134
|
|
},
|
135
|
1
|
toggle (step: string | number, reverse: boolean) {
|
136
|
1
|
this.isActive = step.toString() === this.step.toString()
|
137
|
1
|
this.isReverse = reverse
|
138
|
|
},
|
139
|
|
},
|
140
|
|
|
141
|
1
|
render (h): VNode {
|
142
|
1
|
const contentData = {
|
143
|
|
staticClass: 'v-stepper__content',
|
144
|
|
} as VNodeData
|
145
|
1
|
const wrapperData = {
|
146
|
|
staticClass: 'v-stepper__wrapper',
|
147
|
|
style: this.styles,
|
148
|
|
ref: 'wrapper',
|
149
|
|
}
|
150
|
|
|
151
|
1
|
if (!this.isVertical) {
|
152
|
1
|
contentData.directives = [{
|
153
|
|
name: 'show',
|
154
|
|
value: this.isActive,
|
155
|
|
}]
|
156
|
|
}
|
157
|
|
|
158
|
1
|
const wrapper = h('div', wrapperData, [this.$slots.default])
|
159
|
1
|
const content = h('div', contentData, [wrapper])
|
160
|
|
|
161
|
1
|
return h(this.computedTransition, {
|
162
|
|
on: this.$listeners,
|
163
|
|
}, [content])
|
164
|
|
},
|
165
|
|
})
|