import { useCssVars as _useCssVars } from 'vue'
const __injectCSSVars__ = () => {
_useCssVars(_ctx => ({
- color: (_ctx.color)
-}), \\"xxxxxxxx\\")}
+ \\"xxxxxxxx-color\\": (_ctx.color)
+}))}
const __setup__ = __default__.setup
__default__.setup = __setup__
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
import { useCssVars as _useCssVars } from 'vue'
const __injectCSSVars__ = () => {
_useCssVars(_ctx => ({
- color: (_ctx.color)
-}), \\"xxxxxxxx\\")}
+ \\"xxxxxxxx-color\\": (_ctx.color)
+}))}
const __setup__ = __default__.setup
__default__.setup = __setup__
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
import { useCssVars as _useCssVars } from 'vue'
const __injectCSSVars__ = () => {
_useCssVars(_ctx => ({
- color: (_ctx.color)
-}), \\"xxxxxxxx\\")}
+ \\"xxxxxxxx-color\\": (_ctx.color)
+}))}
const __setup__ = __default__.setup
__default__.setup = __setup__
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
setup(__props) {
_useCssVars(_ctx => ({
- color: (color)
-}), \\"xxxxxxxx\\")
+ \\"xxxxxxxx-color\\": (color)
+}))
const color = 'red'
return { color }
}
import { useCssVars as _useCssVars } from 'vue'
const __injectCSSVars__ = () => {
_useCssVars(_ctx => ({
- color: (_ctx.color),
- font_size: (_ctx.font.size)
-}), \\"xxxxxxxx\\")}
+ \\"xxxxxxxx-color\\": (_ctx.color),
+ \\"xxxxxxxx-font_size\\": (_ctx.font.size)
+}))}
const __setup__ = __default__.setup
__default__.setup = __setup__
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
setup(__props) {
_useCssVars(_ctx => ({
- color: (color),
- size: (_unref(size)),
- foo: (__props.foo)
-}), \\"xxxxxxxx\\")
+ \\"xxxxxxxx-color\\": (color),
+ \\"xxxxxxxx-size\\": (_unref(size)),
+ \\"xxxxxxxx-foo\\": (__props.foo)
+}))
const color = 'red'
const size = ref('10px')
import { compileStyle } from '../src'
-import { compileSFCScript, assertCode } from './utils'
+import { mockId, compileSFCScript, assertCode } from './utils'
describe('CSS vars injection', () => {
test('generating correct code for nested paths', () => {
}</style>`
)
expect(content).toMatch(`_useCssVars(_ctx => ({
- color: (_ctx.color),
- font_size: (_ctx.font.size)
+ "${mockId}-color": (_ctx.color),
+ "${mockId}-font_size": (_ctx.font.size)
})`)
assertCode(content)
})
// 2. local potential ref bindings
// 3. props bindings (analyzed)
expect(content).toMatch(`_useCssVars(_ctx => ({
- color: (color),
- size: (_unref(size)),
- foo: (__props.foo)
+ "${mockId}-color": (color),
+ "${mockId}-size": (_unref(size)),
+ "${mockId}-foo": (__props.foo)
})`)
expect(content).toMatch(
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
import { parse as babelParse } from '@babel/parser'
import { babelParserDefaultPlugins } from '@vue/shared'
+export const mockId = 'xxxxxxxx'
+
export function compileSFCScript(
src: string,
options?: Partial<SFCScriptCompileOptions>
const { descriptor } = parse(src)
return compileScript(descriptor, {
...options,
- id: 'xxxxxxxx'
+ id: mockId
})
}
id: string
) {
const varsExp = `{\n ${vars
- .map(v => `${convertCssVarCasing(v)}: (${v})`)
+ .map(v => `"${id}-${convertCssVarCasing(v)}": (${v})`)
.join(',\n ')}\n}`
const exp = createSimpleExpression(varsExp, false)
const context = createTransformContext(createRoot([]), {
})
.join('')
- return `_${CSS_VARS_HELPER}(_ctx => (${transformedString}), "${id}")`
+ return `_${CSS_VARS_HELPER}(_ctx => (${transformedString}))`
}
// <script setup> already gets the calls injected as part of the transform
} from '@vue/runtime-dom'
describe('useCssVars', () => {
- const id = 'xxxxxx'
async function assertCssVars(getApp: (state: any) => ComponentOptions) {
const state = reactive({ color: 'red' })
const App = getApp(state)
render(h(App), root)
await nextTick()
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- `red`
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
}
state.color = 'green'
await nextTick()
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- 'green'
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')
}
}
await assertCssVars(state => ({
setup() {
// test receiving render context
- useCssVars(
- (ctx: any) => ({
- color: ctx.color
- }),
- id
- )
+ useCssVars((ctx: any) => ({
+ color: ctx.color
+ }))
return state
},
render() {
test('on fragment root', async () => {
await assertCssVars(state => ({
setup() {
- useCssVars(() => state, id)
+ useCssVars(() => state)
return () => [h('div'), h('div')]
}
}))
await assertCssVars(state => ({
setup() {
- useCssVars(() => state, id)
+ useCssVars(() => state)
return () => h(Child)
}
}))
const App = {
setup() {
- useCssVars(() => state, id)
+ useCssVars(() => state)
return () =>
h(Suspense, null, {
default: h(AsyncComp),
await nextTick()
// css vars use with fallback tree
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- `red`
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
}
// AsyncComp resolve
resolveAsync()
await nextTick()
// css vars use with default tree
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- `red`
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
}
state.color = 'green'
await nextTick()
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- 'green'
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')
}
})
- test('with <style scoped>', async () => {
- await assertCssVars(state => ({
- __scopeId: id,
- setup() {
- useCssVars(() => state, id)
- return () => h('div')
- }
- }))
- })
-
test('with subTree changed', async () => {
const state = reactive({ color: 'red' })
const value = ref(true)
const App = {
setup() {
- useCssVars(() => state, id)
+ useCssVars(() => state)
return () => (value.value ? [h('div')] : [h('div'), h('div')])
}
}
await nextTick()
// css vars use with fallback tree
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- `red`
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
}
value.value = false
await nextTick()
for (const c of [].slice.call(root.children as any)) {
- expect((c as HTMLElement).style.getPropertyValue(`--${id}-color`)).toBe(
- 'red'
- )
+ expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
}
})
})
* @private
*/
export function useCssVars(
- getter: (ctx: ComponentPublicInstance) => Record<string, string>,
- scopeId: string
+ getter: (ctx: ComponentPublicInstance) => Record<string, string>
) {
const instance = getCurrentInstance()
/* istanbul ignore next */
}
const setVars = () =>
- setVarsOnVNode(instance.subTree, getter(instance.proxy!), scopeId)
+ setVarsOnVNode(instance.subTree, getter(instance.proxy!))
onMounted(() => watchEffect(setVars, { flush: 'post' }))
onUpdated(setVars)
}
-function setVarsOnVNode(
- vnode: VNode,
- vars: Record<string, string>,
- scopeId: string
-) {
+function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
if (__FEATURE_SUSPENSE__ && vnode.shapeFlag & ShapeFlags.SUSPENSE) {
const suspense = vnode.suspense!
vnode = suspense.activeBranch!
if (suspense.pendingBranch && !suspense.isHydrating) {
suspense.effects.push(() => {
- setVarsOnVNode(suspense.activeBranch!, vars, scopeId)
+ setVarsOnVNode(suspense.activeBranch!, vars)
})
}
}
if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {
const style = vnode.el.style
for (const key in vars) {
- style.setProperty(`--${scopeId}-${key}`, vars[key])
+ style.setProperty(`--${key}`, vars[key])
}
} else if (vnode.type === Fragment) {
- ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars, scopeId))
+ ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars))
}
}