@volverjs/ui-vue 0.0.6-beta.1 → 0.0.6-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +361 -0
- package/dist/components/VvAvatarGroup/VvAvatarGroup.umd.js +1 -0
- package/dist/components/VvAvatarGroup/VvAvatarGroup.vue.d.ts +68 -0
- package/dist/components/VvAvatarGroup/index.d.ts +38 -0
- package/dist/icons.es.js +3 -3
- package/dist/icons.umd.js +1 -1
- package/dist/stories/AvatarGroup/AvatarGroup.settings.d.ts +56 -0
- package/dist/stories/AvatarGroup/AvatarGroup.test.d.ts +2 -0
- package/package.json +9 -1
- package/src/assets/icons/detailed.json +1 -1
- package/src/assets/icons/normal.json +1 -1
- package/src/assets/icons/simple.json +1 -1
- package/src/components/VvAvatarGroup/VvAvatarGroup.vue +65 -0
- package/src/components/VvAvatarGroup/index.ts +28 -0
- package/src/stories/Avatar/Avatar.settings.ts +1 -9
- package/src/stories/AvatarGroup/AvatarGroup.settings.ts +60 -0
- package/src/stories/AvatarGroup/AvatarGroup.stories.mdx +30 -0
- package/src/stories/AvatarGroup/AvatarGroup.test.ts +36 -0
- package/src/stories/AvatarGroup/AvatarGroupModifiers.stories.mdx +24 -0
- package/src/stories/AvatarGroup/AvatarGroupSlotDefault.stories.mdx +45 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { VvAvatarGroupProps } from '@/components/VvAvatarGroup'
|
|
3
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps(VvAvatarGroupProps)
|
|
6
|
+
const { modifiers, items, toShow, totalItems, avatarModifiers } =
|
|
7
|
+
toRefs(props)
|
|
8
|
+
|
|
9
|
+
// bem css classes
|
|
10
|
+
const bemCssClasses = useModifiers('vv-avatar-group', modifiers)
|
|
11
|
+
|
|
12
|
+
const stringModifiers = computed(() => {
|
|
13
|
+
if (avatarModifiers?.value && Array.isArray(avatarModifiers?.value)) {
|
|
14
|
+
return avatarModifiers.value.join(' ')
|
|
15
|
+
}
|
|
16
|
+
return avatarModifiers?.value || ''
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const avatarItems = computed(() => {
|
|
20
|
+
return items.value.slice(0, toShow.value).map((item, index) => {
|
|
21
|
+
let modifiers: string[] = []
|
|
22
|
+
let itemModifiers: string[] = []
|
|
23
|
+
|
|
24
|
+
if (avatarModifiers?.value) {
|
|
25
|
+
modifiers = Array.isArray(avatarModifiers?.value)
|
|
26
|
+
? avatarModifiers?.value
|
|
27
|
+
: [avatarModifiers?.value]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (item.modifiers) {
|
|
31
|
+
itemModifiers = Array.isArray(item.modifiers)
|
|
32
|
+
? item.modifiers
|
|
33
|
+
: [item.modifiers]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
...item,
|
|
38
|
+
key: item.key || `${index}_${new Date().getTime()}`,
|
|
39
|
+
modifiers: [...modifiers, ...itemModifiers],
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<span :class="bemCssClasses">
|
|
47
|
+
<slot name="default">
|
|
48
|
+
<VvAvatar
|
|
49
|
+
v-for="avatarItem in avatarItems"
|
|
50
|
+
:key="avatarItem.key"
|
|
51
|
+
v-bind="{
|
|
52
|
+
modifiers: avatarItem.modifiers,
|
|
53
|
+
imgSrc: avatarItem.imgSrc,
|
|
54
|
+
}"
|
|
55
|
+
>
|
|
56
|
+
<span v-if="avatarItem.text">{{ avatarItem.text }}</span>
|
|
57
|
+
</VvAvatar>
|
|
58
|
+
<VvAvatar
|
|
59
|
+
v-if="(totalItems || items.length) > toShow"
|
|
60
|
+
:modifiers="`${stringModifiers} surface bordered`"
|
|
61
|
+
>{{ `+${(totalItems || items.length) - toShow}` }}</VvAvatar
|
|
62
|
+
>
|
|
63
|
+
</slot>
|
|
64
|
+
</span>
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ModifiersProps } from '@/props'
|
|
2
|
+
|
|
3
|
+
export type AvatarItem = {
|
|
4
|
+
key?: string
|
|
5
|
+
text?: string
|
|
6
|
+
imgSrc?: string
|
|
7
|
+
modifiers?: string | string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const VvAvatarGroupProps = {
|
|
11
|
+
...ModifiersProps,
|
|
12
|
+
/**
|
|
13
|
+
* avatar items
|
|
14
|
+
*/
|
|
15
|
+
items: {
|
|
16
|
+
type: Array<AvatarItem>,
|
|
17
|
+
default: () => [],
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
toShow: {
|
|
21
|
+
type: Number,
|
|
22
|
+
default: 3,
|
|
23
|
+
},
|
|
24
|
+
totalItems: {
|
|
25
|
+
type: Number,
|
|
26
|
+
},
|
|
27
|
+
avatarModifiers: [String, Array] as PropType<string | Array<string>>,
|
|
28
|
+
}
|
|
@@ -22,15 +22,7 @@ export const argTypes = {
|
|
|
22
22
|
},
|
|
23
23
|
modifiers: {
|
|
24
24
|
...ModifiersArgTypes.modifiers,
|
|
25
|
-
options: [
|
|
26
|
-
'rounded',
|
|
27
|
-
'square',
|
|
28
|
-
'bordered',
|
|
29
|
-
'ring',
|
|
30
|
-
'circle',
|
|
31
|
-
'lg',
|
|
32
|
-
'md',
|
|
33
|
-
],
|
|
25
|
+
options: ['rounded', 'square', 'bordered', 'ring', 'lg', 'md'],
|
|
34
26
|
},
|
|
35
27
|
imgSrc: {
|
|
36
28
|
type: {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { VvAvatarGroupProps } from '@/components/VvAvatarGroup'
|
|
2
|
+
import { DefaultSlotArgTypes, ModifiersArgTypes } from '@/stories/argTypes'
|
|
3
|
+
|
|
4
|
+
export const defaultArgs = {
|
|
5
|
+
...propsToObject(VvAvatarGroupProps),
|
|
6
|
+
items: [
|
|
7
|
+
{
|
|
8
|
+
text: 'MR',
|
|
9
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
10
|
+
modifiers: 'rounded',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
14
|
+
modifiers: 'rounded',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
18
|
+
modifiers: 'rounded',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
imgSrc: 'https://i.pravatar.cc/300',
|
|
22
|
+
modifiers: 'rounded',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
avatarModifiers: 'rounded',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const argTypes = {
|
|
29
|
+
...DefaultSlotArgTypes,
|
|
30
|
+
default: {
|
|
31
|
+
description: 'Default slot',
|
|
32
|
+
control: {
|
|
33
|
+
type: 'text',
|
|
34
|
+
},
|
|
35
|
+
table: {
|
|
36
|
+
category: 'Slots',
|
|
37
|
+
type: {
|
|
38
|
+
summary: 'html',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
modifiers: {
|
|
43
|
+
...ModifiersArgTypes.modifiers,
|
|
44
|
+
options: ['tight', 'relaxed'],
|
|
45
|
+
},
|
|
46
|
+
avatarModifiers: {
|
|
47
|
+
...ModifiersArgTypes.modifiers,
|
|
48
|
+
options: ['rounded', 'square', 'bordered', 'ring', 'lg', 'md'],
|
|
49
|
+
},
|
|
50
|
+
toShow: {
|
|
51
|
+
control: {
|
|
52
|
+
type: 'number',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
totalItems: {
|
|
56
|
+
control: {
|
|
57
|
+
type: 'number',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
4
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
5
|
+
|
|
6
|
+
<Meta
|
|
7
|
+
title="Components/AvatarGroup"
|
|
8
|
+
component={VvAvatarGroup}
|
|
9
|
+
args={defaultArgs}
|
|
10
|
+
argTypes={argTypes}
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
export const Template = (args) => ({
|
|
14
|
+
components: { VvAvatarGroup },
|
|
15
|
+
setup() {
|
|
16
|
+
return { args }
|
|
17
|
+
},
|
|
18
|
+
template: /* html */ `
|
|
19
|
+
<div class="m-md">
|
|
20
|
+
<vv-avatar-group v-bind="args" data-testId="element">
|
|
21
|
+
<template v-if="args.default">{{ args.default }}</template>
|
|
22
|
+
</vv-avatar-group>
|
|
23
|
+
</div>`,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
<Canvas>
|
|
27
|
+
<Story name="Default" play={defaultTest}>
|
|
28
|
+
{Template.bind()}
|
|
29
|
+
</Story>
|
|
30
|
+
</Canvas>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PlayAttributes } from '@/test/types'
|
|
2
|
+
import { expect } from '@/test/expect'
|
|
3
|
+
import { within } from '@storybook/testing-library'
|
|
4
|
+
|
|
5
|
+
export async function defaultTest({ canvasElement, args }: PlayAttributes) {
|
|
6
|
+
const element = (await within(canvasElement).findByTestId(
|
|
7
|
+
'element',
|
|
8
|
+
)) as HTMLElement
|
|
9
|
+
|
|
10
|
+
// slot default
|
|
11
|
+
if (!args.default && !args.items && !args.items?.length) {
|
|
12
|
+
throw new Error('Default slot or items is required!')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const modifiers =
|
|
16
|
+
!args.modifiers || Array.isArray(args.modifiers)
|
|
17
|
+
? args.modifiers
|
|
18
|
+
: [args.modifiers]
|
|
19
|
+
|
|
20
|
+
// modifiers
|
|
21
|
+
if (modifiers) {
|
|
22
|
+
for (const modifier of modifiers) {
|
|
23
|
+
expect(element).toHaveClass(`vv-avatar-group--${modifier}`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// check children numbers
|
|
28
|
+
if (args.items && args.items.length && !args.default) {
|
|
29
|
+
if ((args.totalItems || args.items.length) > args.toShow) {
|
|
30
|
+
expect(element.children.length).toEqual(args.toShow + 1)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// check accessibility
|
|
35
|
+
await expect(element).toHaveNoViolations()
|
|
36
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
4
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
5
|
+
import { Template } from './AvatarGroup.stories.mdx'
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Components/AvatarGroup/Modifiers"
|
|
9
|
+
component={VvAvatarGroup}
|
|
10
|
+
args={defaultArgs}
|
|
11
|
+
argTypes={argTypes}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<Canvas>
|
|
15
|
+
<Story name="Tight" play={defaultTest} args={{ modifiers: 'tight' }}>
|
|
16
|
+
{Template.bind({})}
|
|
17
|
+
</Story>
|
|
18
|
+
</Canvas>
|
|
19
|
+
|
|
20
|
+
<Canvas>
|
|
21
|
+
<Story name="Relaxed" play={defaultTest} args={{ modifiers: 'relaxed' }}>
|
|
22
|
+
{Template.bind({})}
|
|
23
|
+
</Story>
|
|
24
|
+
</Canvas>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs'
|
|
2
|
+
import VvAvatarGroup from '@/components/VvAvatarGroup/VvAvatarGroup.vue'
|
|
3
|
+
import VvAvatar from '@/components/VvAvatar/VvAvatar.vue'
|
|
4
|
+
import { defaultArgs, argTypes } from './AvatarGroup.settings'
|
|
5
|
+
import { defaultTest } from './AvatarGroup.test'
|
|
6
|
+
import { Template } from './AvatarGroup.stories.mdx'
|
|
7
|
+
|
|
8
|
+
<Meta
|
|
9
|
+
title="Components/AvatarGroup/Slots"
|
|
10
|
+
component={VvAvatarGroup}
|
|
11
|
+
args={defaultArgs}
|
|
12
|
+
argTypes={argTypes}
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
export const TemplateSlot = (args) => ({
|
|
16
|
+
components: { VvAvatarGroup, VvAvatar },
|
|
17
|
+
setup() {
|
|
18
|
+
return { args }
|
|
19
|
+
},
|
|
20
|
+
template: /* html */ `
|
|
21
|
+
<div class="m-md">
|
|
22
|
+
<vv-avatar-group v-bind="args" data-testId="element" modifiers="relaxed">
|
|
23
|
+
<vv-avatar modifiers="rounded">MR</vv-avatar>
|
|
24
|
+
<vv-avatar modifiers="rounded accent">PB</vv-avatar>
|
|
25
|
+
<vv-avatar imgSrc="https://i.pravatar.cc/300" modifiers="rounded" />
|
|
26
|
+
<vv-avatar modifiers="rounded surface">+3</vv-avatar>
|
|
27
|
+
</vv-avatar-group>
|
|
28
|
+
</div>`,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
<Canvas>
|
|
32
|
+
<Story
|
|
33
|
+
name="Default"
|
|
34
|
+
play={defaultTest}
|
|
35
|
+
argTypes={{
|
|
36
|
+
default: {
|
|
37
|
+
control: {
|
|
38
|
+
disable: true,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
}}
|
|
42
|
+
>
|
|
43
|
+
{TemplateSlot.bind({})}
|
|
44
|
+
</Story>
|
|
45
|
+
</Canvas>
|