Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(runtime-vapor): use css vars work with vapor mode #12621

Open
wants to merge 4 commits into
base: vapor
Choose a base branch
from
Open
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
5 changes: 3 additions & 2 deletions packages/compiler-sfc/src/compileScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
normalScriptDefaultVar,
processNormalScript,
} from './script/normalScript'
import { CSS_VARS_HELPER, genCssVarsCode } from './style/cssVars'
import { genCssVarsCode, getCssVarsHelper } from './style/cssVars'
import {
type SFCTemplateCompileOptions,
compileTemplate,
Expand Down Expand Up @@ -759,7 +759,7 @@ export function compileScript(
// no need to do this when targeting SSR
!options.templateOptions?.ssr
) {
ctx.helperImports.add(CSS_VARS_HELPER)
ctx.helperImports.add(getCssVarsHelper(vapor))
ctx.helperImports.add('unref')
ctx.s.prependLeft(
startOffset,
Expand All @@ -768,6 +768,7 @@ export function compileScript(
ctx.bindingMetadata,
scopeId,
!!options.isProd,
vapor,
)}\n`,
)
}
Expand Down
9 changes: 7 additions & 2 deletions packages/compiler-sfc/src/style/cssVars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import {
import type { SFCDescriptor } from '../parse'
import type { PluginCreator } from 'postcss'
import hash from 'hash-sum'
import { getEscapedCssVarName } from '@vue/shared'
import { capitalize, getEscapedCssVarName } from '@vue/shared'

export const CSS_VARS_HELPER = `useCssVars`

export function getCssVarsHelper(vapor: boolean | undefined): string {
return vapor ? `vapor${capitalize(CSS_VARS_HELPER)}` : CSS_VARS_HELPER
}

export function genCssVarsFromList(
vars: string[],
id: string,
Expand Down Expand Up @@ -162,6 +166,7 @@ export function genCssVarsCode(
bindings: BindingMetadata,
id: string,
isProd: boolean,
vapor?: boolean,
) {
const varsExp = genCssVarsFromList(vars, id, isProd)
const exp = createSimpleExpression(varsExp, false)
Expand All @@ -182,7 +187,7 @@ export function genCssVarsCode(
})
.join('')

return `_${CSS_VARS_HELPER}(_ctx => (${transformedString}))`
return `_${getCssVarsHelper(vapor)}(_ctx => (${transformedString}))`
}

// <script setup> already gets the calls injected as part of the transform
Expand Down
24 changes: 11 additions & 13 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,17 @@ export interface GenericComponentInstance {
* @internal
*/
suspense: SuspenseBoundary | null
/**
* `updateTeleportCssVars`
* For updating css vars on contained teleports
* @internal
*/
ut?: (vars?: Record<string, string>) => void
/**
* dev only. For style v-bind hydration mismatch checks
* @internal
*/
getCssVars?: () => Record<string, string>

// lifecycle
/**
Expand Down Expand Up @@ -651,19 +662,6 @@ export interface ComponentInternalInstance extends GenericComponentInstance {
* @internal
*/
n?: () => Promise<void>
/**
* `updateTeleportCssVars`
* For updating css vars on contained teleports
* @internal
*/
ut?: (vars?: Record<string, string>) => void

/**
* dev only. For style v-bind hydration mismatch checks
* @internal
*/
getCssVars?: () => Record<string, string>

/**
* v2 compat only, for caching mutated $options
* @internal
Expand Down
92 changes: 56 additions & 36 deletions packages/runtime-dom/src/helpers/useCssVars.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Fragment,
type GenericComponentInstance,
Static,
type VNode,
getCurrentInstance,
Expand All @@ -20,48 +21,22 @@ export const CSS_VAR_TEXT: unique symbol = Symbol(__DEV__ ? 'CSS_VAR_TEXT' : '')
export function useCssVars(getter: (ctx: any) => Record<string, string>): void {
if (!__BROWSER__ && !__TEST__) return

const instance = getCurrentInstance()
/* v8 ignore start */
if (!instance) {
__DEV__ &&
warn(`useCssVars is called without current active component instance.`)
return
}
/* v8 ignore stop */

const updateTeleports = (instance.ut = (vars = getter(instance.proxy)) => {
Array.from(
document.querySelectorAll(`[data-v-owner="${instance.uid}"]`),
).forEach(node => setVarsOnNode(node, vars))
})

if (__DEV__) {
instance.getCssVars = () => getter(instance.proxy)
}

const setVars = () => {
const vars = getter(instance.proxy)
const instance = getCurrentInstance()! // to be check in baseUseCssVars
const getVars = () => getter(instance.proxy)
const setVars = (vars: Record<string, any>) => {
if (instance.ce) {
setVarsOnNode(instance.ce as any, vars)
} else {
setVarsOnVNode(instance.subTree, vars)
}
updateTeleports(vars)
}

// handle cases where child component root is affected
// and triggers reflow in onMounted
onBeforeUpdate(() => {
queuePostFlushCb(setVars)
})

onMounted(() => {
// run setVars synchronously here, but run as post-effect on changes
watch(setVars, NOOP, { flush: 'post' })
const ob = new MutationObserver(setVars)
ob.observe(instance.subTree.el!.parentNode, { childList: true })
onUnmounted(() => ob.disconnect())
})
baseUseCssVars(
instance,
() => instance.subTree.el!.parentNode!,
getVars,
setVars,
)
}

function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
Expand Down Expand Up @@ -94,7 +69,52 @@ function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
}
}

function setVarsOnNode(el: Node, vars: Record<string, string>) {
export function baseUseCssVars(
instance: GenericComponentInstance | null,
getParentNode: () => Node,
getVars: () => Record<string, any>,
setVars: (vars: Record<string, any>) => void,
): void {
/* v8 ignore start */
if (!instance) {
__DEV__ &&
warn(`useCssVars is called without current active component instance.`)
return
}
/* v8 ignore stop */

if (__DEV__) {
instance.getCssVars = () => getVars()
}

const updateTeleports = (instance.ut = (vars = getVars()) => {
Array.from(
document.querySelectorAll(`[data-v-owner="${instance.uid}"]`),
).forEach(node => setVarsOnNode(node, vars))
})

const applyCssCars = () => {
const vars = getVars()
setVars(vars)
updateTeleports(vars)
}

// handle cases where child component root is affected
// and triggers reflow in onMounted
onBeforeUpdate(() => {
queuePostFlushCb(applyCssCars)
})

onMounted(() => {
// run setVars synchronously here, but run as post-effect on changes
watch(applyCssCars, NOOP, { flush: 'post' })
const ob = new MutationObserver(applyCssCars)
ob.observe(getParentNode(), { childList: true })
onUnmounted(() => ob.disconnect())
})
}

export function setVarsOnNode(el: Node, vars: Record<string, string>): void {
if (el.nodeType === 1) {
const style = (el as HTMLElement).style
let cssText = ''
Expand Down
4 changes: 4 additions & 0 deletions packages/runtime-dom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,7 @@ export { patchStyle } from './modules/style'
* @internal
*/
export { shouldSetAsProp } from './patchProp'
/**
* @internal
*/
export { baseUseCssVars, setVarsOnNode } from './helpers/useCssVars'
Loading
Loading