Skip to content

Commit 37349a0

Browse files
committed
feat(config-provider): config-provider adds theme configuration function
1 parent fe9c01c commit 37349a0

File tree

12 files changed

+277
-17
lines changed

12 files changed

+277
-17
lines changed

examples/sites/demos/apis/config-provider.js

+14
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ export default {
3838
},
3939
mode: ['pc'],
4040
pcDemo: 'tag'
41+
},
42+
{
43+
name: 'theme',
44+
type: 'object',
45+
defaultValue: '--',
46+
meta: {
47+
stable: '3.23.0'
48+
},
49+
desc: {
50+
'zh-CN': '自定义主题色,格式:{data:{"tv-base-color-brand":"#595959",....}}',
51+
'en-US': 'Customized theme color, in {data:"tv-base-color-brand":"#595959",....} format.'
52+
},
53+
mode: ['pc'],
54+
pcDemo: 'theme'
4155
}
4256
],
4357
events: [],

examples/sites/demos/apis/tabs.js

+11
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,17 @@ export default {
138138
pcDemo: 'size',
139139
mfDemo: ''
140140
},
141+
{
142+
name: 'swipeable',
143+
type: 'boolean',
144+
defaultValue: 'false',
145+
desc: {
146+
'zh-CN': '是否开启滑动内容切换标签页',
147+
'en-US': 'Do you want to enable the sliding content switching tab function'
148+
},
149+
mode: ['mobile-first'],
150+
mfDemo: 'swipeable'
151+
},
141152
{
142153
name: 'stretch',
143154
type: 'boolean',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<template>
2+
<tiny-tabs v-model="activeName" class="select-none" :optimized="false" swipeable>
3+
<tiny-tab-item title="表单组件" name="first">
4+
<div class="flex w-fit">
5+
<div class="bg-color-bg-1 w-96 h-60 mr-4">
6+
表单组件,具有与用户交互,并可完成数据采集功能的控件。--tab 1 item 1
7+
</div>
8+
<div class="bg-color-bg-2 w-96 h-60 mr-4">
9+
表单组件,具有与用户交互,并可完成数据采集功能的控件。--tab 1 item 2
10+
</div>
11+
<div class="bg-color-bg-3 w-96 h-60 mr-4">
12+
表单组件,具有与用户交互,并可完成数据采集功能的控件。--tab 1 item 3
13+
</div>
14+
<div class="bg-color-bg-4 w-96 h-60 mr-4">
15+
表单组件,具有与用户交互,并可完成数据采集功能的控件。--tab 1 item 4
16+
</div>
17+
<div class="bg-color-bg-5 w-96 h-60 mr-4">
18+
表单组件,具有与用户交互,并可完成数据采集功能的控件。--tab 1 item 5
19+
</div>
20+
</div>
21+
</tiny-tab-item>
22+
<tiny-tab-item title="数据组件" name="second">
23+
<div class="bg-color-bg-6 w-full h-60 mr-4">
24+
数据组件,提供了非常强大数据表格功能,在Grid可以展示数据列表,可以对数据列表进行选择、编辑等。--tab 2
25+
</div>
26+
</tiny-tab-item>
27+
<tiny-tab-item title="导航组件" name="third">
28+
<div class="bg-color-bg-7 w-full h-60 mr-4">导航组件,帮助网站访问者浏览站点的组件。--tab 3</div>
29+
</tiny-tab-item>
30+
<tiny-tab-item title="业务组件" name="fourth">
31+
<div class="bg-color-bg-8 w-full h-60 mr-4">业务组件,与业务紧密相关实现某种业务功能的组件集。--tab 4</div>
32+
</tiny-tab-item>
33+
</tiny-tabs>
34+
</template>
35+
36+
<script>
37+
import { TinyTabs, TinyTabItem } from '@opentiny/vue'
38+
39+
export default {
40+
components: {
41+
TinyTabs,
42+
TinyTabItem
43+
},
44+
data() {
45+
return {
46+
activeName: 'first'
47+
}
48+
}
49+
}
50+
</script>

examples/sites/demos/mobile-first/app/tabs/webdoc/tabs.js

+13
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ export default {
2929
},
3030
codeFiles: ['align-center.vue']
3131
},
32+
{
33+
demoId: 'swipeable',
34+
name: {
35+
'zh-CN': '滑动切换内容',
36+
'en-US': 'Slide to switch content'
37+
},
38+
desc: {
39+
'zh-CN':
40+
'<p>在关闭优化渲染并且所有标签项都不开启延时加载时,可通过 <code>:swipeable=true</code> 开启滑动内容切换标签页。在此模式下,标签项内容区可以是一个水平滚动列表,参考示例中 `表单组件` 标签项。</p>',
41+
'en-US': `<p>When optimizing rendering is turned off and all label items do not enable lazy loading, you can use<code>: swift=true</code>to enable sliding content to switch tabs. In this mode, the tag item content area can be a horizontally scrolling list, as shown in the example of the 'form component' tag item.</p>`
42+
},
43+
codeFiles: ['swipeable.vue']
44+
},
3245
{
3346
demoId: 'tab-style-card',
3447
name: {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<template>
2+
<div>
3+
<tiny-button @click="changeTheme" style="margin-bottom: 20px">改变主题颜色</tiny-button>
4+
<tiny-button type="success" @click="resetTheme" style="margin-bottom: 20px">重置主题颜色</tiny-button>
5+
<tiny-config-provider :theme="theme">
6+
<tiny-button type="primary">主题色按钮</tiny-button>
7+
</tiny-config-provider>
8+
</div>
9+
</template>
10+
11+
<script setup>
12+
import { ref } from 'vue'
13+
import { TinyConfigProvider, TinyButton } from '@opentiny/vue'
14+
15+
const theme = ref({
16+
data: {}
17+
})
18+
19+
function changeTheme() {
20+
theme.value = {
21+
data: {
22+
'tv-base-color-brand': 'green'
23+
}
24+
}
25+
}
26+
27+
function resetTheme() {
28+
theme.value = {
29+
data: {
30+
'tv-base-color-brand': '#191919'
31+
}
32+
}
33+
}
34+
</script>
35+
36+
<style scoped>
37+
.tiny-config-provider {
38+
padding: 1em;
39+
border: 1px solid #ccc;
40+
border-radius: 1em;
41+
}
42+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<template>
2+
<div>
3+
<tiny-button @click="changeTheme" style="margin-bottom: 20px">改变主题颜色</tiny-button>
4+
<tiny-button type="success" @click="resetTheme" style="margin-bottom: 20px">重置主题颜色</tiny-button>
5+
<tiny-config-provider :theme="theme">
6+
<tiny-button type="primary">主题色按钮</tiny-button>
7+
</tiny-config-provider>
8+
</div>
9+
</template>
10+
11+
<script>
12+
import { TinyConfigProvider, TinyButton } from '@opentiny/vue'
13+
14+
export default {
15+
components: {
16+
TinyConfigProvider,
17+
TinyButton
18+
},
19+
data() {
20+
return {
21+
theme: {
22+
data: {}
23+
}
24+
}
25+
},
26+
methods: {
27+
changeTheme() {
28+
this.theme = {
29+
data: {
30+
'tv-base-color-brand': 'green'
31+
}
32+
}
33+
},
34+
resetTheme() {
35+
this.theme = {
36+
data: {
37+
'tv-base-color-brand': '#191919'
38+
}
39+
}
40+
}
41+
}
42+
}
43+
</script>
44+
45+
<style scoped>
46+
.tiny-config-provider {
47+
padding: 1em;
48+
border: 1px solid #ccc;
49+
border-radius: 1em;
50+
}
51+
</style>

examples/sites/demos/pc/app/config-provider/webdoc/config-provider.js

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ export default {
4343
'en-US': 'Container labels can be customized through<code>tag</code>.'
4444
},
4545
codeFiles: ['tag.vue']
46+
},
47+
{
48+
demoId: 'theme',
49+
name: {
50+
'zh-CN': '自定义主题色',
51+
'en-US': 'Custom Colors'
52+
},
53+
desc: {
54+
'zh-CN': '可通过<code>theme</code>属性设置自定义主题色常量。',
55+
'en-US': 'You can use the <code>theme</code> property to set a custom theme color constant.'
56+
},
57+
codeFiles: ['theme.vue']
4658
}
4759
],
4860
features: [
+4-15
Loading

packages/utils/src/common/index.ts

+24
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,27 @@ export const CASCADER: Record<string, any> = {
308308
PropsHover: 'hoverThreshold',
309309
MenuConnector: 'cascader-menu-'
310310
}
311+
312+
/**
313+
* 检查对象是否具有任何一个指定的键
314+
* @param obj 需要检查的对象
315+
* @param keys 需要检查的键的数组
316+
* @return 如果对象具有任何一个指定的键,返回true,否则返回false
317+
*/
318+
export const hasAnyKey = (obj: any, keys: string[]): boolean => {
319+
if (obj == null) {
320+
return false
321+
}
322+
323+
if (keys.length === 0) {
324+
return false
325+
}
326+
327+
for (const key of keys) {
328+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
329+
return true
330+
}
331+
}
332+
333+
return false
334+
}

packages/vue/src/config-provider/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
},
1616
"dependencies": {
1717
"@opentiny/vue-common": "workspace:~",
18-
"@opentiny/vue-theme": "workspace:~"
18+
"@opentiny/vue-theme": "workspace:~",
19+
"@opentiny/utils": "workspace:~"
1920
},
2021
"license": "MIT"
2122
}

packages/vue/src/config-provider/src/index.vue

+53-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,32 @@ import type { PropType } from '@opentiny/vue-common'
44
import type { Tag, TextDirection, breakPoint } from './props'
55
import { configProviderContextKey } from '../index'
66
import '@opentiny/vue-theme/config-provider/index.less'
7+
import TinyThemeTool from '@opentiny/vue-theme/theme-tool'
8+
import { isObject } from '@opentiny/utils'
9+
10+
/**
11+
* 检查对象是否具有任何一个指定的键
12+
* @param obj 需要检查的对象
13+
* @param keys 需要检查的键的数组
14+
* @return 如果对象具有任何一个指定的键,返回true,否则返回false
15+
*/
16+
const hasAnyKey = (obj: any, keys: string[]): boolean => {
17+
if (obj == null) {
18+
return false
19+
}
20+
21+
if (keys.length === 0) {
22+
return false
23+
}
24+
25+
for (const key of keys) {
26+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
27+
return true
28+
}
29+
}
30+
31+
return false
32+
}
733
834
export default defineComponent({
935
name: $prefix + 'ConfigProvider',
@@ -42,6 +68,12 @@ export default defineComponent({
4268
}
4369
}
4470
},
71+
theme: {
72+
type: Object,
73+
default: () => {
74+
return null
75+
}
76+
},
4577
..._props
4678
.map((item) => {
4779
return {
@@ -58,8 +90,28 @@ export default defineComponent({
5890
})
5991
},
6092
setup(props, { slots }) {
61-
const { direction, design } = hooks.toRefs(props)
93+
const { direction, design, theme } = hooks.toRefs(props)
6294
provideDesignConfig(design)
95+
hooks.watch(
96+
() => theme.value,
97+
() => {
98+
if (isObject(theme.value) && hasAnyKey(theme.value, ['data'])) {
99+
const themeTool = new TinyThemeTool()
100+
themeTool.changeTheme(theme.value)
101+
}
102+
103+
if (isObject(theme.value) && !hasAnyKey(theme.value, ['data'])) {
104+
console.warn(`configProvider组件的theme属性对象请配置data属性。e.g { data: {'tv-base-color-brand': '#000'}}`)
105+
}
106+
107+
if (theme.value && !isObject(theme.value)) {
108+
console.warn(`configProvider组件的theme属性请配置对象格式数据`)
109+
}
110+
},
111+
{
112+
immediate: true
113+
}
114+
)
63115
const isRTL = hooks.computed(() => direction.value === 'rtl')
64116
const cssVar = hooks.computed(() => {
65117
return {

packages/vue/src/config-provider/src/props.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ export interface ConfigProviderProps {
2020
enable?: boolean
2121
name?: string
2222
}
23+
theme?: Object | null
2324
}

0 commit comments

Comments
 (0)