refactor(components): [el-config-provider] improve componomponent extendiability (#4175)

re #4146

added button configuration
added useGlobalConfig hook
This commit is contained in:
msidolphin 2021-11-05 18:10:07 +08:00 committed by GitHub
parent cf27504bdc
commit 66043aa3b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 168 additions and 46 deletions

View File

@ -77,18 +77,19 @@ button/size
## Button Attributes
| Attribute | Description | Type | Accepted Values | Default |
| ----------- | -------------------------------------- | ------------------ | -------------------------------------------------- | ------- |
| size | button size | string | medium / small / mini | — |
| type | button type | string | primary / success / warning / danger / info / text | — |
| plain | determine whether it's a plain button | boolean | — | false |
| round | determine whether it's a round button | boolean | — | false |
| circle | determine whether it's a circle button | boolean | — | false |
| loading | determine whether it's loading | boolean | — | false |
| disabled | disable the button | boolean | — | false |
| icon | icon component | string / Component | — | — |
| autofocus | same as native button's `autofocus` | boolean | — | false |
| native-type | same as native button's `type` | string | button / submit / reset | button |
| Attribute | Description | Type | Accepted Values | Default |
| ----------------- | ----------------------------------------------------------- | ------------------ | -------------------------------------------------- | ------- |
| size | button size | string | medium / small / mini | — |
| type | button type | string | primary / success / warning / danger / info / text | — |
| plain | determine whether it's a plain button | boolean | — | false |
| round | determine whether it's a round button | boolean | — | false |
| circle | determine whether it's a circle button | boolean | — | false |
| loading | determine whether it's loading | boolean | — | false |
| disabled | disable the button | boolean | — | false |
| icon | icon component | string / Component | — | — |
| autofocus | same as native button's `autofocus` | boolean | — | false |
| native-type | same as native button's `type` | string | button / submit / reset | button |
| auto-insert-space | automatically insert a space between two chinese characters | boolean | | — |
## Button Slots

View File

@ -17,12 +17,27 @@ config-provider/usage
:::
## button configurations
:::demo Use two attributes to provide i18n related config
config-provider/button
:::
## Config Provider Attributes
| Attribute | Description | Type | Accepted Values | Default |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------- | ------- |
| locale | Locale Object | Object\<Language\> | [languages](https://github.com/element-plus/element-plus/tree/dev/packages/locale/lang) | English |
| i18n | External translator, when this attribute is provided, it will be used at first, and it will fallback to default translator when this method returns nullish value | Function\<(...args: []) =\> string\> | - | - |
| Attribute | Description | Type | Accepted Values | Default |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------- | ----------------------- |
| locale | Locale Object | Object\<Language\> | [languages](https://github.com/element-plus/element-plus/tree/dev/packages/locale/lang) | English |
| i18n | External translator, when this attribute is provided, it will be used at first, and it will fallback to default translator when this method returns nullish value | Function\<(...args: []) =\> string\> | - | - |
| button | button related configuration, [see the following table](#button-attributes) | ButtonGlobalConfig | - | see the following table |
### Button Attributes
| Attribute | Description | Type | Accepted Values | Default |
| --------------- | ----------------------------------------------------------- | ------- | --------------- | ------- |
| autoInsertSpace | automatically insert a space between two chinese characters | boolean | - | true |
## ConfigProvider Slots

View File

@ -0,0 +1,28 @@
<template>
<div>
<el-config-provider :button="config">
<el-button>中文</el-button>
</el-config-provider>
<div>
<el-checkbox v-model="config.autoInsertSpace"
>autoInsertSpace</el-checkbox
>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue'
export default defineComponent({
setup() {
const config = reactive({
autoInsertSpace: true,
})
return {
config,
}
},
})
</script>

View File

@ -1,6 +1,5 @@
import { useFormItemProps } from '@element-plus/hooks'
import { buildProps, definePropType } from '@element-plus/utils/props'
import type { ExtractPropTypes, Component } from 'vue'
export const buttonType = [
@ -37,8 +36,15 @@ export const buttonProps = buildProps({
autofocus: Boolean,
round: Boolean,
circle: Boolean,
autoInsertSpace: {
type: Boolean,
},
} as const)
export interface ButtonConfigContext {
autoInsertSpace?: boolean
}
export const buttonEmits = {
click: (evt: MouseEvent) => evt instanceof MouseEvent,
}

View File

@ -33,10 +33,9 @@
<script lang="ts">
import { computed, inject, defineComponent, Text } from 'vue'
import { ElIcon } from '@element-plus/components/icon'
import { useFormItem } from '@element-plus/hooks'
import { useFormItem, useGlobalConfig } from '@element-plus/hooks'
import { elButtonGroupKey, elFormKey } from '@element-plus/tokens'
import { Loading } from '@element-plus/icons'
import { buttonEmits, buttonProps } from './button'
export default defineComponent({
@ -52,10 +51,15 @@ export default defineComponent({
setup(props, { emit, slots }) {
const elBtnGroup = inject(elButtonGroupKey, undefined)
const globalConfig = useGlobalConfig()
const autoInsertSpace = computed(() => {
return props.autoInsertSpace ?? globalConfig?.button.autoInsertSpace
})
// add space between two characters in Chinese
const shouldAddSpace = computed(() => {
const defaultSlot = slots.default?.()
if (defaultSlot?.length === 1) {
if (autoInsertSpace.value && defaultSlot?.length === 1) {
const slot = defaultSlot[0]
if (slot?.type === Text) {
const text = slot.children

View File

@ -1,10 +1,10 @@
import { h, ref, inject } from 'vue'
import { h, ref, inject, reactive, nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import { LocaleInjectionKey } from '@element-plus/hooks'
import Chinese from '@element-plus/locale/lang/zh-cn'
import English from '@element-plus/locale/lang/en'
import { ConfigProvider } from '../config-provider'
import { ElButton } from '@element-plus/components'
import { ConfigProvider } from '../src'
import type { Language } from '@element-plus/locale'
const TestComp = {
@ -87,4 +87,37 @@ describe('config-provider', () => {
)
})
})
describe('button-config', () => {
it('autoInsertSpace', async () => {
const wrapper = mount({
components: {
[ConfigProvider.name]: ConfigProvider,
ElButton,
},
setup() {
const config = reactive({
autoInsertSpace: true,
})
return {
config,
}
},
template: `
<el-config-provider :button="config">
<el-button></el-button>
</el-config-provider>
<button class="toggle" @click="config.autoInsertSpace = !config.autoInsertSpace">toggle</button>
`,
})
await nextTick()
expect(
wrapper.find('.el-button .el-button__text--expand').exists()
).toBeTruthy()
await wrapper.find('.toggle').trigger('click')
expect(
wrapper.find('.el-button .el-button__text--expand').exists()
).toBeFalsy()
})
})
})

View File

@ -1,17 +0,0 @@
import { defineComponent } from 'vue'
import { useLocaleProps, useLocale } from '@element-plus/hooks'
export const ConfigProvider = defineComponent({
name: 'ElConfigProvider',
props: {
...useLocaleProps,
// Add more configs
},
setup(_, { slots }) {
useLocale()
return () => slots.default?.()
},
})

View File

@ -1,5 +1,5 @@
import { withInstall } from '@element-plus/utils/with-install'
import { ConfigProvider } from './config-provider'
import { ConfigProvider } from './src'
export const ElConfigProvider = withInstall(ConfigProvider)
export default ElConfigProvider

View File

@ -0,0 +1,16 @@
import { useLocaleProps } from '@element-plus/hooks'
import { buildProp, definePropType, mutable } from '@element-plus/utils/props'
import type { ButtonConfigContext } from '@element-plus/components/button'
export const configProviderProps = {
...useLocaleProps,
// Add more configs
button: buildProp({
type: definePropType<ButtonConfigContext>(Object),
default: () => {
return mutable({
autoInsertSpace: true,
} as const)
},
}),
}

View File

@ -0,0 +1,14 @@
import { provide, defineComponent } from 'vue'
import { useLocale } from '@element-plus/hooks'
import { configProviderContextKey } from '@element-plus/tokens'
import { configProviderProps } from './config-provider'
export const ConfigProvider = defineComponent({
name: 'ElConfigProvider',
props: configProviderProps,
setup(props, { slots }) {
useLocale()
provide(configProviderContextKey, props)
return () => slots.default?.()
},
})

View File

@ -15,3 +15,4 @@ export * from './use-css-var'
export * from './use-locale'
export * from './use-form-item'
export * from './use-same-target'
export * from './use-global-config'

View File

@ -0,0 +1,13 @@
import { inject } from 'vue'
import { configProviderContextKey } from '@element-plus/tokens'
import type { ConfigProvdierContext } from '@element-plus/tokens'
const defaultConfig: ConfigProvdierContext = {
button: {
autoInsertSpace: true,
},
}
export const useGlobalConfig = () => {
return inject(configProviderContextKey, defaultConfig)
}

View File

@ -1,13 +1,13 @@
import { computed, getCurrentInstance, inject, provide, ref } from 'vue'
import English from '@element-plus/locale/lang/en'
import type { InjectionKey, PropType, Ref } from 'vue'
import { buildProp, definePropType } from '@element-plus/utils/props'
import type { InjectionKey, Ref } from 'vue'
import type { Language } from '@element-plus/locale'
export const useLocaleProps = {
locale: {
type: Object as PropType<Language>,
},
locale: buildProp({
type: definePropType<Language>(Object),
}),
}
type Translator = (...args: any[]) => string

View File

@ -0,0 +1,7 @@
import type { configProviderProps } from '@element-plus/components/config-provider/config-provider'
import type { InjectionKey, ExtractPropTypes } from 'vue'
export type ConfigProvdierContext = ExtractPropTypes<typeof configProviderProps>
export const configProviderContextKey: InjectionKey<ConfigProvdierContext> =
Symbol()

View File

@ -2,3 +2,4 @@ export * from './form'
export * from './button'
export * from './breadcrumb'
export * from './pagination'
export * from './config-provider'