Skip to content

Commit 7ef63d9

Browse files
committed
feat(theme): support embed theme provider and passing a function to theme prop
1 parent 122e854 commit 7ef63d9

File tree

4 files changed

+62
-29
lines changed

4 files changed

+62
-29
lines changed

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"provenance": true
4444
},
4545
"devDependencies": {
46+
"@types/lodash-es": "^4.17.12",
4647
"@types/stylis": "^4.2.6"
4748
},
4849
"dependencies": {

packages/core/src/providers/theme.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
import { defineComponent, h, PropType, provide, reactive, ref, watch } from 'vue'
1+
import { defineComponent, h, PropType, provide, reactive, inject, watch } from 'vue'
2+
import { assign, cloneDeep } from 'lodash-es'
23

34
export interface DefaultTheme {
45
[key: string]: any
56
}
67

78
export const ThemeProvider = defineComponent(
89
(props, { slots }) => {
9-
const theme = ref(props.theme)
10-
provide('$theme', reactive(theme.value as DefaultTheme))
10+
const parentTheme = inject<DefaultTheme>('$theme', reactive({}))
11+
const mergeTheme = (cur: DefaultTheme) => {
12+
return typeof props.theme === 'function' ? props.theme(cloneDeep(cur)) : props.theme
13+
}
14+
15+
const reactiveTheme = reactive(mergeTheme(parentTheme))
16+
17+
provide<DefaultTheme>('$theme', reactive(reactiveTheme))
1118

1219
watch(
13-
() => props.theme,
20+
parentTheme,
1421
(v) => {
15-
theme.value = v
16-
},
17-
{
18-
deep: true,
22+
assign(reactiveTheme, mergeTheme(v))
1923
},
24+
{ deep: true, immediate: true },
2025
)
2126

2227
return () => {
@@ -27,9 +32,8 @@ export const ThemeProvider = defineComponent(
2732
name: 'ThemeProvider',
2833
props: {
2934
theme: {
30-
type: Object as PropType<DefaultTheme>,
35+
type: [Object, Function] as PropType<DefaultTheme | ((theme: DefaultTheme) => DefaultTheme)>,
3136
required: true,
32-
default: () => {},
3337
},
3438
},
3539
},

packages/playground/src/App.vue

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
11
<script setup lang="ts">
2-
import styled from '@vue-styled-components/core'
2+
import styled, { ThemeProvider } from '@vue-styled-components/core'
3+
import { reactive } from 'vue'
34
4-
const Test = styled('div', { color: String }).attrs<{ disabled: boolean }>({ disabled: false })`
5-
color: ${(props) => props.color};
6-
background: ${(props) => (props.disabled ? 'gray' : 'red')};
7-
`
8-
const Test2 = styled('div', { color: String }).attrs<{ disabled: boolean }>((props) => ({
9-
disabled: props.color === 'orange',
10-
}))`
11-
color: ${(props) => props.color};
12-
background: ${(props) => (props.disabled ? 'gray' : 'red')};
5+
const Button = styled.button`
6+
color: ${(props) => props.theme.fg};
7+
background: ${(props) => props.theme.bg};
138
`
9+
10+
const theme = reactive({
11+
fg: 'red',
12+
bg: 'blue',
13+
})
14+
15+
const changeTheme = () => {
16+
if (theme.fg === 'red') {
17+
theme.fg = 'blue'
18+
theme.bg = 'red'
19+
} else {
20+
theme.fg = 'red'
21+
theme.bg = 'blue'
22+
}
23+
}
1424
</script>
1525

1626
<template>
17-
<Test color="orange">666</Test>
18-
<Test2 color="orange">666</Test2>
27+
<ThemeProvider :theme="theme">
28+
<Button @click="changeTheme">666</Button>
29+
<ThemeProvider
30+
:theme="
31+
(t) => {
32+
return { fg: t.bg, bg: t.fg, aa: 2111 }
33+
}
34+
"
35+
>
36+
<Button>777</Button>
37+
</ThemeProvider>
38+
</ThemeProvider>
1939
</template>
2040

2141
<style>

pnpm-lock.yaml

Lines changed: 15 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)