Skip to content

Commit 2e71c9e

Browse files
feat(vapor): vapor TransitionGroup (#13019)
* wip: save * wip: save * wip: handle tag prop and attrs fallthrough * test: add e2e tests * [autofix.ci] apply automated fixes * wip: add more tests * [autofix.ci] apply automated fixes * wip: handle vdom interop * [autofix.ci] apply automated fixes * wip: vapor interop + filter out reserved props * [autofix.ci] apply automated fixes * fix: tests --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 5392c7a commit 2e71c9e

File tree

27 files changed

+1167
-190
lines changed

27 files changed

+1167
-190
lines changed

packages-private/vapor-e2e-test/__tests__/transition-group.spec.ts

+406
Large diffs are not rendered by default.

packages-private/vapor-e2e-test/__tests__/transition.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ describe('vapor transition', () => {
130130

131131
expect(calls).toStrictEqual([
132132
'beforeAppear',
133-
'onEnter',
133+
'onAppear',
134134
'afterAppear',
135135
'beforeLeave',
136136
'onLeave',

packages-private/vapor-e2e-test/__tests__/vdomInterop.spec.ts

+52-10
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,18 @@ describe('vdom / vapor interop', () => {
105105
const btnSelector = '.trans-vapor > button'
106106
const containerSelector = '.trans-vapor > div'
107107

108-
expect(await html(containerSelector)).toBe(
109-
`<div key="0">vapor compA</div>`,
110-
)
108+
expect(await html(containerSelector)).toBe(`<div>vapor compA</div>`)
111109

112110
// comp leave
113111
expect(
114112
(await transitionStart(btnSelector, containerSelector)).innerHTML,
115113
).toBe(
116-
`<div key="0" class="v-leave-from v-leave-active">vapor compA</div><!---->`,
114+
`<div class="v-leave-from v-leave-active">vapor compA</div><!---->`,
117115
)
118116

119117
await nextFrame()
120118
expect(await html(containerSelector)).toBe(
121-
`<div key="0" class="v-leave-active v-leave-to">vapor compA</div><!---->`,
119+
`<div class="v-leave-active v-leave-to">vapor compA</div><!---->`,
122120
)
123121

124122
await transitionFinish()
@@ -127,18 +125,16 @@ describe('vdom / vapor interop', () => {
127125
// comp enter
128126
expect(
129127
(await transitionStart(btnSelector, containerSelector)).innerHTML,
130-
).toBe(
131-
`<div key="0" class="v-enter-from v-enter-active">vapor compA</div>`,
132-
)
128+
).toBe(`<div class="v-enter-from v-enter-active">vapor compA</div>`)
133129

134130
await nextFrame()
135131
expect(await html(containerSelector)).toBe(
136-
`<div key="0" class="v-enter-active v-enter-to">vapor compA</div>`,
132+
`<div class="v-enter-active v-enter-to">vapor compA</div>`,
137133
)
138134

139135
await transitionFinish()
140136
expect(await html(containerSelector)).toBe(
141-
`<div key="0" class="">vapor compA</div>`,
137+
`<div class="">vapor compA</div>`,
142138
)
143139
},
144140
E2E_TIMEOUT,
@@ -214,4 +210,50 @@ describe('vdom / vapor interop', () => {
214210
E2E_TIMEOUT,
215211
)
216212
})
213+
214+
describe('vdom transition-group', () => {
215+
test(
216+
'render vapor component',
217+
async () => {
218+
const btnSelector = '.trans-group-vapor > button'
219+
const containerSelector = '.trans-group-vapor > div'
220+
221+
expect(await html(containerSelector)).toBe(
222+
`<div><div>a</div></div>` +
223+
`<div><div>b</div></div>` +
224+
`<div><div>c</div></div>`,
225+
)
226+
227+
// insert
228+
expect(
229+
(await transitionStart(btnSelector, containerSelector)).innerHTML,
230+
).toBe(
231+
`<div><div>a</div></div>` +
232+
`<div><div>b</div></div>` +
233+
`<div><div>c</div></div>` +
234+
`<div class="test-enter-from test-enter-active"><div>d</div></div>` +
235+
`<div class="test-enter-from test-enter-active"><div>e</div></div>`,
236+
)
237+
238+
await nextFrame()
239+
expect(await html(containerSelector)).toBe(
240+
`<div><div>a</div></div>` +
241+
`<div><div>b</div></div>` +
242+
`<div><div>c</div></div>` +
243+
`<div class="test-enter-active test-enter-to"><div>d</div></div>` +
244+
`<div class="test-enter-active test-enter-to"><div>e</div></div>`,
245+
)
246+
247+
await transitionFinish()
248+
expect(await html(containerSelector)).toBe(
249+
`<div><div>a</div></div>` +
250+
`<div><div>b</div></div>` +
251+
`<div><div>c</div></div>` +
252+
`<div class=""><div>d</div></div>` +
253+
`<div class=""><div>e</div></div>`,
254+
)
255+
},
256+
E2E_TIMEOUT,
257+
)
258+
})
217259
})
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
<a href="/interop/">VDOM / Vapor interop</a>
22
<a href="/todomvc/">Vapor TodoMVC</a>
33
<a href="/transition/">Vapor Transition</a>
4+
<a href="/transition-group/">Vapor TransitionGroup</a>
5+
6+
<style>
7+
a {
8+
display: block;
9+
margin: 10px;
10+
}
11+
</style>

packages-private/vapor-e2e-test/interop/App.vue

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ref, shallowRef } from 'vue'
33
import VaporComp from './VaporComp.vue'
44
import VaporCompA from '../transition/components/VaporCompA.vue'
55
import VdomComp from '../transition/components/VdomComp.vue'
6+
import VaporSlot from '../transition/components/VaporSlot.vue'
67
78
const msg = ref('hello')
89
const passSlot = ref(true)
@@ -13,6 +14,9 @@ function toggleInteropComponent() {
1314
interopComponent.value =
1415
interopComponent.value === VaporCompA ? VdomComp : VaporCompA
1516
}
17+
18+
const items = ref(['a', 'b', 'c'])
19+
const enterClick = () => items.value.push('d', 'e')
1620
</script>
1721

1822
<template>
@@ -52,4 +56,17 @@ function toggleInteropComponent() {
5256
</div>
5357
</div>
5458
</div>
59+
<!-- transition-group interop -->
60+
<div>
61+
<div class="trans-group-vapor">
62+
<button @click="enterClick">insert items</button>
63+
<div>
64+
<transition-group name="test">
65+
<VaporSlot v-for="item in items" :key="item">
66+
<div>{{ item }}</div>
67+
</VaporSlot>
68+
</transition-group>
69+
</div>
70+
</div>
71+
</div>
5572
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<script setup vapor>
2+
import { ref } from 'vue'
3+
import VdomComp from './components/VdomComp.vue'
4+
5+
const items = ref(['a', 'b', 'c'])
6+
const enterClick = () => items.value.push('d', 'e')
7+
const leaveClick = () => (items.value = ['b'])
8+
const enterLeaveClick = () => (items.value = ['b', 'c', 'd'])
9+
const appear = ref(false)
10+
window.setAppear = () => (appear.value = true)
11+
const moveClick = () => (items.value = ['d', 'b', 'a'])
12+
13+
const name = ref('invalid')
14+
const dynamicClick = () => (items.value = ['b', 'c', 'a'])
15+
const changeName = () => {
16+
name.value = 'group'
17+
items.value = ['a', 'b', 'c']
18+
}
19+
20+
let calls = []
21+
window.getCalls = () => {
22+
const ret = calls.slice()
23+
calls = []
24+
return ret
25+
}
26+
const eventsClick = () => (items.value = ['b', 'c', 'd'])
27+
28+
const interopClick = () => (items.value = ['b', 'c', 'd'])
29+
</script>
30+
31+
<template>
32+
<div class="transition-group-container">
33+
<div class="enter">
34+
<button @click="enterClick">enter button</button>
35+
<div>
36+
<transition-group name="test">
37+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
38+
</transition-group>
39+
</div>
40+
</div>
41+
<div class="leave">
42+
<button @click="leaveClick">leave button</button>
43+
<div>
44+
<transition-group name="test">
45+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
46+
</transition-group>
47+
</div>
48+
</div>
49+
<div class="enter-leave">
50+
<button @click="enterLeaveClick">enter-leave button</button>
51+
<div>
52+
<transition-group name="test">
53+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
54+
</transition-group>
55+
</div>
56+
</div>
57+
<div class="appear">
58+
<button @click="enterClick">appear button</button>
59+
<div v-if="appear">
60+
<transition-group
61+
appear
62+
appear-from-class="test-appear-from"
63+
appear-to-class="test-appear-to"
64+
appear-active-class="test-appear-active"
65+
name="test"
66+
>
67+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
68+
</transition-group>
69+
</div>
70+
</div>
71+
<div class="move">
72+
<button @click="moveClick">move button</button>
73+
<div>
74+
<transition-group name="group">
75+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
76+
</transition-group>
77+
</div>
78+
</div>
79+
<div class="dynamic-name">
80+
<button class="toggleBtn" @click="dynamicClick">dynamic button</button>
81+
<button class="changeNameBtn" @click="changeName">change name</button>
82+
<div>
83+
<transition-group :name="name">
84+
<div v-for="item in items" :key="item">{{ item }}</div>
85+
</transition-group>
86+
</div>
87+
</div>
88+
<div class="events">
89+
<button @click="eventsClick">events button</button>
90+
<div v-if="appear">
91+
<transition-group
92+
name="test"
93+
appear
94+
appear-from-class="test-appear-from"
95+
appear-to-class="test-appear-to"
96+
appear-active-class="test-appear-active"
97+
@beforeEnter="() => calls.push('beforeEnter')"
98+
@enter="() => calls.push('onEnter')"
99+
@afterEnter="() => calls.push('afterEnter')"
100+
@beforeLeave="() => calls.push('beforeLeave')"
101+
@leave="() => calls.push('onLeave')"
102+
@afterLeave="() => calls.push('afterLeave')"
103+
@beforeAppear="() => calls.push('beforeAppear')"
104+
@appear="() => calls.push('onAppear')"
105+
@afterAppear="() => calls.push('afterAppear')"
106+
>
107+
<div v-for="item in items" :key="item" class="test">{{ item }}</div>
108+
</transition-group>
109+
</div>
110+
</div>
111+
<div class="interop">
112+
<button @click="interopClick">interop button</button>
113+
<div>
114+
<transition-group name="test">
115+
<VdomComp v-for="item in items" :key="item">
116+
<div>{{ item }}</div>
117+
</VdomComp>
118+
</transition-group>
119+
</div>
120+
</div>
121+
</div>
122+
</template>
123+
<style>
124+
.transition-group-container > div {
125+
padding: 15px;
126+
border: 1px solid #f7f7f7;
127+
margin-top: 15px;
128+
}
129+
130+
.test-move,
131+
.test-enter-active,
132+
.test-leave-active {
133+
transition: all 50ms cubic-bezier(0.55, 0, 0.1, 1);
134+
}
135+
136+
.test-enter-from,
137+
.test-leave-to {
138+
opacity: 0;
139+
transform: scaleY(0.01) translate(30px, 0);
140+
}
141+
142+
.test-leave-active {
143+
position: absolute;
144+
}
145+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script vapor>
2+
const msg = 'vapor comp'
3+
</script>
4+
5+
<template>
6+
<div>
7+
<slot />
8+
</div>
9+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script setup>
2+
const msg = 'vdom comp'
3+
</script>
4+
5+
<template>
6+
<div>
7+
<slot />
8+
</div>
9+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<script type="module" src="./main.ts"></script>
2+
<div id="app"></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createVaporApp, vaporInteropPlugin } from 'vue'
2+
import App from './App.vue'
3+
import '../../../packages/vue/__tests__/e2e/style.css'
4+
5+
createVaporApp(App).use(vaporInteropPlugin).mount('#app')

0 commit comments

Comments
 (0)