mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-21 01:02:59 +08:00
feat: support custom namespace (#5377)
This commit is contained in:
parent
62eb0f92d0
commit
9929c0fba4
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<div class="el-button-group">
|
||||
<div :class="`${ns.b('group')}`">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, provide, reactive, toRef } from 'vue'
|
||||
import { buttonGroupContextKey } from '@element-plus/tokens'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { buttonGroupProps } from './button-group'
|
||||
|
||||
export default defineComponent({
|
||||
@ -20,6 +21,10 @@ export default defineComponent({
|
||||
type: toRef(props, 'type'),
|
||||
})
|
||||
)
|
||||
const ns = useNamespace('button')
|
||||
return {
|
||||
ns,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
@ -2,9 +2,9 @@
|
||||
<button
|
||||
ref="buttonRef"
|
||||
:class="[
|
||||
'el-button',
|
||||
buttonType ? 'el-button--' + buttonType : '',
|
||||
buttonSize ? 'el-button--' + buttonSize : '',
|
||||
`${ns.b()}`,
|
||||
`${ns.m(buttonType)}`,
|
||||
`${ns.m(buttonSize)}`,
|
||||
{
|
||||
'is-disabled': buttonDisabled,
|
||||
'is-loading': loading,
|
||||
@ -27,7 +27,7 @@
|
||||
</el-icon>
|
||||
<span
|
||||
v-if="$slots.default"
|
||||
:class="{ 'el-button__text--expand': shouldAddSpace }"
|
||||
:class="[shouldAddSpace ? `${ns.em('text', 'expand')}` : '']"
|
||||
>
|
||||
<slot></slot>
|
||||
</span>
|
||||
@ -43,6 +43,7 @@ import {
|
||||
useDisabled,
|
||||
useFormItem,
|
||||
useGlobalConfig,
|
||||
useNamespace,
|
||||
useSize,
|
||||
} from '@element-plus/hooks'
|
||||
import { buttonGroupContextKey } from '@element-plus/tokens'
|
||||
@ -65,6 +66,7 @@ export default defineComponent({
|
||||
const buttonRef = ref()
|
||||
const buttonGroupContext = inject(buttonGroupContextKey, undefined)
|
||||
const globalConfig = useGlobalConfig('button')
|
||||
const ns = useNamespace('button')
|
||||
const autoInsertSpace = computed(
|
||||
() =>
|
||||
props.autoInsertSpace ?? globalConfig.value?.autoInsertSpace ?? false
|
||||
@ -156,6 +158,8 @@ export default defineComponent({
|
||||
shouldAddSpace,
|
||||
|
||||
handleClick,
|
||||
|
||||
ns,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
@ -124,6 +124,37 @@ describe('config-provider', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('namespace-config', () => {
|
||||
it('reactive namespace', async () => {
|
||||
const wrapper = mount({
|
||||
components: {
|
||||
[ConfigProvider.name]: ConfigProvider,
|
||||
ElButton,
|
||||
},
|
||||
setup() {
|
||||
const namespace = ref()
|
||||
return {
|
||||
namespace,
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<el-config-provider :namespace="namespace">
|
||||
<el-button>test str</el-button>
|
||||
</el-config-provider>
|
||||
`,
|
||||
})
|
||||
await nextTick()
|
||||
expect(wrapper.find('button').classes().join('')).toBe(
|
||||
'el-button' + 'el-button--default'
|
||||
)
|
||||
wrapper.vm.namespace = 'ep'
|
||||
await nextTick()
|
||||
expect(wrapper.find('button').classes().join('')).toBe(
|
||||
'ep-button' + 'ep-button--default'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('message-config', () => {
|
||||
it('limit the number of messages displayed at the same time', async () => {
|
||||
const wrapper = mount({
|
||||
|
@ -28,6 +28,11 @@ export const configProviderProps = buildProps({
|
||||
zIndex: {
|
||||
type: Number,
|
||||
},
|
||||
|
||||
namespace: {
|
||||
type: String,
|
||||
default: 'el',
|
||||
},
|
||||
} as const)
|
||||
|
||||
export default defineComponent({
|
||||
|
73
packages/hooks/__tests__/use-namespace.spec.ts
Normal file
73
packages/hooks/__tests__/use-namespace.spec.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { h, nextTick } from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { useNamespace, provideGlobalConfig } from '..'
|
||||
|
||||
const TestComp = {
|
||||
setup() {
|
||||
const ns = useNamespace('table')
|
||||
return () => {
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
id: 'testId',
|
||||
class: [
|
||||
ns.b(), // return ns + block
|
||||
ns.b('body'),
|
||||
ns.e('content'),
|
||||
ns.m('active'),
|
||||
ns.be('content', 'active'),
|
||||
ns.em('content', 'active'),
|
||||
ns.bem('body', 'content', 'active'),
|
||||
ns.e(), // return empty string
|
||||
ns.m(), // return empty string
|
||||
ns.be(), // return empty string
|
||||
ns.em(), // return empty string
|
||||
ns.bem(), // return empty string
|
||||
],
|
||||
},
|
||||
'text'
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
describe('use-locale', () => {
|
||||
let wrapper
|
||||
beforeEach(() => {
|
||||
wrapper = mount(
|
||||
{
|
||||
components: {
|
||||
'el-test': TestComp,
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
provideGlobalConfig({ namespace: 'ep' })
|
||||
return () => slots.default()
|
||||
},
|
||||
},
|
||||
{
|
||||
slots: {
|
||||
default: () => h(TestComp),
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('should provide bem correctly', async () => {
|
||||
await nextTick()
|
||||
expect(wrapper.find('#testId').classes().join('~')).toBe(
|
||||
[
|
||||
'ep-table', // b()
|
||||
'ep-table-body', // b('body')
|
||||
'ep-table__content', // e('content')
|
||||
'ep-table--active', // m('active')
|
||||
'ep-table-content__active', // be('content', 'active')
|
||||
'ep-table__content--active', // em('content', 'active')
|
||||
'ep-table-body__content--active', // bem('body', 'content', 'active')
|
||||
].join('~')
|
||||
)
|
||||
})
|
||||
})
|
@ -22,3 +22,4 @@ export * from './use-popper-container'
|
||||
export * from './use-intermediate-render'
|
||||
export * from './use-delayed-toggle'
|
||||
export * from './use-forward-ref'
|
||||
export * from './use-namespace'
|
||||
|
56
packages/hooks/use-namespace/index.ts
Normal file
56
packages/hooks/use-namespace/index.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { unref, computed } from 'vue'
|
||||
import curry from 'lodash/curry'
|
||||
import { useGlobalConfig } from '../use-global-config'
|
||||
|
||||
const curryBem = curry(
|
||||
(
|
||||
namespace: string,
|
||||
block: string,
|
||||
blockSuffix: string,
|
||||
element: string,
|
||||
modifier: string
|
||||
) => {
|
||||
let cls = `${namespace}-${block}`
|
||||
if (blockSuffix) {
|
||||
cls += `-${blockSuffix}`
|
||||
}
|
||||
if (element) {
|
||||
cls += `__${element}`
|
||||
}
|
||||
if (modifier) {
|
||||
cls += `--${modifier}`
|
||||
}
|
||||
return cls
|
||||
}
|
||||
)
|
||||
|
||||
export const useNamespace = (block: string) => {
|
||||
const namespace = computed(() => useGlobalConfig('namespace').value || 'el')
|
||||
const b = (blockSuffix = '') =>
|
||||
curryBem(unref(namespace), block, blockSuffix, '', '')
|
||||
const e = (element?: string) =>
|
||||
element ? curryBem(unref(namespace), block, '', element, '') : ''
|
||||
const m = (modifier?: string) =>
|
||||
modifier ? curryBem(unref(namespace), block, '', '')(modifier) : ''
|
||||
const be = (blockSuffix?: string, element?: string) =>
|
||||
blockSuffix && element
|
||||
? curryBem(unref(namespace), block, blockSuffix, element, '')
|
||||
: ''
|
||||
const em = (element?: string, modifier?: string) =>
|
||||
element && modifier
|
||||
? curryBem(unref(namespace), block, '')(element, modifier)
|
||||
: ''
|
||||
const bem = (blockSuffix?: string, element?: string, modifier?: string) =>
|
||||
blockSuffix && element && modifier
|
||||
? curryBem(unref(namespace), block)(blockSuffix, element, modifier)
|
||||
: ''
|
||||
return {
|
||||
namespace,
|
||||
b,
|
||||
e,
|
||||
m,
|
||||
be,
|
||||
em,
|
||||
bem,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user