Skip to content

Commit 413651d

Browse files
committed
wip: save
1 parent 8957eaa commit 413651d

File tree

2 files changed

+105
-33
lines changed

2 files changed

+105
-33
lines changed

packages/runtime-vapor/src/block.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ export type Block = (
2525
export type TransitionBlock = {
2626
key?: any
2727
transition?: TransitionHooks
28-
applyLeavingHooks?: (
28+
applyTransitionLeavingHooks?: (
2929
block: Block,
3030
afterLeaveCb: () => void,
31-
) => TransitionHooks
31+
) => TransitionHooks | undefined
3232
}
3333

3434
export type BlockFn = (...args: any[]) => Block
@@ -39,10 +39,10 @@ export class VaporFragment {
3939
insert?: (parent: ParentNode, anchor: Node | null) => void
4040
remove?: (parent?: ParentNode) => void
4141
transition?: TransitionHooks
42-
applyLeavingHooks?: (
42+
applyTransitionLeavingHooks?: (
4343
block: Block,
4444
afterLeaveCb: () => void,
45-
) => TransitionHooks
45+
) => TransitionHooks | undefined
4646

4747
constructor(nodes: Block) {
4848
this.nodes = nodes
@@ -70,7 +70,7 @@ export class DynamicFragment extends VaporFragment {
7070
pauseTracking()
7171
const parent = this.anchor.parentNode
7272

73-
const renderNewBranch = () => {
73+
const renderBranch = () => {
7474
if (render) {
7575
this.scope = new EffectScope()
7676
this.nodes = this.scope.run(render) || []
@@ -79,22 +79,17 @@ export class DynamicFragment extends VaporFragment {
7979
this.scope = undefined
8080
this.nodes = []
8181
}
82-
83-
if (this.fallback && !isValidBlock(this.nodes)) {
84-
parent && remove(this.nodes, parent, this.transition)
85-
this.nodes =
86-
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
87-
[]
88-
parent && insert(this.nodes, parent, this.anchor, this.transition)
89-
}
9082
}
9183

9284
// teardown previous branch
9385
if (this.scope) {
9486
this.scope.stop()
9587
const mode = this.transition && this.transition.mode
9688
if (mode) {
97-
const transition = this.applyLeavingHooks!(this.nodes, renderNewBranch)
89+
const transition = this.applyTransitionLeavingHooks!(
90+
this.nodes,
91+
renderBranch,
92+
)
9893
parent && remove(this.nodes, parent, transition)
9994
if (mode === 'out-in') {
10095
resetTracking()
@@ -105,7 +100,16 @@ export class DynamicFragment extends VaporFragment {
105100
}
106101
}
107102

108-
renderNewBranch()
103+
renderBranch()
104+
105+
if (this.fallback && !isValidBlock(this.nodes)) {
106+
parent && remove(this.nodes, parent, this.transition)
107+
this.nodes =
108+
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
109+
[]
110+
parent && insert(this.nodes, parent, this.anchor, this.transition)
111+
}
112+
109113
resetTracking()
110114
}
111115
}
@@ -145,7 +149,8 @@ export function insert(
145149
): void {
146150
anchor = anchor === 0 ? parent.firstChild : anchor
147151
if (block instanceof Node) {
148-
if (transition) {
152+
// don't apply transition on text or comment nodes
153+
if (transition && block instanceof Element) {
149154
applyTransitionEnter(
150155
block,
151156
transition,
@@ -183,7 +188,7 @@ export function remove(
183188
transition: TransitionHooks | undefined = block.transition,
184189
): void {
185190
if (block instanceof Node) {
186-
if (transition) {
191+
if (transition && block instanceof Element) {
187192
applyTransitionLeave(
188193
block,
189194
transition,

packages/runtime-vapor/src/components/Transition.ts

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
leaveCbKey,
1212
registerVaporTransition,
1313
useTransitionState,
14+
warn,
1415
} from '@vue/runtime-dom'
1516
import type { Block } from '../block'
1617
import { 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

143174
function 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

151218
let registered = false

0 commit comments

Comments
 (0)