feat(ConfigProvider): add icon-prefix prop (#8986)

This commit is contained in:
neverland 2021-07-06 17:24:22 +08:00 committed by GitHub
parent b5ea1cd3ad
commit 2a74d88c91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 41 deletions

View File

@ -1,14 +1,22 @@
import { computed, CSSProperties, defineComponent, PropType } from 'vue';
import { createNamespace } from '../utils';
import {
provide,
computed,
PropType,
CSSProperties,
InjectionKey,
defineComponent,
} from 'vue';
import { createNamespace, kebabCase } from '../utils';
const [name, bem] = createNamespace('config-provider');
export function kebabCase(word: string) {
return word
.replace(/([A-Z])/g, '-$1')
.toLowerCase()
.replace(/^-/, '');
}
export type ConfigProviderProvide = {
iconPrefix?: string;
};
export const CONFIG_PROVIDER_KEY: InjectionKey<ConfigProviderProvide> = Symbol(
name
);
function mapThemeVarsToCSSVars(themeVars: Record<string, string | number>) {
const cssVars: Record<string, string | number> = {};
@ -23,6 +31,7 @@ export default defineComponent({
props: {
themeVars: Object as PropType<Record<string, string | number>>,
iconPrefix: String,
tag: {
type: String as PropType<keyof HTMLElementTagNameMap>,
default: 'div',
@ -36,6 +45,8 @@ export default defineComponent({
}
});
provide(CONFIG_PROVIDER_KEY, props);
return () => (
<props.tag class={bem()} style={style.value}>
{slots.default?.()}

View File

@ -195,7 +195,8 @@ There are some **Basic Variables** below, for component CSS Variables, please re
### Props
| Attribute | Description | Type | Default |
| ------------ | ------------------------ | -------- | ------- |
| theme-vars | Theme variables | _object_ | - |
| tag `v3.1.2` | HTML Tag of root element | _string_ | `div` |
| Attribute | Description | Type | Default |
| -------------------- | ------------------------ | -------- | ---------- |
| theme-vars | Theme variables | _object_ | - |
| tag `v3.1.2` | HTML Tag of root element | _string_ | `div` |
| icon-prefix `v3.1.3` | Icon className prefix | _string_ | `van-icon` |

View File

@ -195,7 +195,8 @@ export default {
### Props
| 参数 | 说明 | 类型 | 默认值 |
| ------------ | ------------------------ | -------- | ------ |
| theme-vars | 自定义主题变量 | _object_ | - |
| tag `v3.1.2` | 根节点对应的 HTML 标签名 | _string_ | `div` |
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| theme-vars | 自定义主题变量 | _object_ | - |
| tag `v3.1.2` | 根节点对应的 HTML 标签名 | _string_ | `div` |
| icon-prefix `v3.1.3` | 所有图标的类名前缀,同 Icon 组件的 [class-prefix 属性](#/zh-CN/icon#props) | _string_ | `van-icon` |

View File

@ -1,6 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render tag prop correctly 1`] = `
<section class="van-config-provider">
</section>
`;

View File

@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should change icon class-prefix when using icon-prefix prop 1`] = `
<div class="van-config-provider">
<i class="van-badge__wrapper foo foo-success">
</i>
</div>
`;
exports[`should render tag prop correctly 1`] = `
<section class="van-config-provider">
</section>
`;

View File

@ -1,11 +0,0 @@
import { ConfigProvider } from '..';
import { mount } from '../../../test';
test('should render tag prop correctly', () => {
const wrapper = mount(ConfigProvider, {
props: {
tag: 'section',
},
});
expect(wrapper.html()).toMatchSnapshot();
});

View File

@ -0,0 +1,25 @@
import { ConfigProvider } from '..';
import { Icon } from '../../icon';
import { mount } from '../../../test';
test('should render tag prop correctly', () => {
const wrapper = mount(ConfigProvider, {
props: {
tag: 'section',
},
});
expect(wrapper.html()).toMatchSnapshot();
});
test('should change icon class-prefix when using icon-prefix prop', () => {
const wrapper = mount({
render() {
return (
<ConfigProvider iconPrefix="foo">
<Icon name="success" />
</ConfigProvider>
);
},
});
expect(wrapper.html()).toMatchSnapshot();
});

View File

@ -1,11 +1,12 @@
import { PropType, defineComponent } from 'vue';
import { PropType, defineComponent, inject, computed } from 'vue';
import { addUnit, createNamespace } from '../utils';
import { Badge } from '../badge';
import { CONFIG_PROVIDER_KEY } from '../config-provider/ConfigProvider';
const [name, bem] = createNamespace('icon');
function isImage(name?: string) {
return name ? name.includes('/') : false;
return name?.includes('/');
}
export default defineComponent({
@ -17,19 +18,22 @@ export default defineComponent({
size: [Number, String],
badge: [Number, String],
color: String,
classPrefix: String,
tag: {
type: String as PropType<keyof HTMLElementTagNameMap>,
default: 'i',
},
classPrefix: {
type: String,
default: bem(),
},
},
setup(props, { slots }) {
const config = inject(CONFIG_PROVIDER_KEY, null);
const classPrefix = computed(
() => props.classPrefix || config?.iconPrefix || bem()
);
return () => {
const { tag, dot, name, size, badge, color, classPrefix } = props;
const { tag, dot, name, size, badge, color } = props;
const isImageIcon = isImage(name);
return (
@ -37,7 +41,10 @@ export default defineComponent({
dot={dot}
tag={tag}
content={badge}
class={[classPrefix, isImageIcon ? '' : `${classPrefix}-${name}`]}
class={[
classPrefix.value,
isImageIcon ? '' : `${classPrefix.value}-${name}`,
]}
style={{
color,
fontSize: addUnit(size),

View File

@ -4,6 +4,13 @@ export function camelize(str: string): string {
return str.replace(camelizeRE, (_, c) => c.toUpperCase());
}
export function kebabCase(str: string) {
return str
.replace(/([A-Z])/g, '-$1')
.toLowerCase()
.replace(/^-/, '');
}
export function padZero(num: number | string, targetLength = 2): string {
let str = num + '';