Skip to content

Commit

Permalink
feat: config-provider (opentiny#271)
Browse files Browse the repository at this point in the history
* feat: config-provider

* 🐞 fix(config-provider):

开发者如果只覆盖某个design item 那么其他的常量会被覆盖为 undefined. commit主要修复该问题

* 🧪 test(config-provider): 补充单元测试

* 🐞 fix(config-provider): 修改检视意见
  • Loading branch information
GaoNeng-wWw authored Jun 8, 2023
1 parent 6b1d103 commit 77b68be
Show file tree
Hide file tree
Showing 13 changed files with 483 additions and 10 deletions.
32 changes: 32 additions & 0 deletions examples/docs/resources/pc/api/zh-CN/config-provider.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"attrs": [
{
"name": "design",
"sample": "base",
"desc": "规范",
"type": "ConfigProviderProps",
"defaultValue": ""
},
{
"name": "breakPoints",
"sample": "base",
"desc": "断点, 为Layout提供",
"type": "breakPoint",
"defaultValue": "{'xs': 480,'sm': 640,'md': 768,'lg': 1024,'xl': 1280,'2xl': 1536}"
},
{
"name": "direction",
"sample": "text-dire",
"desc": "文字排版方向",
"type": "'ltr' | 'rtl'",
"defaultValue": "ltr"
},
{
"name": "tag",
"type": "object",
"desc": "是否被元素包裹, 如果是vue2且没有一个单一节点, 组件会自动创建一个div",
"sample": "base",
"defaultValue": "{enable: true,name: 'div'}"
}
]
}
18 changes: 18 additions & 0 deletions examples/docs/resources/pc/demo-config/zh-CN/config-provider.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"title": "基本使用",
"content": "如何使用ConfigProvider组件",
"link": "config-provider/base",
"component": " ConfigProvide 组件",
"findIntroStr": "",
"demoId": "base"
},
{
"title": "改变文字方向",
"content": "有时, 我们需要改变文字的排列方向, 例如我们在排列阿拉伯语是就需要RTL而非LTR.config-provider也考虑到了这点,只需要覆写design.direction即可",
"link": "config-provider/text-direct",
"component": " ConfigProvide 组件",
"findIntroStr": "",
"demoId": "text-direct"
}
]
48 changes: 48 additions & 0 deletions examples/docs/resources/pc/demo/config-provider/base.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<div>
<tiny-config-provider :tag="tag">
<tiny-tag>这是一个Tag</tiny-tag>
<tiny-tag>{{ tagEnable }}</tiny-tag>
</tiny-config-provider>
<br />
<div :style="[tag.enable && 'padding: 0px 1em;']">
<tiny-switch v-model="tag.enable" />
</div>
</div>
</template>

<script>
import { ConfigProvider, Tag, Switch } from '@opentiny/vue'
export default {
components: {
TinyConfigProvider: ConfigProvider,
TinyTag: Tag,
TinySwitch: Switch
},
data() {
return {
tag: {
enable: true,
name: 'div'
}
}
},
computed: {
tagEnable() {
return this.tag.enable ? '被DOM包裹' : '没有被DOM包裹'
}
}
}
</script>

<style scoped>
.tiny-config-provider{
padding: 1em;
border: 1px solid #ccc;
border-radius: 1em;
}
.tiny-tag {
margin-right: 10px;
}
</style>
125 changes: 125 additions & 0 deletions examples/docs/resources/pc/demo/config-provider/text-direct.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<template>
<div>
<tiny-config-provider :direction="direction">
<h1>Text</h1>
<h1>المعرفة نور والجهل ظلام</h1>
<div>
<span>ما هو مكتوب في الكتب هو مجرد كلمات ، وما يتم تذكره هو المعرفة</span>
</div>
<hr />
<h1>Input</h1>
<tiny-input v-model="input" placeholder="الرجاء إدخال المحتوى"></tiny-input>
<h1>Container</h1>
<div class="content">
<tiny-layout>
<tiny-row>
<tiny-col :span="12">
<div class="col">
span 12
</div>
</tiny-col>
</tiny-row>
<tiny-row>
<tiny-col :span="3">
<div class="col">
span 3
</div>
</tiny-col>
<tiny-col :span="6">
<div class="col">
span 6
</div>
</tiny-col>
<tiny-col :span="3">
<div class="col">
span 3
</div>
</tiny-col>
</tiny-row>
<tiny-row>
<tiny-col :span="2">
<div class="col">
span 2
</div>
</tiny-col>
<tiny-col :span="3">
<div class="col">
span 3
</div>
</tiny-col>
<tiny-col :span="2">
<div class="col">
span 2
</div>
</tiny-col>
<tiny-col :span="3">
<div class="col">
span 3
</div>
</tiny-col>
<tiny-col :span="2">
<div class="col">
span 2
</div>
</tiny-col>
</tiny-row>
</tiny-layout>
</div>
</tiny-config-provider>

<tiny-button @click="changeDirect('rtl')">
RTL
</tiny-button>
<tiny-button @click="changeDirect('ltr')">
LTR
</tiny-button>
</div>
</template>

<script>
import { ConfigProvider, Button, Input, Layout, Row, Col } from '@opentiny/vue'
export default {
components: {
TinyConfigProvider: ConfigProvider,
TinyButton: Button,
TinyInput: Input,
TinyLayout: Layout,
TinyRow: Row,
TinyCol: Col
},
data() {
return {
direction: 'ltr',
input: ''
}
},
methods: {
changeDirect(direct) {
this.direction = direct
}
}
}
</script>

<style scoped>
.content .tiny-row {
margin-bottom: 20px;
}
.content .tiny-row .last-child {
margin-bottom: 0;
}
.content .tiny-col .col {
line-height: 30px;
text-align: center;
color: #fff;
background: #1f9ed8;
border-radius: 15px;
}
.content .tiny-col:nth-child(even) .col {
background: #73d0fc;
}
</style>
6 changes: 6 additions & 0 deletions examples/docs/resources/pc/menus.js
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,12 @@ const routerArr = [
zh: '全屏显示',
enSuffix: true,
path: '/fullscreen'
},
{
en: 'ConfigProvider',
zh: '全局设置',
enSuffix: true,
path: '/config-provider'
}
]
}
Expand Down
15 changes: 15 additions & 0 deletions packages/theme/src/config-provider/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/

export default {
// Config-Provider
}
12 changes: 12 additions & 0 deletions packages/theme/src/config-provider/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/

12 changes: 12 additions & 0 deletions packages/theme/src/config-provider/vars.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/

92 changes: 92 additions & 0 deletions packages/vue/src/config-provider/__tests__/config-provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { mountPcMode } from '@opentiny-internal/vue-test-utils'
import { describe, test, expect } from 'vitest'
import ConfigProvider, { configProviderContextKey } from '@opentiny/vue-config-provider'
import { defineComponent, h, inject } from 'vue'
import type { ConfigProviderProps } from '../src/props'
import { isVue2 } from '@opentiny/vue-common'

describe('PC Mode', () => {
const mount = mountPcMode
test('rtl', () => {
const wrapper = mount(ConfigProvider, {
props: {
direction: 'rtl'
}
})
expect(wrapper.classes()).toContain('tiny-config-provider--rtl')
})
describe('tag', () => {
test('no tag', () => {
const wrapper = mount(ConfigProvider, {
props: {
tag: {
enable: false,
}
},
slots: {
default: ['<button>just button</button>'],
}
})
expect(wrapper.html()).not.contain('div')
})
test('has tag but not div', () => {
const wrapper = mount(ConfigProvider, {
props: {
tag: {
enable: true,
name: 'custom-el'
}
}
})
const html = wrapper.html()
expect(html).contain('custom-el')
expect(html).not.contain('div')
})
test('mutil node', () => {
const wrapper = mount(ConfigProvider, {
props: {
tag: {
enable: false
}
},
slots: {
default: ['<button>btn1</button>', '<button>btn2</button>']
}
})
if (isVue2) {
expect(wrapper.html()).contain('div')
expect(wrapper.classes().length).toBe(0)
} else {
expect(wrapper.html()).not.contain('div')
}
})
})
if (!isVue2) {
describe('inject', () => {
test('one layer', () => {
let component
if (!isVue2) {
component = defineComponent({
name: 'CustomComponent',
setup() {
const config = inject<ConfigProviderProps>(configProviderContextKey)
expect(config).not.toBeNull()
expect(config).not.toStrictEqual({})
expect(config?.direction).not.toBe('ltr')
// just fix Component is missing template or render function.
return () => h('div')
}
})
}
mount(ConfigProvider, {
slots: {
default: [component]
},
props: {
direction: 'rtl'
}
})
})
})
}
})
7 changes: 7 additions & 0 deletions packages/vue/src/config-provider/hooks/use-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ConfigProviderProps } from '../src/props'
import { configProviderContextKey } from '../index'
import { hooks } from '@opentiny/vue-common/src'

export function useConfig(): ConfigProviderProps | {} {
return hooks.inject(configProviderContextKey) ?? {}
}
2 changes: 2 additions & 0 deletions packages/vue/src/config-provider/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ConfigProvider from './src/index.vue'
import { version } from './package.json'

export const configProviderContextKey = Symbol('CONFIG_PROVIDER_CONTEXT_KEY')

/* istanbul ignore next */
ConfigProvider.install = function (Vue) {
Vue.component(ConfigProvider.name, ConfigProvider)
Expand Down
Loading

0 comments on commit 77b68be

Please sign in to comment.