Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion packages/runtime-vapor/__tests__/helpers/useCssVars.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
setStyle,
template,
useVaporCssVars,
withVaporCtx,
} from '@vue/runtime-vapor'
import { nextTick, onMounted, reactive, ref } from '@vue/runtime-core'
import { makeRender } from '../_utils'
Expand Down Expand Up @@ -209,14 +210,15 @@ describe('useVaporCssVars', () => {
setup() {
useVaporCssVars(() => state)
return createComponent(Child, null, {
default: () =>
default: withVaporCtx(() =>
createComponent(
VaporTeleport,
{ to: () => target },
{
default: () => template('<div></div>', true)(),
},
),
),
})
},
}).render()
Expand All @@ -233,6 +235,63 @@ describe('useVaporCssVars', () => {
}
})

test('with teleport in child slot should keep slot owner css vars across branch switches', async () => {
const parentState = reactive({ parent: 'red' })
const childState = reactive({ child: 'blue' })
const target = document.createElement('div')
document.body.appendChild(target)
const show = ref(true)

const Child = defineVaporComponent({
setup(_, { slots }) {
useVaporCssVars(() => childState)
return slots.default!()
},
})

define({
setup() {
useVaporCssVars(() => parentState)
return createComponent(Child, null, {
default: withVaporCtx(() =>
createComponent(
VaporTeleport,
{ to: () => target },
{
default: () =>
createIf(
() => show.value,
() => template('<div></div>', true)(),
() => template('<span></span>', true)(),
),
},
),
),
})
},
}).render()

await nextTick()
let el = target.children[0] as HTMLElement
expect(el.tagName).toBe('DIV')
expect(el.style.getPropertyValue(`--parent`)).toBe('red')
expect(el.style.getPropertyValue(`--child`)).toBe('')

show.value = false
await nextTick()
el = target.children[0] as HTMLElement
expect(el.tagName).toBe('SPAN')
expect(el.style.getPropertyValue(`--parent`)).toBe('red')
expect(el.style.getPropertyValue(`--child`)).toBe('')

show.value = true
await nextTick()
el = target.children[0] as HTMLElement
expect(el.tagName).toBe('DIV')
expect(el.style.getPropertyValue(`--parent`)).toBe('red')
expect(el.style.getPropertyValue(`--child`)).toBe('')
})

test('with teleport(change subTree)', async () => {
const state = reactive({ color: 'red' })
const target = document.createElement('div')
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-vapor/src/components/Teleport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
MoveType,
type TeleportProps,
type TeleportTargetElement,
currentInstance,
isMismatchAllowed,
isTeleportDeferred,
isTeleportDisabled,
Expand Down Expand Up @@ -40,6 +39,7 @@ import {
setCurrentHydrationNode,
} from '../dom/hydration'
import type { DefineVaporSetupFnComponent } from '../apiDefineComponent'
import { getScopeOwner } from '../componentSlots'

const VaporTeleportImpl = {
name: 'VaporTeleport',
Expand Down Expand Up @@ -76,7 +76,7 @@ export class TeleportFragment extends VaporFragment {
super([])
this.rawProps = props
this.rawSlots = slots
this.parentComponent = currentInstance
this.parentComponent = getScopeOwner()
this.anchor = isHydrating
? undefined
: __DEV__
Expand Down
5 changes: 5 additions & 0 deletions packages/runtime-vapor/src/helpers/useCssVars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import { type VaporComponentInstance, isVaporComponent } from '../component'
import { isArray } from '@vue/shared'
import type { Block } from '../block'
import { isTeleportFragment } from '../components/Teleport'

export function useVaporCssVars(getter: () => Record<string, string>): void {
if (!__BROWSER__ && !__TEST__) return
Expand Down Expand Up @@ -50,6 +51,10 @@ function setVarsOnBlock(block: Block, vars: Record<string, string>): void {
block.forEach(child => setVarsOnBlock(child, vars))
} else if (isVaporComponent(block)) {
setVarsOnBlock(block.block!, vars)
} else if (isTeleportFragment(block)) {
// Teleport children are handled via data-v-owner + ut() to preserve
// lexical owner semantics for slot content.
return
} else {
setVarsOnBlock(block.nodes, vars)
}
Expand Down
Loading