} from './components/BaseTransition'
// For using custom directives
export { withDirectives } from './directives'
-// SFC CSS Modules
-export { useCSSModule } from './helpers/useCssModule'
// SSR context
export { useSSRContext, ssrContextKey } from './helpers/useSsrContext'
-import { getCurrentInstance } from '../component'
+import { warn, getCurrentInstance } from '@vue/runtime-core'
import { EMPTY_OBJ } from '@vue/shared'
-import { warn } from '../warning'
-export const useCSSModule = (name = '$style'): Record<string, string> => {
+export function useCSSModule(name = '$style'): Record<string, string> {
if (!__GLOBAL__) {
const instance = getCurrentInstance()!
if (!instance) {
--- /dev/null
+import {
+ ComponentPublicInstance,
+ getCurrentInstance,
+ onMounted,
+ watchEffect,
+ warn,
+ VNode,
+ Fragment
+} from '@vue/runtime-core'
+import { ShapeFlags } from '@vue/shared/src'
+
+export function useCSSVars(
+ getter: (ctx: ComponentPublicInstance) => Record<string, string>
+) {
+ const instance = getCurrentInstance()
+ if (!instance) {
+ __DEV__ &&
+ warn(`useCssVars is called without current active component instance.`)
+ return
+ }
+ onMounted(() => {
+ watchEffect(() => {
+ setVarsOnVNode(instance.vnode, getter(instance.proxy!))
+ })
+ })
+}
+
+function setVarsOnVNode(vnode: VNode, vars: Record<string, string>) {
+ // drill down HOCs until it's a non-component vnode
+ while (vnode.component) {
+ vnode = vnode.component.subTree
+ }
+ if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {
+ const style = vnode.el.style
+ for (const key in vars) {
+ style.setProperty(`--${key}`, vars[key])
+ }
+ } else if (vnode.type === Fragment) {
+ ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars))
+ }
+}
return container
}
+// SFC CSS utilities
+export { useCSSModule } from './helpers/useCssModule'
+export { useCSSVars } from './helpers/useCssVars'
+
// DOM-only components
export { Transition, TransitionProps } from './components/Transition'
export {