mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-30 11:16:12 +08:00
refactor(components): [el-config-provider] improve componomponent extendiability (#4175)
re #4146 added button configuration added useGlobalConfig hook
This commit is contained in:
parent
cf27504bdc
commit
66043aa3b5
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
28
docs/examples/config-provider/button.vue
Normal file
28
docs/examples/config-provider/button.vue
Normal 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>
|
@ -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,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -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?.()
|
||||
},
|
||||
})
|
@ -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
|
||||
|
16
packages/components/config-provider/src/config-provider.ts
Normal file
16
packages/components/config-provider/src/config-provider.ts
Normal 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)
|
||||
},
|
||||
}),
|
||||
}
|
14
packages/components/config-provider/src/index.ts
Normal file
14
packages/components/config-provider/src/index.ts
Normal 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?.()
|
||||
},
|
||||
})
|
@ -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'
|
||||
|
13
packages/hooks/use-global-config/index.ts
Normal file
13
packages/hooks/use-global-config/index.ts
Normal 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)
|
||||
}
|
@ -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
|
||||
|
7
packages/tokens/config-provider.ts
Normal file
7
packages/tokens/config-provider.ts
Normal 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()
|
@ -2,3 +2,4 @@ export * from './form'
|
||||
export * from './button'
|
||||
export * from './breadcrumb'
|
||||
export * from './pagination'
|
||||
export * from './config-provider'
|
||||
|
Loading…
Reference in New Issue
Block a user