mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(components): [avatar-group] new component (#23211)
* feat(components): [avatar-group] new component * feat: update * feat: update * feat: update * docs: add an example * refactor: remove unnecessary computed * refactor: extract props to avatar-group-props * feat: update * fix: handle the rendering issue of hiddenAvatars * style: use inline-flex instead of flex * test: update test case * docs: update the default values of size and shape * refactor: apply rabbit comment * refactor: apply rabbit comment * chore: update description * style: use getCssVar * style: css variables take effect on collapse-avatars
This commit is contained in:
@@ -47,28 +47,56 @@ avatar/fit
|
||||
|
||||
:::
|
||||
|
||||
## API
|
||||
## Avatar Group ^(2.13.1)
|
||||
|
||||
### Attributes
|
||||
Displayed as a avatar group.
|
||||
|
||||
:::demo Use tag `<el-avatar-group>` to group your avatars.
|
||||
|
||||
avatar/group
|
||||
|
||||
:::
|
||||
|
||||
## Avatar API
|
||||
|
||||
### Avatar Attributes
|
||||
|
||||
| Name | Description | Type | Default |
|
||||
| ------- | --------------------------------------------------------- | ----------------------------------------------------------------- | ------- |
|
||||
| icon | representation type to icon, more info on icon component. | ^[string] / ^[Component] | — |
|
||||
| size | avatar size. | ^[number] / ^[enum]`'large' \| 'default' \| 'small'` | default |
|
||||
| shape | avatar shape. | ^[enum]`'circle' \| 'square'` | circle |
|
||||
| size | avatar size. | ^[number] / ^[enum]`'large' \| 'default' \| 'small'` | — |
|
||||
| shape | avatar shape. | ^[enum]`'circle' \| 'square'` | — |
|
||||
| src | the source of the image for an image avatar. | `string` | — |
|
||||
| src-set | native attribute `srcset` of image avatar. | `string` | — |
|
||||
| alt | native attribute `alt` of image avatar. | `string` | — |
|
||||
| fit | set how the image fit its container for an image avatar. | ^[enum]`'fill' \| 'contain' \| 'cover' \| 'none' \| 'scale-down'` | cover |
|
||||
|
||||
### Events
|
||||
### Avatar Events
|
||||
|
||||
| Name | Description | Type |
|
||||
| ----- | ------------------------------ | ------------------------------- |
|
||||
| error | trigger when image load error. | ^[Function]`(e: Event) => void` |
|
||||
|
||||
### Slots
|
||||
### Avatar Slots
|
||||
|
||||
| Name | Description |
|
||||
| ------- | ------------------------- |
|
||||
| default | customize avatar content. |
|
||||
|
||||
## AvatarGroup API ^(2.13.1)
|
||||
|
||||
### AvatarGroup Attributes
|
||||
|
||||
| Name | Description | Type | Default |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| size | control the size of avatars in this avatar-group | ^[number] / ^[enum]`'large' \| 'default' \| 'small'` | — |
|
||||
| shape | control the shape of avatars in this avatar-group | ^[enum]`'circle' \| 'square'` | — |
|
||||
| collapse-avatars | whether to collapse avatars | ^[boolean] | false |
|
||||
| collapse-avatars-tooltip | whether show all collapsed avatars when mouse hover text of the collapse-avatar. To use this, `collapse-avatars` must be true | ^[boolean] | false |
|
||||
| max-collapse-avatars | the max avatars number to be shown. To use this, `collapse-avatars` must be true | ^[number] | 1 |
|
||||
| effect | tooltip theme, built-in theme: `dark` / `light` | ^[enum]`'dark' \| 'light'` / ^[string] | light |
|
||||
| placement | placement of tooltip | ^[enum]`'top' \| 'top-start' \| 'top-end' \| 'bottom' \| 'bottom-start' \| 'bottom-end' \| 'left' \| 'left-start' \| 'left-end' \| 'right' \| 'right-start' \| 'right-end'` | top |
|
||||
| popper-class | custom class name for tooltip | ^[string] | '' |
|
||||
| popper-style | custom style for tooltip | ^[string] / ^[object] | — |
|
||||
| collapse-class | custom class name for the collapse-avatar | ^[string] | '' |
|
||||
| collapse-style | custom style for the collapse-avatar | ^[string] / ^[object] | — |
|
||||
|
||||
51
docs/examples/avatar/group.vue
Normal file
51
docs/examples/avatar/group.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div class="m-4">
|
||||
<p>default</p>
|
||||
<el-avatar-group>
|
||||
<el-avatar v-for="number in 5" :key="number" :src="circleUrl" />
|
||||
</el-avatar-group>
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<p>use collapse-avatars</p>
|
||||
<el-avatar-group collapse-avatars>
|
||||
<el-avatar v-for="number in 5" :key="number" :src="circleUrl" />
|
||||
</el-avatar-group>
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<p>use collapse-class and collapse-style</p>
|
||||
<el-avatar-group
|
||||
collapse-avatars
|
||||
:collapse-style="{ 'background-color': '#d9ecff' }"
|
||||
collapse-class="my-collapse-avatar"
|
||||
>
|
||||
<el-avatar v-for="number in 5" :key="number" :src="circleUrl" />
|
||||
</el-avatar-group>
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<p>use max-collapse-avatars</p>
|
||||
<el-avatar-group collapse-avatars :max-collapse-avatars="3">
|
||||
<el-avatar v-for="number in 5" :key="number" :src="circleUrl" />
|
||||
</el-avatar-group>
|
||||
</div>
|
||||
<div class="m-4">
|
||||
<p>use collapse-avatars-tooltip</p>
|
||||
<el-avatar-group
|
||||
collapse-avatars
|
||||
:max-collapse-avatars="3"
|
||||
collapse-avatars-tooltip
|
||||
>
|
||||
<el-avatar v-for="number in 5" :key="number" :src="circleUrl" />
|
||||
</el-avatar-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const circleUrl =
|
||||
'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.my-collapse-avatar {
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
3
packages/components/avatar-group/style/css.ts
Normal file
3
packages/components/avatar-group/style/css.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import '@element-plus/components/base/style/css'
|
||||
import '@element-plus/theme-chalk/el-avatar-group.css'
|
||||
import '@element-plus/components/tooltip/style/css'
|
||||
3
packages/components/avatar-group/style/index.ts
Normal file
3
packages/components/avatar-group/style/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import '@element-plus/components/base/style'
|
||||
import '@element-plus/theme-chalk/src/avatar-group.scss'
|
||||
import '@element-plus/components/tooltip/style'
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
} from '@element-plus/test-utils/mock'
|
||||
import { stableLoad } from '@element-plus/test-utils/stable-load'
|
||||
import Avatar from '../src/avatar.vue'
|
||||
import AvatarGroup from '../src/avatar-group'
|
||||
|
||||
describe('Avatar.vue', () => {
|
||||
mockImageEvent()
|
||||
@@ -96,3 +97,61 @@ describe('Avatar.vue', () => {
|
||||
expect(wrapper.find('img').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Avatar Group', () => {
|
||||
test('render test', () => {
|
||||
const wrapper = mount(
|
||||
<AvatarGroup size="small" shape="square">
|
||||
<Avatar />
|
||||
<Avatar size="large" shape="circle"></Avatar>
|
||||
<Avatar />
|
||||
<Avatar size="large" shape="circle"></Avatar>
|
||||
<Avatar />
|
||||
</AvatarGroup>
|
||||
)
|
||||
|
||||
expect(wrapper.findAll('.el-avatar').length).toBe(5)
|
||||
expect(wrapper.findAll('.el-avatar--small').length).toBe(3)
|
||||
expect(wrapper.findAll('.el-avatar--large').length).toBe(2)
|
||||
expect(wrapper.findAll('.el-avatar--circle').length).toBe(2)
|
||||
expect(wrapper.findAll('.el-avatar--square').length).toBe(3)
|
||||
})
|
||||
|
||||
test('collapse-class & collapse-style', () => {
|
||||
const collapseStyle = 'background-color: red;'
|
||||
const wrapper = mount(
|
||||
<AvatarGroup
|
||||
collapseAvatars
|
||||
collapseClass="collapse-avatar"
|
||||
collapseStyle={collapseStyle}
|
||||
>
|
||||
<Avatar />
|
||||
<Avatar />
|
||||
</AvatarGroup>
|
||||
)
|
||||
|
||||
const collapseAvatar = wrapper.findAll('.el-avatar')[1]
|
||||
expect(collapseAvatar.text()).toBe('+ 1')
|
||||
expect(collapseAvatar.classes()).toContain('collapse-avatar')
|
||||
expect(collapseAvatar.attributes('style')).toContain(
|
||||
'background-color: red;'
|
||||
)
|
||||
})
|
||||
|
||||
test('collapse-avatars-tooltip', async () => {
|
||||
const wrapper = mount(
|
||||
<AvatarGroup collapseAvatars collapseAvatarsTooltip>
|
||||
<Avatar />
|
||||
<Avatar />
|
||||
</AvatarGroup>
|
||||
)
|
||||
|
||||
const collapseAvatar = wrapper.findAll('.el-avatar')[1]
|
||||
await collapseAvatar.trigger('mouseenter')
|
||||
await nextTick()
|
||||
|
||||
const tooltip = wrapper.findComponent({ name: 'ElTooltip' })
|
||||
expect(tooltip.exists()).toBe(true)
|
||||
expect(tooltip.html()).toContain('el-avatar')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { withInstall } from '@element-plus/utils'
|
||||
import { withInstall, withNoopInstall } from '@element-plus/utils'
|
||||
import Avatar from './src/avatar.vue'
|
||||
import AvatarGroup from './src/avatar-group'
|
||||
|
||||
import type { SFCWithInstall } from '@element-plus/utils'
|
||||
|
||||
export const ElAvatar: SFCWithInstall<typeof Avatar> = withInstall(Avatar)
|
||||
export const ElAvatar: SFCWithInstall<typeof Avatar> & {
|
||||
AvatarGroup: typeof AvatarGroup
|
||||
} = withInstall(Avatar, {
|
||||
AvatarGroup,
|
||||
})
|
||||
export const ElAvatarGroup: SFCWithInstall<typeof AvatarGroup> =
|
||||
withNoopInstall(AvatarGroup)
|
||||
export default ElAvatar
|
||||
|
||||
export * from './src/avatar'
|
||||
export type { AvatarInstance } from './src/instance'
|
||||
export * from './src/constants'
|
||||
export * from './src/avatar-group-props'
|
||||
export type { AvatarInstance, AvatarGroupInstance } from './src/instance'
|
||||
|
||||
70
packages/components/avatar/src/avatar-group-props.ts
Normal file
70
packages/components/avatar/src/avatar-group-props.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { placements } from '@popperjs/core'
|
||||
import { useTooltipContentProps } from '@element-plus/components/tooltip'
|
||||
import { buildProps, definePropType } from '@element-plus/utils'
|
||||
import { avatarProps } from './avatar'
|
||||
|
||||
import type { ExtractPropTypes, ExtractPublicPropTypes, StyleValue } from 'vue'
|
||||
import type { Placement, PopperEffect } from '@element-plus/components/popper'
|
||||
|
||||
export const avatarGroupProps = buildProps({
|
||||
/**
|
||||
* @description control the size of avatars in this avatar-group
|
||||
*/
|
||||
size: avatarProps.size,
|
||||
/**
|
||||
* @description control the shape of avatars in this avatar-group
|
||||
*/
|
||||
shape: avatarProps.shape,
|
||||
/**
|
||||
* @description whether to collapse avatars
|
||||
*/
|
||||
collapseAvatars: Boolean,
|
||||
/**
|
||||
* @description whether show all collapsed avatars when mouse hover text of the collapse-avatar. To use this, `collapse-avatars` must be true
|
||||
*/
|
||||
collapseAvatarsTooltip: Boolean,
|
||||
/**
|
||||
* @description the max avatars number to be shown. To use this, `collapse-avatars` must be true
|
||||
*/
|
||||
maxCollapseAvatars: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
/**
|
||||
* @description tooltip theme, built-in theme: `dark` / `light`
|
||||
*/
|
||||
effect: {
|
||||
type: definePropType<PopperEffect>(String),
|
||||
default: 'light',
|
||||
},
|
||||
/**
|
||||
* @description placement of tooltip
|
||||
*/
|
||||
placement: {
|
||||
type: definePropType<Placement>(String),
|
||||
values: placements,
|
||||
default: 'top',
|
||||
},
|
||||
/**
|
||||
* @description custom class name for tooltip
|
||||
*/
|
||||
popperClass: useTooltipContentProps.popperClass,
|
||||
/**
|
||||
* @description custom style for tooltip
|
||||
*/
|
||||
popperStyle: useTooltipContentProps.popperStyle,
|
||||
/**
|
||||
* @description custom class name for the collapse-avatar
|
||||
*/
|
||||
collapseClass: String,
|
||||
/**
|
||||
* @description custom style for the collapse-avatar
|
||||
*/
|
||||
collapseStyle: {
|
||||
type: definePropType<StyleValue>([String, Array, Object]),
|
||||
},
|
||||
} as const)
|
||||
export type AvatarGroupProps = ExtractPropTypes<typeof avatarGroupProps>
|
||||
export type AvatarGroupPropsPublic = ExtractPublicPropTypes<
|
||||
typeof avatarGroupProps
|
||||
>
|
||||
77
packages/components/avatar/src/avatar-group.tsx
Normal file
77
packages/components/avatar/src/avatar-group.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
cloneVNode,
|
||||
defineComponent,
|
||||
isVNode,
|
||||
provide,
|
||||
reactive,
|
||||
toRef,
|
||||
} from 'vue'
|
||||
import { flattedChildren } from '@element-plus/utils'
|
||||
import ElTooltip from '@element-plus/components/tooltip'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import ElAvatar from './avatar.vue'
|
||||
import { avatarGroupContextKey } from './constants'
|
||||
import { avatarGroupProps } from './avatar-group-props'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ElAvatarGroup',
|
||||
props: avatarGroupProps,
|
||||
setup(props, { slots }) {
|
||||
const ns = useNamespace('avatar-group')
|
||||
|
||||
provide(
|
||||
avatarGroupContextKey,
|
||||
reactive({
|
||||
size: toRef(props, 'size'),
|
||||
shape: toRef(props, 'shape'),
|
||||
})
|
||||
)
|
||||
|
||||
return () => {
|
||||
const avatars = flattedChildren(slots.default?.() ?? [])
|
||||
let visibleAvatars = avatars
|
||||
|
||||
const showCollapseAvatar =
|
||||
props.collapseAvatars && avatars.length > props.maxCollapseAvatars
|
||||
|
||||
if (showCollapseAvatar) {
|
||||
visibleAvatars = avatars.slice(0, props.maxCollapseAvatars)
|
||||
const hiddenAvatars = avatars.slice(props.maxCollapseAvatars)
|
||||
|
||||
visibleAvatars.push(
|
||||
<ElTooltip
|
||||
popperClass={props.popperClass}
|
||||
popperStyle={props.popperStyle}
|
||||
placement={props.placement}
|
||||
effect={props.effect}
|
||||
disabled={!props.collapseAvatarsTooltip}
|
||||
>
|
||||
{{
|
||||
default: () => (
|
||||
<ElAvatar
|
||||
size={props.size}
|
||||
shape={props.shape}
|
||||
class={props.collapseClass}
|
||||
style={props.collapseStyle}
|
||||
>
|
||||
+ {hiddenAvatars.length}
|
||||
</ElAvatar>
|
||||
),
|
||||
content: () => (
|
||||
<div class={ns.e('collapse-avatars')}>
|
||||
{hiddenAvatars.map((node, idx) =>
|
||||
isVNode(node)
|
||||
? cloneVNode(node, { key: node.key ?? idx })
|
||||
: node
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
</ElTooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return <div class={ns.b()}>{visibleAvatars}</div>
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -19,7 +19,6 @@ export const avatarProps = buildProps({
|
||||
size: {
|
||||
type: [Number, String],
|
||||
values: componentSizes,
|
||||
default: '',
|
||||
validator: (val: unknown): val is number => isNumber(val),
|
||||
},
|
||||
/**
|
||||
@@ -28,7 +27,6 @@ export const avatarProps = buildProps({
|
||||
shape: {
|
||||
type: String,
|
||||
values: ['circle', 'square'],
|
||||
default: 'circle',
|
||||
},
|
||||
/**
|
||||
* @description representation type to icon, more info on icon component.
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { computed, inject, ref, watch } from 'vue'
|
||||
import { ElIcon } from '@element-plus/components/icon'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { addUnit, isNumber, isString } from '@element-plus/utils'
|
||||
import { avatarEmits, avatarProps } from './avatar'
|
||||
import { avatarGroupContextKey } from './constants'
|
||||
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
@@ -31,24 +32,30 @@ defineOptions({
|
||||
const props = defineProps(avatarProps)
|
||||
const emit = defineEmits(avatarEmits)
|
||||
|
||||
const avatarGroupContext = inject(avatarGroupContextKey, undefined)
|
||||
|
||||
const ns = useNamespace('avatar')
|
||||
|
||||
const hasLoadError = ref(false)
|
||||
|
||||
const size = computed(() => props.size ?? avatarGroupContext?.size)
|
||||
const shape = computed(
|
||||
() => props.shape ?? avatarGroupContext?.shape ?? 'circle'
|
||||
)
|
||||
|
||||
const avatarClass = computed(() => {
|
||||
const { size, icon, shape } = props
|
||||
const { icon } = props
|
||||
const classList = [ns.b()]
|
||||
if (isString(size)) classList.push(ns.m(size))
|
||||
if (isString(size.value)) classList.push(ns.m(size.value))
|
||||
if (icon) classList.push(ns.m('icon'))
|
||||
if (shape) classList.push(ns.m(shape))
|
||||
if (shape.value) classList.push(ns.m(shape.value))
|
||||
return classList
|
||||
})
|
||||
|
||||
const sizeStyle = computed(() => {
|
||||
const { size } = props
|
||||
return isNumber(size)
|
||||
return isNumber(size.value)
|
||||
? (ns.cssVarBlock({
|
||||
size: addUnit(size)!,
|
||||
size: addUnit(size.value)!,
|
||||
}) as CSSProperties)
|
||||
: undefined
|
||||
})
|
||||
|
||||
11
packages/components/avatar/src/constants.ts
Normal file
11
packages/components/avatar/src/constants.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { InjectionKey } from 'vue'
|
||||
import type { AvatarProps } from './avatar'
|
||||
|
||||
export interface AvatarGroupContext {
|
||||
size?: AvatarProps['size']
|
||||
shape?: AvatarProps['shape']
|
||||
}
|
||||
|
||||
export const avatarGroupContextKey: InjectionKey<AvatarGroupContext> = Symbol(
|
||||
'avatarGroupContextKey'
|
||||
)
|
||||
@@ -1,3 +1,5 @@
|
||||
import type Avatar from './avatar.vue'
|
||||
import type AvatarGroup from './avatar-group'
|
||||
|
||||
export type AvatarInstance = InstanceType<typeof Avatar> & unknown
|
||||
export type AvatarGroupInstance = InstanceType<typeof AvatarGroup> & unknown
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ElAffix } from '@element-plus/components/affix'
|
||||
import { ElAlert } from '@element-plus/components/alert'
|
||||
import { ElAutocomplete } from '@element-plus/components/autocomplete'
|
||||
import { ElAvatar } from '@element-plus/components/avatar'
|
||||
import { ElAvatar, ElAvatarGroup } from '@element-plus/components/avatar'
|
||||
import { ElBacktop } from '@element-plus/components/backtop'
|
||||
import { ElBadge } from '@element-plus/components/badge'
|
||||
import {
|
||||
@@ -119,6 +119,7 @@ export default [
|
||||
ElAutocomplete,
|
||||
ElAutoResizer,
|
||||
ElAvatar,
|
||||
ElAvatarGroup,
|
||||
ElBacktop,
|
||||
ElBadge,
|
||||
ElBreadcrumb,
|
||||
|
||||
25
packages/theme-chalk/src/avatar-group.scss
Normal file
25
packages/theme-chalk/src/avatar-group.scss
Normal file
@@ -0,0 +1,25 @@
|
||||
@use 'mixins/mixins' as *;
|
||||
@use 'mixins/var' as *;
|
||||
@use 'common/var' as *;
|
||||
|
||||
@include b(avatar-group) {
|
||||
@include set-component-css-var('avatar-group', $avatar-group);
|
||||
|
||||
display: inline-flex;
|
||||
|
||||
.#{$namespace}-avatar {
|
||||
border: 1px solid getCssVar('border-color-extra-light');
|
||||
}
|
||||
|
||||
.#{$namespace}-avatar:not(:first-child) {
|
||||
margin-left: getCssVar('avatar-group', 'item-gap');
|
||||
}
|
||||
|
||||
@include e(collapse-avatars) {
|
||||
@include set-component-css-var('avatar-group', $avatar-group);
|
||||
|
||||
.#{$namespace}-avatar:not(:first-child) {
|
||||
margin-left: getCssVar('avatar-group', 'collapse-item-gap');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1523,6 +1523,15 @@ $avatar-size: map.merge(
|
||||
$avatar-size
|
||||
);
|
||||
|
||||
$avatar-group: () !default;
|
||||
$avatar-group: map.merge(
|
||||
(
|
||||
'item-gap': -8px,
|
||||
'collapse-item-gap': 4px,
|
||||
),
|
||||
$avatar-group
|
||||
);
|
||||
|
||||
// Empty
|
||||
// css3 var in packages/theme-chalk/src/empty.scss
|
||||
$empty: () !default;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
@use './aside.scss';
|
||||
@use './autocomplete.scss';
|
||||
@use './avatar.scss';
|
||||
@use './avatar-group.scss';
|
||||
@use './backtop.scss';
|
||||
@use './badge.scss';
|
||||
@use './breadcrumb-item.scss';
|
||||
|
||||
1
typings/global.d.ts
vendored
1
typings/global.d.ts
vendored
@@ -8,6 +8,7 @@ declare module 'vue' {
|
||||
ElAutoResizer: typeof import('element-plus')['ElAutoResizer']
|
||||
ElAutocomplete: typeof import('element-plus')['ElAutocomplete']
|
||||
ElAvatar: typeof import('element-plus')['ElAvatar']
|
||||
ElAvatarGroup: typeof import('element-plus')['ElAvatarGroup']
|
||||
ElAnchor: typeof import('element-plus')['ElAnchor']
|
||||
ElAnchorLink: typeof import('element-plus')['ElAnchorLink']
|
||||
ElBacktop: typeof import('element-plus')['ElBacktop']
|
||||
|
||||
Reference in New Issue
Block a user