feat(v3/avatar): add avatar group (#4062)
* feat(avatar): add avatar group * refactor: update * refactor: update Co-authored-by: tangjinzhou <415800467@qq.com>feat-new-menu
parent
49ad768432
commit
0984951845
|
@ -0,0 +1,21 @@
|
||||||
|
import { onMounted, onUnmounted, Ref, ref } from 'vue';
|
||||||
|
import ResponsiveObserve, { ScreenMap } from '../../_util/responsiveObserve';
|
||||||
|
|
||||||
|
function useBreakpoint(): Ref<ScreenMap> {
|
||||||
|
const screens = ref<ScreenMap>({});
|
||||||
|
let token = null;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
token = ResponsiveObserve.subscribe(supportScreens => {
|
||||||
|
screens.value = supportScreens;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
ResponsiveObserve.unsubscribe(token);
|
||||||
|
});
|
||||||
|
|
||||||
|
return screens;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useBreakpoint;
|
|
@ -1,6 +1,7 @@
|
||||||
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs';
|
||||||
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
|
export type BreakpointMap = Partial<Record<Breakpoint, string>>;
|
||||||
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
|
export type ScreenMap = Partial<Record<Breakpoint, boolean>>;
|
||||||
|
export type ScreenSizeMap = Partial<Record<Breakpoint, number>>;
|
||||||
|
|
||||||
export const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
export const responsiveArray: Breakpoint[] = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'];
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { tuple, VueNode } from '../_util/type';
|
import { tuple, VueNode } from '../_util/type';
|
||||||
import {
|
import {
|
||||||
|
computed,
|
||||||
CSSProperties,
|
CSSProperties,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
ExtractPropTypes,
|
ExtractPropTypes,
|
||||||
|
@ -14,20 +15,25 @@ import {
|
||||||
import { defaultConfigProvider } from '../config-provider';
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
import { getPropsSlot } from '../_util/props-util';
|
import { getPropsSlot } from '../_util/props-util';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
|
import useBreakpoint from '../_util/hooks/useBreakpoint';
|
||||||
|
import { Breakpoint, responsiveArray, ScreenSizeMap } from '../_util/responsiveObserve';
|
||||||
|
|
||||||
const avatarProps = {
|
export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap;
|
||||||
|
|
||||||
|
export const avatarProps = {
|
||||||
prefixCls: PropTypes.string,
|
prefixCls: PropTypes.string,
|
||||||
shape: PropTypes.oneOf(tuple('circle', 'square')),
|
shape: PropTypes.oneOf(tuple('circle', 'square')),
|
||||||
size: {
|
size: {
|
||||||
type: [Number, String] as PropType<'large' | 'small' | 'default' | number>,
|
type: [Number, String, Object] as PropType<AvatarSize>,
|
||||||
default: 'default',
|
default: (): AvatarSize => 'default',
|
||||||
},
|
},
|
||||||
src: PropTypes.string,
|
src: PropTypes.string,
|
||||||
/** Srcset of image avatar */
|
/** Srcset of image avatar */
|
||||||
srcset: PropTypes.string,
|
srcset: PropTypes.string,
|
||||||
icon: PropTypes.VNodeChild,
|
icon: PropTypes.VNodeChild,
|
||||||
alt: PropTypes.string,
|
alt: PropTypes.string,
|
||||||
gap: Number,
|
gap: PropTypes.number,
|
||||||
|
draggable: PropTypes.bool,
|
||||||
loadError: {
|
loadError: {
|
||||||
type: Function as PropType<() => boolean>,
|
type: Function as PropType<() => boolean>,
|
||||||
},
|
},
|
||||||
|
@ -38,7 +44,7 @@ export type AvatarProps = Partial<ExtractPropTypes<typeof avatarProps>>;
|
||||||
const Avatar = defineComponent({
|
const Avatar = defineComponent({
|
||||||
name: 'AAvatar',
|
name: 'AAvatar',
|
||||||
props: avatarProps,
|
props: avatarProps,
|
||||||
setup(props, { slots }) {
|
setup(props, { slots, attrs }) {
|
||||||
const isImgExist = ref(true);
|
const isImgExist = ref(true);
|
||||||
const isMounted = ref(false);
|
const isMounted = ref(false);
|
||||||
const scale = ref(1);
|
const scale = ref(1);
|
||||||
|
@ -48,6 +54,34 @@ const Avatar = defineComponent({
|
||||||
|
|
||||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||||
|
|
||||||
|
const groupSize = inject(
|
||||||
|
'SizeProvider',
|
||||||
|
computed(() => 'default'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const screens = useBreakpoint();
|
||||||
|
const responsiveSize = computed(() => {
|
||||||
|
if (typeof props.size !== 'object') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const currentBreakpoint: Breakpoint = responsiveArray.find(screen => screens.value[screen])!;
|
||||||
|
const currentSize = props.size[currentBreakpoint];
|
||||||
|
|
||||||
|
return currentSize;
|
||||||
|
});
|
||||||
|
|
||||||
|
const responsiveSizeStyle = (hasIcon: boolean) => {
|
||||||
|
if (responsiveSize.value) {
|
||||||
|
return {
|
||||||
|
width: `${responsiveSize.value}px`,
|
||||||
|
height: `${responsiveSize.value}px`,
|
||||||
|
lineHeight: `${responsiveSize.value}px`,
|
||||||
|
fontSize: `${hasIcon ? responsiveSize.value / 2 : 18}px`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
const setScale = () => {
|
const setScale = () => {
|
||||||
if (!avatarChildrenRef.value || !avatarNodeRef.value) {
|
if (!avatarChildrenRef.value || !avatarNodeRef.value) {
|
||||||
return;
|
return;
|
||||||
|
@ -96,11 +130,19 @@ const Avatar = defineComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { prefixCls: customizePrefixCls, shape, size, src, alt, srcset } = props;
|
const {
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
shape,
|
||||||
|
size: customSize,
|
||||||
|
src,
|
||||||
|
alt,
|
||||||
|
srcset,
|
||||||
|
draggable,
|
||||||
|
} = props;
|
||||||
const icon = getPropsSlot(slots, props, 'icon');
|
const icon = getPropsSlot(slots, props, 'icon');
|
||||||
const getPrefixCls = configProvider.getPrefixCls;
|
const getPrefixCls = configProvider.getPrefixCls;
|
||||||
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
const prefixCls = getPrefixCls('avatar', customizePrefixCls);
|
||||||
|
const size = customSize === 'default' ? groupSize.value : customSize;
|
||||||
const classString = {
|
const classString = {
|
||||||
[prefixCls]: true,
|
[prefixCls]: true,
|
||||||
[`${prefixCls}-lg`]: size === 'large',
|
[`${prefixCls}-lg`]: size === 'large',
|
||||||
|
@ -122,7 +164,15 @@ const Avatar = defineComponent({
|
||||||
|
|
||||||
let children: VueNode = slots.default?.();
|
let children: VueNode = slots.default?.();
|
||||||
if (src && isImgExist.value) {
|
if (src && isImgExist.value) {
|
||||||
children = <img src={src} srcset={srcset} onError={handleImgLoadError} alt={alt} />;
|
children = (
|
||||||
|
<img
|
||||||
|
draggable={draggable}
|
||||||
|
src={src}
|
||||||
|
srcset={srcset}
|
||||||
|
onError={handleImgLoadError}
|
||||||
|
alt={alt}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else if (icon) {
|
} else if (icon) {
|
||||||
children = icon;
|
children = icon;
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,7 +209,15 @@ const Avatar = defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span ref={avatarNodeRef} class={classString} style={sizeStyle}>
|
<span
|
||||||
|
ref={avatarNodeRef}
|
||||||
|
class={classString}
|
||||||
|
style={{
|
||||||
|
...sizeStyle,
|
||||||
|
...responsiveSizeStyle(!!icon),
|
||||||
|
...(attrs.style as CSSProperties),
|
||||||
|
}}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
import toArray from 'lodash/toArray';
|
||||||
|
import { cloneElement } from '../_util/vnode';
|
||||||
|
import { defaultConfigProvider } from '../config-provider';
|
||||||
|
import Avatar, { avatarProps } from './Avatar';
|
||||||
|
import Popover from '../popover';
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
inject,
|
||||||
|
provide,
|
||||||
|
PropType,
|
||||||
|
ExtractPropTypes,
|
||||||
|
CSSProperties,
|
||||||
|
} from 'vue';
|
||||||
|
import PropTypes from '../_util/vue-types';
|
||||||
|
import { getPropsSlot } from '../_util/props-util';
|
||||||
|
import { tuple } from '../_util/type';
|
||||||
|
|
||||||
|
const groupProps = {
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
maxCount: PropTypes.number,
|
||||||
|
maxStyle: {
|
||||||
|
type: Object as PropType<CSSProperties>,
|
||||||
|
default: () => ({} as CSSProperties),
|
||||||
|
},
|
||||||
|
maxPopoverPlacement: PropTypes.oneOf(tuple('top', 'bottom')).def('top'),
|
||||||
|
/*
|
||||||
|
* Size of avatar, options: `large`, `small`, `default`
|
||||||
|
* or a custom number size
|
||||||
|
* */
|
||||||
|
size: avatarProps.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AvatarGroupProps = Partial<ExtractPropTypes<typeof groupProps>>;
|
||||||
|
|
||||||
|
const Group = defineComponent({
|
||||||
|
name: 'AAvatarGroup',
|
||||||
|
props: groupProps,
|
||||||
|
inheritAttrs: false,
|
||||||
|
setup(props, { slots, attrs }) {
|
||||||
|
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||||
|
|
||||||
|
provide(
|
||||||
|
'SizeProvider',
|
||||||
|
computed(() => props.size || configProvider.componentSize),
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const {
|
||||||
|
prefixCls: customizePrefixCls,
|
||||||
|
maxPopoverPlacement = 'top',
|
||||||
|
maxCount,
|
||||||
|
maxStyle,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const { getPrefixCls } = configProvider;
|
||||||
|
const prefixCls = getPrefixCls('avatar-group', customizePrefixCls);
|
||||||
|
const className = attrs.class as string;
|
||||||
|
|
||||||
|
const cls = {
|
||||||
|
[prefixCls]: true,
|
||||||
|
[className]: className !== undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const children = getPropsSlot(slots, props);
|
||||||
|
const childrenWithProps = toArray(children).map((child, index) =>
|
||||||
|
cloneElement(child, {
|
||||||
|
key: `avatar-key-${index}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const numOfChildren = childrenWithProps.length;
|
||||||
|
if (maxCount && maxCount < numOfChildren) {
|
||||||
|
const childrenShow = childrenWithProps.slice(0, maxCount);
|
||||||
|
const childrenHidden = childrenWithProps.slice(maxCount, numOfChildren);
|
||||||
|
|
||||||
|
childrenShow.push(
|
||||||
|
<Popover
|
||||||
|
key="avatar-popover-key"
|
||||||
|
content={childrenHidden}
|
||||||
|
trigger="hover"
|
||||||
|
placement={maxPopoverPlacement}
|
||||||
|
overlayClassName={`${prefixCls}-popover`}
|
||||||
|
>
|
||||||
|
<Avatar style={maxStyle}>{`+${numOfChildren - maxCount}`}</Avatar>
|
||||||
|
</Popover>,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div class={cls} style={attrs.style}>
|
||||||
|
{childrenShow}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={cls} style={attrs.style}>
|
||||||
|
{childrenWithProps}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Group;
|
|
@ -1,9 +1,14 @@
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { asyncExpect } from '@/tests/utils';
|
import { asyncExpect } from '@/tests/utils';
|
||||||
import Avatar from '..';
|
import Avatar from '..';
|
||||||
|
import useBreakpoint from '../../_util/hooks/useBreakpoint';
|
||||||
|
|
||||||
|
jest.mock('../../_util/hooks/useBreakpoint');
|
||||||
|
|
||||||
describe('Avatar Render', () => {
|
describe('Avatar Render', () => {
|
||||||
let originOffsetWidth;
|
let originOffsetWidth;
|
||||||
|
const sizes = { xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 };
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
// Mock offsetHeight
|
// Mock offsetHeight
|
||||||
originOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth').get;
|
originOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth').get;
|
||||||
|
@ -124,4 +129,83 @@ describe('Avatar Render', () => {
|
||||||
expect(wrapper.findAll('.ant-avatar-image').length).toBe(1);
|
expect(wrapper.findAll('.ant-avatar-image').length).toBe(1);
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should calculate scale of avatar children correctly', async () => {
|
||||||
|
let wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return <Avatar>Avatar</Avatar>;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await asyncExpect(() => {
|
||||||
|
expect(wrapper.find('.ant-avatar-string')).toMatchSnapshot();
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
|
||||||
|
get() {
|
||||||
|
if (this.className === 'ant-avatar-string') {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
return 40;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return <Avatar>xx</Avatar>;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await asyncExpect(() => {
|
||||||
|
expect(wrapper.find('.ant-avatar-string')).toMatchSnapshot();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate scale of avatar children correctly with gap', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return <Avatar gap={2}>Avatar</Avatar>;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await asyncExpect(() => {
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.entries(sizes).forEach(([key, value]) => {
|
||||||
|
it(`adjusts component size to ${value} when window size is ${key}`, async () => {
|
||||||
|
useBreakpoint.mockReturnValue({ value: { [key]: true } });
|
||||||
|
|
||||||
|
const wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return <Avatar size={sizes} />;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await asyncExpect(() => {
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fallback', async () => {
|
||||||
|
const div = global.document.createElement('div');
|
||||||
|
global.document.body.appendChild(div);
|
||||||
|
const wrapper = mount(
|
||||||
|
{
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Avatar shape="circle" src="http://error.url">
|
||||||
|
A
|
||||||
|
</Avatar>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ attachTo: div },
|
||||||
|
);
|
||||||
|
await asyncExpect(async () => {
|
||||||
|
await wrapper.find('img').trigger('error');
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
wrapper.unmount();
|
||||||
|
global.document.body.removeChild(div);
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 24 when window size is xs 1`] = `<span class="ant-avatar" style="width: 24px; height: 24px; line-height: 24px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 32 when window size is sm 1`] = `<span class="ant-avatar" style="width: 32px; height: 32px; line-height: 32px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 40 when window size is md 1`] = `<span class="ant-avatar" style="width: 40px; height: 40px; line-height: 40px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 64 when window size is lg 1`] = `<span class="ant-avatar" style="width: 64px; height: 64px; line-height: 64px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 80 when window size is xl 1`] = `<span class="ant-avatar" style="width: 80px; height: 80px; line-height: 80px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render adjusts component size to 100 when window size is xxl 1`] = `<span class="ant-avatar" style="width: 100px; height: 100px; line-height: 100px; font-size: 18px;"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);"><!----></span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render fallback 1`] = `<span class="ant-avatar ant-avatar-circle"><span class="ant-avatar-string" style="transform: scale(0.32) translateX(-50%);">A</span></span>`;
|
||||||
|
|
||||||
|
exports[`Avatar Render should calculate scale of avatar children correctly 1`] = `
|
||||||
|
DOMWrapper {
|
||||||
|
"wrapperElement": <span
|
||||||
|
class="ant-avatar-string"
|
||||||
|
style="transform: scale(0.72) translateX(-50%);"
|
||||||
|
>
|
||||||
|
|
||||||
|
Avatar
|
||||||
|
|
||||||
|
</span>,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Avatar Render should calculate scale of avatar children correctly 2`] = `
|
||||||
|
DOMWrapper {
|
||||||
|
"wrapperElement": <span
|
||||||
|
class="ant-avatar-string"
|
||||||
|
style="transform: scale(0.32) translateX(-50%);"
|
||||||
|
>
|
||||||
|
|
||||||
|
xx
|
||||||
|
|
||||||
|
</span>,
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Avatar Render should calculate scale of avatar children correctly with gap 1`] = `<span class="ant-avatar"><span class="ant-avatar-string" style="transform: scale(0.36) translateX(-50%);">Avatar</span></span>`;
|
|
@ -1,6 +1,20 @@
|
||||||
|
import { App } from 'vue';
|
||||||
import Avatar from './Avatar';
|
import Avatar from './Avatar';
|
||||||
import { withInstall } from '../_util/type';
|
import Group from './Group';
|
||||||
|
|
||||||
export { AvatarProps } from './Avatar';
|
export { AvatarProps, AvatarSize } from './Avatar';
|
||||||
|
export { AvatarGroupProps } from './Group';
|
||||||
|
|
||||||
export default withInstall(Avatar);
|
Avatar.Group = Group;
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
Avatar.install = function(app: App) {
|
||||||
|
app.component(Avatar.name, Avatar);
|
||||||
|
app.component(Group.name, Group);
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Avatar as typeof Avatar &
|
||||||
|
Plugin & {
|
||||||
|
readonly Group: typeof Group;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
.@{avatar-prefix-cls}-group {
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
.@{avatar-prefix-cls} {
|
||||||
|
border: 1px solid @avatar-group-border-color;
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
margin-left: @avatar-group-overlapping;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-popover {
|
||||||
|
.@{ant-prefix}-avatar + .@{ant-prefix}-avatar {
|
||||||
|
margin-left: @avatar-group-space;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,3 +57,5 @@
|
||||||
font-size: @font-size;
|
font-size: @font-size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@import './group';
|
||||||
|
|
|
@ -14,6 +14,31 @@ export interface CSPConfig {
|
||||||
|
|
||||||
export { RenderEmptyHandler };
|
export { RenderEmptyHandler };
|
||||||
|
|
||||||
|
export interface ConfigConsumerProps {
|
||||||
|
getTargetContainer?: () => HTMLElement;
|
||||||
|
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
|
||||||
|
rootPrefixCls?: string;
|
||||||
|
getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => string;
|
||||||
|
renderEmpty: RenderEmptyHandler;
|
||||||
|
transformCellText?: (tableProps: TransformCellTextProps) => any;
|
||||||
|
csp?: CSPConfig;
|
||||||
|
autoInsertSpaceInButton?: boolean;
|
||||||
|
input?: {
|
||||||
|
autoComplete?: string;
|
||||||
|
};
|
||||||
|
locale?: Locale;
|
||||||
|
pageHeader?: {
|
||||||
|
ghost: boolean;
|
||||||
|
};
|
||||||
|
componentSize?: SizeType;
|
||||||
|
direction?: 'ltr' | 'rtl';
|
||||||
|
space?: {
|
||||||
|
size?: SizeType | number;
|
||||||
|
};
|
||||||
|
virtual?: boolean;
|
||||||
|
dropdownMatchSelectWidth?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const configConsumerProps = [
|
export const configConsumerProps = [
|
||||||
'getTargetContainer',
|
'getTargetContainer',
|
||||||
'getPopupContainer',
|
'getPopupContainer',
|
||||||
|
|
|
@ -644,6 +644,9 @@
|
||||||
@avatar-bg: #ccc;
|
@avatar-bg: #ccc;
|
||||||
@avatar-color: #fff;
|
@avatar-color: #fff;
|
||||||
@avatar-border-radius: @border-radius-base;
|
@avatar-border-radius: @border-radius-base;
|
||||||
|
@avatar-group-overlapping: -8px;
|
||||||
|
@avatar-group-space: 3px;
|
||||||
|
@avatar-group-border-color: #fff;
|
||||||
|
|
||||||
// Switch
|
// Switch
|
||||||
// ---
|
// ---
|
||||||
|
|
Loading…
Reference in New Issue