import { isKeepAlive } from './KeepAlive'
import { toRaw } from '@vue/reactivity'
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
-import { ShapeFlags, PatchFlags } from '@vue/shared'
+import { ShapeFlags, PatchFlags, isArray } from '@vue/shared'
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
import { RendererElement } from '../renderer'
+type Hook<T = () => void> = T | T[]
+
export interface BaseTransitionProps<HostElement = RendererElement> {
mode?: 'in-out' | 'out-in' | 'default'
appear?: boolean
// Hooks. Using camel case for easier usage in render functions & JSX.
// In templates these can be written as @before-enter="xxx" as prop names
// are camelized.
- onBeforeEnter?: (el: HostElement) => void
- onEnter?: (el: HostElement, done: () => void) => void
- onAfterEnter?: (el: HostElement) => void
- onEnterCancelled?: (el: HostElement) => void
+ onBeforeEnter?: Hook<(el: HostElement) => void>
+ onEnter?: Hook<(el: HostElement, done: () => void) => void>
+ onAfterEnter?: Hook<(el: HostElement) => void>
+ onEnterCancelled?: Hook<(el: HostElement) => void>
// leave
- onBeforeLeave?: (el: HostElement) => void
- onLeave?: (el: HostElement, done: () => void) => void
- onAfterLeave?: (el: HostElement) => void
- onLeaveCancelled?: (el: HostElement) => void // only fired in persisted mode
+ onBeforeLeave?: Hook<(el: HostElement) => void>
+ onLeave?: Hook<(el: HostElement, done: () => void) => void>
+ onAfterLeave?: Hook<(el: HostElement) => void>
+ onLeaveCancelled?: Hook<(el: HostElement) => void> // only fired in persisted mode
// appear
- onBeforeAppear?: (el: HostElement) => void
- onAppear?: (el: HostElement, done: () => void) => void
- onAfterAppear?: (el: HostElement) => void
- onAppearCancelled?: (el: HostElement) => void
+ onBeforeAppear?: Hook<(el: HostElement) => void>
+ onAppear?: Hook<(el: HostElement, done: () => void) => void>
+ onAfterAppear?: Hook<(el: HostElement) => void>
+ onAppearCancelled?: Hook<(el: HostElement) => void>
}
export interface TransitionHooks<
delayedLeave?(): void
}
-export type TransitionHookCaller = (
- hook: ((el: any) => void) | Array<(el: any) => void> | undefined,
- args?: any[]
+export type TransitionHookCaller = <T extends any[] = [el: any]>(
+ hook: Hook<(...args: T) => void> | undefined,
+ args?: T
) => void
export type PendingCallback = (cancelled?: boolean) => void
)
}
+ const callAsyncHook = (
+ hook: Hook<(el: any, done: () => void) => void>,
+ args: [TransitionElement, () => void]
+ ) => {
+ const done = args[1]
+ callHook(hook, args)
+ if (isArray(hook)) {
+ if (hook.every(hook => hook.length <= 1)) done()
+ } else if (hook.length <= 1) {
+ done()
+ }
+ }
+
const hooks: TransitionHooks<TransitionElement> = {
mode,
persisted,
el._enterCb = undefined
})
if (hook) {
- hook(el, done)
- if (hook.length <= 1) {
- done()
- }
+ callAsyncHook(hook, [el, done])
} else {
done()
}
})
leavingVNodesCache[key] = vnode
if (onLeave) {
- onLeave(el, done)
- if (onLeave.length <= 1) {
- done()
- }
+ callAsyncHook(onLeave, [el, done])
} else {
done()
}