@@ -11,6 +11,7 @@ import {
1111 leaveCbKey ,
1212 registerVaporTransition ,
1313 useTransitionState ,
14+ warn ,
1415} from '@vue/runtime-dom'
1516import type { Block } from '../block'
1617import { isVaporComponent } from '../component'
@@ -21,12 +22,10 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
2122 slots : { default : ( ) => Block } ,
2223 ) => {
2324 const children = slots . default && slots . default ( )
24- if ( ! children ) {
25- return
26- }
25+ if ( ! children ) return
2726
28- // TODO find non-comment node
29- const child = children
27+ const child = findElementChild ( children )
28+ if ( ! child ) return
3029
3130 const state = useTransitionState ( )
3231 let enterHooks = resolveTransitionHooks (
@@ -39,12 +38,23 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
3938 setTransitionHooks ( child , enterHooks )
4039
4140 const { mode } = props
42- // TODO check mode
41+ if (
42+ __DEV__ &&
43+ mode &&
44+ mode !== 'in-out' &&
45+ mode !== 'out-in' &&
46+ mode !== 'default'
47+ ) {
48+ warn ( `invalid <transition> mode: ${ mode } ` )
49+ }
4350
44- child . applyLeavingHooks = (
45- leavingBlock : Block ,
51+ child . applyTransitionLeavingHooks = (
52+ block : Block ,
4653 afterLeaveCb : ( ) => void ,
4754 ) => {
55+ const leavingBlock = findElementChild ( block )
56+ if ( ! leavingBlock ) return undefined
57+
4858 let leavingHooks = resolveTransitionHooks (
4959 leavingBlock as any ,
5060 props ,
@@ -87,15 +97,15 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
8797 } ,
8898}
8999
90- function resolveTransitionHooks (
100+ const getTransitionHooksContext = (
101+ leavingNodeCache : Record < string , Block > ,
102+ key : string ,
91103 block : Block ,
92104 props : TransitionProps ,
93105 state : TransitionState ,
94106 instance : GenericComponentInstance ,
95- postClone ?: ( hooks : TransitionHooks ) => void ,
96- ) : TransitionHooks {
97- const key = String ( block . key )
98- const leavingNodeCache = getLeavingNodesForBlock ( state , block )
107+ postClone : ( ( hooks : TransitionHooks ) => void ) | undefined ,
108+ ) => {
99109 const context : TransitionHooksContext = {
100110 setLeavingNodeCache : ( ) => {
101111 leavingNodeCache [ key ] = block
@@ -124,6 +134,27 @@ function resolveTransitionHooks(
124134 return hooks
125135 } ,
126136 }
137+ return context
138+ }
139+
140+ function resolveTransitionHooks (
141+ block : Block ,
142+ props : TransitionProps ,
143+ state : TransitionState ,
144+ instance : GenericComponentInstance ,
145+ postClone ?: ( hooks : TransitionHooks ) => void ,
146+ ) : TransitionHooks {
147+ const key = String ( block . key )
148+ const leavingNodeCache = getLeavingNodesForBlock ( state , block )
149+ const context = getTransitionHooksContext (
150+ leavingNodeCache ,
151+ key ,
152+ block ,
153+ props ,
154+ state ,
155+ instance ,
156+ postClone ,
157+ )
127158 return baseResolveTransitionHooks ( context , props , state , instance )
128159}
129160
@@ -141,11 +172,47 @@ function getLeavingNodesForBlock(
141172}
142173
143174function setTransitionHooks ( block : Block , hooks : TransitionHooks ) {
144- if ( isVaporComponent ( block ) ) {
145- setTransitionHooks ( block . block , hooks )
175+ block . transition = hooks
176+ }
177+
178+ function findElementChild ( block : Block ) : Block | undefined {
179+ let child : Block | undefined
180+ // transition can only be applied on Element child
181+ if ( block instanceof Element ) {
182+ child = block
183+ } else if ( isVaporComponent ( block ) ) {
184+ child = findElementChild ( block . block )
185+ } else if ( Array . isArray ( block ) ) {
186+ child = block [ 0 ]
187+ let hasFound = false
188+ for ( const c of block ) {
189+ const item = findElementChild ( c )
190+ if ( item instanceof Element ) {
191+ if ( __DEV__ && hasFound ) {
192+ // warn more than one non-comment child
193+ warn (
194+ '<transition> can only be used on a single element or component. ' +
195+ 'Use <transition-group> for lists.' ,
196+ )
197+ break
198+ }
199+ child = item
200+ hasFound = true
201+ if ( ! __DEV__ ) break
202+ }
203+ }
146204 } else {
147- block . transition = hooks
205+ // fragment
206+ // store transition hooks on fragment itself, so it can apply to both
207+ // previous and new branch during updates.
208+ child = block
148209 }
210+
211+ if ( __DEV__ && ! child ) {
212+ warn ( 'Transition component has no valid child element' )
213+ }
214+
215+ return child
149216}
150217
151218let registered = false
0 commit comments