From cfd4aadc292f8e22db9c10fa2152ec0f767c08e9 Mon Sep 17 00:00:00 2001 From: selicens <1244620067@qq.com> Date: Fri, 18 Aug 2023 14:22:07 +0800 Subject: [PATCH] feat(Avatar): group add shape & synch demo (#6822) --- components/avatar/Avatar.tsx | 9 +- components/avatar/AvatarContext.ts | 16 +++ components/avatar/Group.tsx | 13 ++- components/avatar/SizeContext.ts | 17 --- components/avatar/demo/badge.vue | 13 +-- components/avatar/demo/basic.vue | 55 +++++----- components/avatar/demo/dynamic.vue | 30 +++--- components/avatar/demo/group.vue | 49 +++++++-- components/avatar/demo/index.vue | 7 -- components/avatar/demo/type.vue | 30 +++--- components/avatar/index.en-US.md | 1 + components/avatar/index.zh-CN.md | 1 + components/avatar/style/index.ts | 159 +++++++++++++++++++---------- 13 files changed, 240 insertions(+), 160 deletions(-) create mode 100644 components/avatar/AvatarContext.ts delete mode 100644 components/avatar/SizeContext.ts diff --git a/components/avatar/Avatar.tsx b/components/avatar/Avatar.tsx index 88f5cbcdd..5bd4f17e0 100644 --- a/components/avatar/Avatar.tsx +++ b/components/avatar/Avatar.tsx @@ -11,7 +11,7 @@ import useConfigInject from '../config-provider/hooks/useConfigInject'; import ResizeObserver from '../vc-resize-observer'; import eagerComputed from '../_util/eagerComputed'; import useStyle from './style'; -import { useInjectSize } from './SizeContext'; +import { useAvatarInjectContext } from './AvatarContext'; export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap; @@ -56,9 +56,9 @@ const Avatar = defineComponent({ const { prefixCls } = useConfigInject('avatar', props); const [wrapSSR, hashId] = useStyle(prefixCls); - const groupSize = useInjectSize(); + const avatarCtx = useAvatarInjectContext(); const size = computed(() => { - return props.size === 'default' ? groupSize.value : props.size; + return props.size === 'default' ? avatarCtx.size : props.size; }); const screens = useBreakpoint(); const responsiveSize = eagerComputed(() => { @@ -135,6 +135,7 @@ const Avatar = defineComponent({ return () => { const { shape, src, alt, srcset, draggable, crossOrigin } = props; + const mergeShape = avatarCtx.shape ?? shape; const icon = getPropsSlot(slots, props, 'icon'); const pre = prefixCls.value; const classString = { @@ -142,7 +143,7 @@ const Avatar = defineComponent({ [pre]: true, [`${pre}-lg`]: size.value === 'large', [`${pre}-sm`]: size.value === 'small', - [`${pre}-${shape}`]: shape, + [`${pre}-${mergeShape}`]: true, [`${pre}-image`]: src && isImgExist.value, [`${pre}-icon`]: icon, [hashId.value]: true, diff --git a/components/avatar/AvatarContext.ts b/components/avatar/AvatarContext.ts new file mode 100644 index 000000000..396b7ce57 --- /dev/null +++ b/components/avatar/AvatarContext.ts @@ -0,0 +1,16 @@ +import type { InjectionKey } from 'vue'; +import { inject, provide } from 'vue'; +import type { ScreenSizeMap } from '../_util/responsiveObserve'; +export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap; +export interface AvatarContextType { + size?: AvatarSize; + shape?: 'circle' | 'square'; +} +const AvatarContextKey: InjectionKey = Symbol('AvatarContextKey'); + +export const useAvatarInjectContext = () => { + return inject(AvatarContextKey, {}); +}; +export const useAvatarProviderContext = (context: AvatarContextType) => { + return provide(AvatarContextKey, context); +}; diff --git a/components/avatar/Group.tsx b/components/avatar/Group.tsx index e1832e117..c60f6411b 100644 --- a/components/avatar/Group.tsx +++ b/components/avatar/Group.tsx @@ -3,11 +3,11 @@ import type { AvatarSize } from './Avatar'; import Avatar from './Avatar'; import Popover from '../popover'; import type { PropType, ExtractPropTypes, CSSProperties } from 'vue'; -import { computed, defineComponent } from 'vue'; +import { computed, defineComponent, watchEffect } from 'vue'; import { flattenChildren, getPropsSlot } from '../_util/props-util'; import useConfigInject from '../config-provider/hooks/useConfigInject'; import useStyle from './style'; -import { useProviderSize } from './SizeContext'; +import { useAvatarProviderContext } from './AvatarContext'; export const groupProps = () => ({ prefixCls: String, @@ -23,6 +23,7 @@ export const groupProps = () => ({ type: [Number, String, Object] as PropType, default: 'default' as AvatarSize, }, + shape: { type: String as PropType<'circle' | 'square'>, default: 'circle' }, }); export type AvatarGroupProps = Partial>>; @@ -36,13 +37,17 @@ const Group = defineComponent({ const { prefixCls, direction } = useConfigInject('avatar', props); const groupPrefixCls = computed(() => `${prefixCls.value}-group`); const [wrapSSR, hashId] = useStyle(prefixCls); - useProviderSize(computed(() => props.size)); + watchEffect(() => { + const context = { size: props.size, shape: props.shape }; + useAvatarProviderContext(context); + }); return () => { const { maxPopoverPlacement = 'top', maxCount, maxStyle, maxPopoverTrigger = 'hover', + shape, } = props; const cls = { @@ -72,7 +77,7 @@ const Group = defineComponent({ placement={maxPopoverPlacement} overlayClassName={`${groupPrefixCls.value}-popover`} > - {`+${numOfChildren - maxCount}`} + {`+${numOfChildren - maxCount}`} , ); return wrapSSR( diff --git a/components/avatar/SizeContext.ts b/components/avatar/SizeContext.ts deleted file mode 100644 index 409b8adbd..000000000 --- a/components/avatar/SizeContext.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { InjectionKey, Ref } from 'vue'; -import { computed, inject, ref, provide } from 'vue'; -import type { ScreenSizeMap } from '../_util/responsiveObserve'; -export type AvatarSize = 'large' | 'small' | 'default' | number | ScreenSizeMap; -const SizeContextKey: InjectionKey> = Symbol('SizeContextKey'); - -export const useInjectSize = () => { - return inject(SizeContextKey, ref('default' as AvatarSize)); -}; -export const useProviderSize = (size: Ref) => { - const parentSize = useInjectSize(); - provide( - SizeContextKey, - computed(() => size.value || parentSize.value), - ); - return size; -}; diff --git a/components/avatar/demo/badge.vue b/components/avatar/demo/badge.vue index c76e52b77..00ce30f1a 100644 --- a/components/avatar/demo/badge.vue +++ b/components/avatar/demo/badge.vue @@ -16,29 +16,20 @@ Usually used for reminders and notifications. - - diff --git a/components/avatar/demo/basic.vue b/components/avatar/demo/basic.vue index 5e6b02501..3c62046ad 100644 --- a/components/avatar/demo/basic.vue +++ b/components/avatar/demo/basic.vue @@ -16,31 +16,36 @@ Three sizes and two shapes are available. diff --git a/components/avatar/demo/group.vue b/components/avatar/demo/group.vue index a1848c41d..66cc2ab39 100644 --- a/components/avatar/demo/group.vue +++ b/components/avatar/demo/group.vue @@ -17,20 +17,22 @@ Avatar group display. diff --git a/components/avatar/demo/index.vue b/components/avatar/demo/index.vue index 5f84da14c..d508df1bd 100644 --- a/components/avatar/demo/index.vue +++ b/components/avatar/demo/index.vue @@ -36,10 +36,3 @@ export default defineComponent({ }, }); - - diff --git a/components/avatar/demo/type.vue b/components/avatar/demo/type.vue index 752c0884d..fcdf9c215 100644 --- a/components/avatar/demo/type.vue +++ b/components/avatar/demo/type.vue @@ -16,20 +16,22 @@ Image, Icon and letter are supported, and the latter two kinds avatar can have c