@vaadin/avatar-group 25.0.0-alpha2 → 25.0.0-alpha20
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/package.json +14 -15
- package/src/styles/vaadin-avatar-group-base-styles.js +55 -0
- package/src/styles/vaadin-avatar-group-menu-base-styles.js +21 -0
- package/src/styles/vaadin-avatar-group-menu-item-base-styles.js +17 -0
- package/src/vaadin-avatar-group-menu-item.js +5 -11
- package/src/vaadin-avatar-group-menu.js +5 -18
- package/src/vaadin-avatar-group-mixin.d.ts +1 -3
- package/src/vaadin-avatar-group-mixin.js +108 -151
- package/src/vaadin-avatar-group-overlay.js +6 -4
- package/src/vaadin-avatar-group.d.ts +4 -3
- package/src/vaadin-avatar-group.js +12 -6
- package/vaadin-avatar-group.js +1 -1
- package/web-types.json +4 -26
- package/web-types.lit.json +4 -11
- package/src/vaadin-avatar-group-styles.js +0 -51
- package/theme/lumo/vaadin-avatar-group-styles.d.ts +0 -3
- package/theme/lumo/vaadin-avatar-group-styles.js +0 -84
- package/theme/lumo/vaadin-avatar-group.d.ts +0 -3
- package/theme/lumo/vaadin-avatar-group.js +0 -3
- /package/src/{vaadin-avatar-group-styles.d.ts → styles/vaadin-avatar-group-base-styles.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/avatar-group",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-alpha20",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"type": "module",
|
|
22
22
|
"files": [
|
|
23
23
|
"src",
|
|
24
|
-
"theme",
|
|
25
24
|
"vaadin-*.d.ts",
|
|
26
25
|
"vaadin-*.js",
|
|
27
26
|
"web-types.json",
|
|
@@ -36,26 +35,26 @@
|
|
|
36
35
|
],
|
|
37
36
|
"dependencies": {
|
|
38
37
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
39
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
40
|
-
"@vaadin/avatar": "25.0.0-
|
|
41
|
-
"@vaadin/component-base": "25.0.0-
|
|
42
|
-
"@vaadin/item": "25.0.0-
|
|
43
|
-
"@vaadin/list-box": "25.0.0-
|
|
44
|
-
"@vaadin/overlay": "25.0.0-
|
|
45
|
-
"@vaadin/tooltip": "25.0.0-
|
|
46
|
-
"@vaadin/vaadin-
|
|
47
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha2",
|
|
38
|
+
"@vaadin/a11y-base": "25.0.0-alpha20",
|
|
39
|
+
"@vaadin/avatar": "25.0.0-alpha20",
|
|
40
|
+
"@vaadin/component-base": "25.0.0-alpha20",
|
|
41
|
+
"@vaadin/item": "25.0.0-alpha20",
|
|
42
|
+
"@vaadin/list-box": "25.0.0-alpha20",
|
|
43
|
+
"@vaadin/overlay": "25.0.0-alpha20",
|
|
44
|
+
"@vaadin/tooltip": "25.0.0-alpha20",
|
|
45
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha20",
|
|
48
46
|
"lit": "^3.0.0"
|
|
49
47
|
},
|
|
50
48
|
"devDependencies": {
|
|
51
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
52
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
49
|
+
"@vaadin/chai-plugins": "25.0.0-alpha20",
|
|
50
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha20",
|
|
53
51
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
54
|
-
"
|
|
52
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-alpha20",
|
|
53
|
+
"sinon": "^21.0.0"
|
|
55
54
|
},
|
|
56
55
|
"web-types": [
|
|
57
56
|
"web-types.json",
|
|
58
57
|
"web-types.lit.json"
|
|
59
58
|
],
|
|
60
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "c948aae591a30b432f3784000d4677674cae56e0"
|
|
61
60
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import '@vaadin/component-base/src/styles/style-props.js';
|
|
7
|
+
import { css } from 'lit';
|
|
8
|
+
|
|
9
|
+
export const avatarGroupStyles = css`
|
|
10
|
+
:host {
|
|
11
|
+
display: block;
|
|
12
|
+
width: 100%; /* prevent collapsing inside non-stretching column flex */
|
|
13
|
+
/* 1: last on top */
|
|
14
|
+
/* -1: first on top */
|
|
15
|
+
--_dir: 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:host([theme~='reverse']) {
|
|
19
|
+
--_dir: -1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
:host([hidden]) {
|
|
23
|
+
display: none !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[part='container'] {
|
|
27
|
+
display: flex;
|
|
28
|
+
position: relative;
|
|
29
|
+
width: 100%;
|
|
30
|
+
flex-wrap: nowrap;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
::slotted(vaadin-avatar) {
|
|
34
|
+
--_overlap: max(0px, var(--vaadin-avatar-group-overlap, 8px));
|
|
35
|
+
--_gap: max(0px, var(--vaadin-avatar-group-gap, 2px));
|
|
36
|
+
mask-image: url('data:image/svg+xml;utf8,<svg viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M300 0H0V300H300V0ZM150 200C177.614 200 200 177.614 200 150C200 122.386 177.614 100 150 100C122.386 100 100 122.386 100 150C100 177.614 122.386 200 150 200Z" fill="black"/></svg>');
|
|
37
|
+
mask-size: calc((100% - var(--vaadin-focus-ring-width) * 2) * 3);
|
|
38
|
+
mask-position: calc(50% + (100% - var(--vaadin-focus-ring-width) * 2 - var(--_overlap)) * var(--_d));
|
|
39
|
+
--_d: var(--_dir);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:host(:dir(rtl)) ::slotted(vaadin-avatar) {
|
|
43
|
+
--_d: calc(var(--_dir) * -1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
::slotted(vaadin-avatar:not(:first-of-type)) {
|
|
47
|
+
margin-inline-start: calc((var(--vaadin-focus-ring-width) + var(--_overlap) - var(--_gap)) * -1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:host(:not([theme~='reverse'])) ::slotted(vaadin-avatar:last-child),
|
|
51
|
+
:host(:not([theme~='reverse']):not([has-overflow])) ::slotted(vaadin-avatar:nth-last-child(2)),
|
|
52
|
+
:host([theme~='reverse']) ::slotted(vaadin-avatar:first-of-type) {
|
|
53
|
+
mask-image: none;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
|
|
8
|
+
export const avatarGroupMenuStyles = css`
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
padding: var(--vaadin-item-overlay-padding, 4px);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:host([hidden]) {
|
|
15
|
+
display: none !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[part='items'] {
|
|
19
|
+
display: contents;
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css } from 'lit';
|
|
7
|
+
import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-base-styles.js';
|
|
8
|
+
|
|
9
|
+
const menuItemStyles = css`
|
|
10
|
+
[part='content'] {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: inherit;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
export const avatarGroupMenuItemStyles = [itemStyles, menuItemStyles];
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { html, LitElement } from 'lit';
|
|
7
7
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
8
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
9
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
10
|
import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
|
|
11
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
11
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
+
import { avatarGroupMenuItemStyles } from './styles/vaadin-avatar-group-menu-item-base-styles.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* An element used internally by `<vaadin-avatar-group>`. Not intended to be used separately.
|
|
@@ -20,21 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
20
22
|
* @mixes ThemableMixin
|
|
21
23
|
* @protected
|
|
22
24
|
*/
|
|
23
|
-
class AvatarGroupMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
|
|
25
|
+
class AvatarGroupMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
24
26
|
static get is() {
|
|
25
27
|
return 'vaadin-avatar-group-menu-item';
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
static get styles() {
|
|
29
|
-
return
|
|
30
|
-
:host {
|
|
31
|
-
display: inline-block;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
:host([hidden]) {
|
|
35
|
-
display: none !important;
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
31
|
+
return avatarGroupMenuItemStyles;
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
/** @protected */
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { html, LitElement } from 'lit';
|
|
7
7
|
import { ListMixin } from '@vaadin/a11y-base/src/list-mixin.js';
|
|
8
8
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
9
9
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
10
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
11
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
11
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
+
import { avatarGroupMenuStyles } from './styles/vaadin-avatar-group-menu-base-styles.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* An element used internally by `<vaadin-avatar-group>`. Not intended to be used separately.
|
|
@@ -20,28 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
20
22
|
* @mixes ThemableMixin
|
|
21
23
|
* @protected
|
|
22
24
|
*/
|
|
23
|
-
class AvatarGroupMenu extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
|
|
25
|
+
class AvatarGroupMenu extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
24
26
|
static get is() {
|
|
25
27
|
return 'vaadin-avatar-group-menu';
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
static get styles() {
|
|
29
|
-
return
|
|
30
|
-
:host {
|
|
31
|
-
display: flex;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
:host([hidden]) {
|
|
35
|
-
display: none !important;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
[part='items'] {
|
|
39
|
-
height: 100%;
|
|
40
|
-
width: 100%;
|
|
41
|
-
overflow-y: auto;
|
|
42
|
-
-webkit-overflow-scrolling: touch;
|
|
43
|
-
}
|
|
44
|
-
`;
|
|
31
|
+
return avatarGroupMenuStyles;
|
|
45
32
|
}
|
|
46
33
|
|
|
47
34
|
static get properties() {
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
7
|
import type { AvatarI18n } from '@vaadin/avatar/src/vaadin-avatar.js';
|
|
8
8
|
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
9
|
-
import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
10
9
|
import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
|
|
11
10
|
|
|
12
11
|
export interface AvatarGroupI18n extends AvatarI18n {
|
|
@@ -33,7 +32,6 @@ export declare function AvatarGroupMixin<T extends Constructor<HTMLElement>>(
|
|
|
33
32
|
base: T,
|
|
34
33
|
): Constructor<AvatarGroupMixinClass> &
|
|
35
34
|
Constructor<I18nMixinClass<AvatarGroupI18n>> &
|
|
36
|
-
Constructor<OverlayClassMixinClass> &
|
|
37
35
|
Constructor<ResizeMixinClass> &
|
|
38
36
|
T;
|
|
39
37
|
|
|
@@ -79,7 +77,7 @@ export declare class AvatarGroupMixinClass {
|
|
|
79
77
|
* just the individual properties you want to change.
|
|
80
78
|
*
|
|
81
79
|
* The object has the following JSON structure and default values:
|
|
82
|
-
* ```
|
|
80
|
+
* ```js
|
|
83
81
|
* {
|
|
84
82
|
* // Translation of the anonymous user avatar tooltip.
|
|
85
83
|
* anonymous: 'anonymous',
|
|
@@ -7,7 +7,6 @@ import { html, render } from 'lit';
|
|
|
7
7
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
8
8
|
import { announce } from '@vaadin/a11y-base/src/announce.js';
|
|
9
9
|
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
10
|
-
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
11
10
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
12
11
|
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
13
12
|
|
|
@@ -29,10 +28,9 @@ const DEFAULT_I18N = {
|
|
|
29
28
|
* @polymerMixin
|
|
30
29
|
* @mixes I18nMixin
|
|
31
30
|
* @mixes ResizeMixin
|
|
32
|
-
* @mixes OverlayClassMixin
|
|
33
31
|
*/
|
|
34
32
|
export const AvatarGroupMixin = (superClass) =>
|
|
35
|
-
class AvatarGroupMixinClass extends I18nMixin(DEFAULT_I18N, ResizeMixin(
|
|
33
|
+
class AvatarGroupMixinClass extends I18nMixin(DEFAULT_I18N, ResizeMixin(superClass)) {
|
|
36
34
|
static get properties() {
|
|
37
35
|
return {
|
|
38
36
|
/**
|
|
@@ -64,7 +62,6 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
64
62
|
*/
|
|
65
63
|
items: {
|
|
66
64
|
type: Array,
|
|
67
|
-
observer: '__itemsChanged',
|
|
68
65
|
sync: true,
|
|
69
66
|
},
|
|
70
67
|
|
|
@@ -79,13 +76,6 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
79
76
|
sync: true,
|
|
80
77
|
},
|
|
81
78
|
|
|
82
|
-
/** @private */
|
|
83
|
-
_avatars: {
|
|
84
|
-
type: Array,
|
|
85
|
-
value: () => [],
|
|
86
|
-
sync: true,
|
|
87
|
-
},
|
|
88
|
-
|
|
89
79
|
/** @private */
|
|
90
80
|
__itemsInView: {
|
|
91
81
|
type: Number,
|
|
@@ -93,23 +83,14 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
93
83
|
sync: true,
|
|
94
84
|
},
|
|
95
85
|
|
|
96
|
-
/** @private */
|
|
97
|
-
_overflow: {
|
|
98
|
-
type: Object,
|
|
99
|
-
sync: true,
|
|
100
|
-
},
|
|
101
|
-
|
|
102
86
|
/** @private */
|
|
103
87
|
_overflowItems: {
|
|
104
88
|
type: Array,
|
|
105
|
-
observer: '__overflowItemsChanged',
|
|
106
|
-
computed: '__computeOverflowItems(items, __itemsInView, maxItemsVisible)',
|
|
107
89
|
},
|
|
108
90
|
|
|
109
91
|
/** @private */
|
|
110
|
-
|
|
111
|
-
type:
|
|
112
|
-
sync: true,
|
|
92
|
+
_overflowLimit: {
|
|
93
|
+
type: Number,
|
|
113
94
|
},
|
|
114
95
|
|
|
115
96
|
/** @private */
|
|
@@ -120,24 +101,13 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
120
101
|
};
|
|
121
102
|
}
|
|
122
103
|
|
|
123
|
-
static get observers() {
|
|
124
|
-
return [
|
|
125
|
-
'__i18nItemsChanged(__effectiveI18n, items)',
|
|
126
|
-
'__openedChanged(_opened, _overflow)',
|
|
127
|
-
'__updateAvatarsTheme(_overflow, _avatars, _theme)',
|
|
128
|
-
'__updateAvatars(items, __itemsInView, maxItemsVisible, _overflow, __effectiveI18n)',
|
|
129
|
-
'__updateOverflowAvatar(_overflow, items, __itemsInView, maxItemsVisible)',
|
|
130
|
-
'__updateOverflowTooltip(_overflowTooltip, items, __itemsInView, maxItemsVisible)',
|
|
131
|
-
];
|
|
132
|
-
}
|
|
133
|
-
|
|
134
104
|
/**
|
|
135
105
|
* The object used to localize this component. To change the default
|
|
136
106
|
* localization, replace this with an object that provides all properties, or
|
|
137
107
|
* just the individual properties you want to change.
|
|
138
108
|
*
|
|
139
109
|
* The object has the following JSON structure and default values:
|
|
140
|
-
* ```
|
|
110
|
+
* ```js
|
|
141
111
|
* {
|
|
142
112
|
* // Translation of the anonymous user avatar tooltip.
|
|
143
113
|
* anonymous: 'anonymous',
|
|
@@ -167,13 +137,26 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
167
137
|
super.i18n = value;
|
|
168
138
|
}
|
|
169
139
|
|
|
140
|
+
/** @protected */
|
|
141
|
+
get _avatars() {
|
|
142
|
+
return [...this.children].filter((node) => node.localName === 'vaadin-avatar');
|
|
143
|
+
}
|
|
144
|
+
|
|
170
145
|
/** @protected */
|
|
171
146
|
ready() {
|
|
172
147
|
super.ready();
|
|
173
148
|
|
|
149
|
+
this._menuController = new SlotController(this, 'overlay', 'vaadin-avatar-group-menu', {
|
|
150
|
+
initializer: (menu) => {
|
|
151
|
+
menu.addEventListener('keydown', this._onListKeyDown.bind(this));
|
|
152
|
+
this._menuElement = menu;
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
174
156
|
this._overflowController = new SlotController(this, 'overflow', 'vaadin-avatar', {
|
|
175
157
|
initializer: (overflow) => {
|
|
176
158
|
overflow.setAttribute('role', 'button');
|
|
159
|
+
overflow.setAttribute('tabindex', '0');
|
|
177
160
|
overflow.setAttribute('aria-haspopup', 'menu');
|
|
178
161
|
overflow.setAttribute('aria-expanded', 'false');
|
|
179
162
|
overflow.addEventListener('click', (e) => this._onOverflowClick(e));
|
|
@@ -187,11 +170,11 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
187
170
|
this._overflowTooltip = tooltip;
|
|
188
171
|
},
|
|
189
172
|
});
|
|
173
|
+
|
|
174
|
+
this.addController(this._menuController);
|
|
190
175
|
this.addController(this._overflowController);
|
|
191
176
|
|
|
192
|
-
|
|
193
|
-
overlay.renderer = this.__overlayRenderer.bind(this);
|
|
194
|
-
this._overlayElement = overlay;
|
|
177
|
+
this._overlayElement = this.$.overlay;
|
|
195
178
|
}
|
|
196
179
|
|
|
197
180
|
/** @protected */
|
|
@@ -201,65 +184,91 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
201
184
|
this._opened = false;
|
|
202
185
|
}
|
|
203
186
|
|
|
204
|
-
/** @
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
*/
|
|
215
|
-
__overlayRenderer(root) {
|
|
216
|
-
let menu = root.firstElementChild;
|
|
217
|
-
if (!menu) {
|
|
218
|
-
menu = document.createElement('vaadin-avatar-group-menu');
|
|
219
|
-
menu.addEventListener('keydown', (event) => this._onListKeyDown(event));
|
|
220
|
-
root.appendChild(menu);
|
|
187
|
+
/** @protected */
|
|
188
|
+
willUpdate(props) {
|
|
189
|
+
super.willUpdate(props);
|
|
190
|
+
|
|
191
|
+
if (props.has('items') || props.has('__itemsInView') || props.has('maxItemsVisible')) {
|
|
192
|
+
// Calculate overflow limit only once to reuse it in updated() observers
|
|
193
|
+
const count = Array.isArray(this.items) ? this.items.length : 0;
|
|
194
|
+
const limit = this.__getLimit(count, this.__itemsInView, this.maxItemsVisible);
|
|
195
|
+
this._overflowLimit = limit;
|
|
196
|
+
this._overflowItems = limit ? this.items.slice(limit) : [];
|
|
221
197
|
}
|
|
198
|
+
}
|
|
222
199
|
|
|
223
|
-
|
|
200
|
+
/** @protected */
|
|
201
|
+
updated(props) {
|
|
202
|
+
super.updated(props);
|
|
224
203
|
|
|
225
|
-
if (
|
|
226
|
-
|
|
204
|
+
if (props.has('items')) {
|
|
205
|
+
this.__itemsChanged(this.items, props.get('items'));
|
|
227
206
|
}
|
|
228
207
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
/** @private */
|
|
235
|
-
__createItemElement(item) {
|
|
236
|
-
const itemElement = document.createElement('vaadin-avatar-group-menu-item');
|
|
208
|
+
if (props.has('items') || props.has('_overflowLimit') || props.has('__effectiveI18n') || props.has('_theme')) {
|
|
209
|
+
const limit = this._overflowLimit;
|
|
210
|
+
this.__renderAvatars(limit ? this.items.slice(0, limit) : this.items || []);
|
|
211
|
+
}
|
|
237
212
|
|
|
238
|
-
|
|
239
|
-
|
|
213
|
+
if (props.has('items') || props.has('_overflowLimit')) {
|
|
214
|
+
this.__updateOverflowTooltip(this.items, this._overflowLimit);
|
|
215
|
+
this.__updateOverflowAvatar(this.items, this._overflowLimit, this.__itemsInView);
|
|
216
|
+
}
|
|
240
217
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
218
|
+
if (props.has('__effectiveI18n') || props.has('items')) {
|
|
219
|
+
this.__i18nItemsChanged(this.__effectiveI18n, this.items);
|
|
220
|
+
}
|
|
244
221
|
|
|
245
|
-
if (
|
|
246
|
-
|
|
222
|
+
if (props.has('_opened')) {
|
|
223
|
+
this.__openedChanged(this._opened, props.get('_opened'));
|
|
247
224
|
}
|
|
248
225
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
226
|
+
if (props.has('_theme')) {
|
|
227
|
+
if (this._theme) {
|
|
228
|
+
this._overflow.setAttribute('theme', this._theme);
|
|
229
|
+
} else {
|
|
230
|
+
this._overflow.removeAttribute('theme');
|
|
231
|
+
}
|
|
255
232
|
}
|
|
256
233
|
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
itemElement.appendChild(text);
|
|
234
|
+
if (props.has('_overflowItems') || props.has('__effectiveI18n') || props.has('_theme')) {
|
|
235
|
+
this.__renderMenu();
|
|
260
236
|
}
|
|
237
|
+
}
|
|
261
238
|
|
|
262
|
-
|
|
239
|
+
/** @private */
|
|
240
|
+
__getMessage(user, action) {
|
|
241
|
+
return action.replace('{user}', user.name || user.abbr || this.__effectiveI18n.anonymous);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Renders items when they are provided by the `items` property and clears the content otherwise.
|
|
246
|
+
* @private
|
|
247
|
+
*/
|
|
248
|
+
__renderMenu() {
|
|
249
|
+
render(
|
|
250
|
+
html`
|
|
251
|
+
${(this._overflowItems || []).map(
|
|
252
|
+
(item) => html`
|
|
253
|
+
<vaadin-avatar-group-menu-item>
|
|
254
|
+
<vaadin-avatar
|
|
255
|
+
.name="${item.name}"
|
|
256
|
+
.abbr="${item.abbr}"
|
|
257
|
+
.img="${item.img}"
|
|
258
|
+
.colorIndex="${item.colorIndex}"
|
|
259
|
+
.i18n="${this.__effectiveI18n}"
|
|
260
|
+
class="${ifDefined(item.className)}"
|
|
261
|
+
theme="${ifDefined(this._theme)}"
|
|
262
|
+
aria-hidden="true"
|
|
263
|
+
></vaadin-avatar>
|
|
264
|
+
${item.name || ''}
|
|
265
|
+
</vaadin-avatar-group-menu-item>
|
|
266
|
+
`,
|
|
267
|
+
)}
|
|
268
|
+
`,
|
|
269
|
+
this._menuElement,
|
|
270
|
+
{ host: this },
|
|
271
|
+
);
|
|
263
272
|
}
|
|
264
273
|
|
|
265
274
|
/** @private */
|
|
@@ -323,7 +332,9 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
323
332
|
.img="${item.img}"
|
|
324
333
|
.colorIndex="${item.colorIndex}"
|
|
325
334
|
.i18n="${this.__effectiveI18n}"
|
|
335
|
+
theme="${ifDefined(this._theme)}"
|
|
326
336
|
class="${ifDefined(item.className)}"
|
|
337
|
+
tabindex="0"
|
|
327
338
|
with-tooltip
|
|
328
339
|
></vaadin-avatar>
|
|
329
340
|
`,
|
|
@@ -335,56 +346,25 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
335
346
|
}
|
|
336
347
|
|
|
337
348
|
/** @private */
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
344
|
-
|
|
345
|
-
this.__renderAvatars(limit ? items.slice(0, limit) : items);
|
|
346
|
-
|
|
347
|
-
this._avatars = [...this.querySelectorAll('vaadin-avatar')];
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/** @private */
|
|
351
|
-
__computeOverflowItems(items, itemsInView, maxItemsVisible) {
|
|
352
|
-
const count = Array.isArray(items) ? items.length : 0;
|
|
353
|
-
const limit = this.__getLimit(count, itemsInView, maxItemsVisible);
|
|
354
|
-
return limit ? items.slice(limit) : [];
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/** @private */
|
|
358
|
-
__updateOverflowAvatar(overflow, items, itemsInView, maxItemsVisible) {
|
|
349
|
+
__updateOverflowAvatar(items, limit, itemsInView) {
|
|
350
|
+
const overflow = this._overflow;
|
|
359
351
|
if (overflow) {
|
|
360
352
|
const count = Array.isArray(items) ? items.length : 0;
|
|
361
|
-
const maxReached = maxItemsVisible != null && count > this.__getMax(maxItemsVisible);
|
|
353
|
+
const maxReached = this.maxItemsVisible != null && count > this.__getMax(this.maxItemsVisible);
|
|
362
354
|
|
|
363
|
-
overflow.abbr = `+${count -
|
|
364
|
-
|
|
355
|
+
overflow.abbr = `+${count - limit}`;
|
|
356
|
+
const hasOverflow = maxReached || (itemsInView && itemsInView < count);
|
|
357
|
+
overflow.toggleAttribute('hidden', !hasOverflow);
|
|
358
|
+
this.toggleAttribute('has-overflow', hasOverflow);
|
|
365
359
|
}
|
|
366
360
|
}
|
|
367
361
|
|
|
368
362
|
/** @private */
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
[overflow, ...avatars].forEach((avatar) => {
|
|
372
|
-
if (theme) {
|
|
373
|
-
avatar.setAttribute('theme', theme);
|
|
374
|
-
} else {
|
|
375
|
-
avatar.removeAttribute('theme');
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/** @private */
|
|
382
|
-
__updateOverflowTooltip(tooltip, items, itemsInView, maxItemsVisible) {
|
|
383
|
-
if (!tooltip || !Array.isArray(items)) {
|
|
363
|
+
__updateOverflowTooltip(items, limit) {
|
|
364
|
+
if (!Array.isArray(items)) {
|
|
384
365
|
return;
|
|
385
366
|
}
|
|
386
367
|
|
|
387
|
-
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
388
368
|
if (limit == null) {
|
|
389
369
|
return;
|
|
390
370
|
}
|
|
@@ -397,7 +377,7 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
397
377
|
}
|
|
398
378
|
}
|
|
399
379
|
|
|
400
|
-
|
|
380
|
+
this._overflowTooltip.text = result.join('\n');
|
|
401
381
|
}
|
|
402
382
|
|
|
403
383
|
/** @private */
|
|
@@ -466,41 +446,18 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
466
446
|
if (effectiveI18n.activeUsers[field]) {
|
|
467
447
|
this.setAttribute('aria-label', effectiveI18n.activeUsers[field].replace('{count}', count || 0));
|
|
468
448
|
}
|
|
469
|
-
|
|
470
|
-
this._avatars.forEach((avatar) => {
|
|
471
|
-
avatar.i18n = effectiveI18n;
|
|
472
|
-
});
|
|
473
449
|
}
|
|
474
450
|
}
|
|
475
451
|
|
|
476
452
|
/** @private */
|
|
477
|
-
__openedChanged(opened,
|
|
478
|
-
if (!overflow) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
|
|
453
|
+
__openedChanged(opened, oldOpened) {
|
|
482
454
|
if (opened) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
this._openedWithFocusRing = overflow.hasAttribute('focus-ring');
|
|
488
|
-
} else if (this.__oldOpened) {
|
|
489
|
-
overflow.focus();
|
|
490
|
-
if (this._openedWithFocusRing) {
|
|
491
|
-
overflow.setAttribute('focus-ring', '');
|
|
492
|
-
}
|
|
455
|
+
this._openedWithFocusRing = this._overflow.hasAttribute('focus-ring');
|
|
456
|
+
} else if (oldOpened) {
|
|
457
|
+
this._overflow.focus({ focusVisible: this._openedWithFocusRing });
|
|
493
458
|
}
|
|
494
459
|
|
|
495
|
-
|
|
496
|
-
this.__oldOpened = opened;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/** @private */
|
|
500
|
-
__overflowItemsChanged(items, oldItems) {
|
|
501
|
-
if (items || oldItems) {
|
|
502
|
-
this.$.overlay.requestContentUpdate();
|
|
503
|
-
}
|
|
460
|
+
this._overflow.setAttribute('aria-expanded', opened === true);
|
|
504
461
|
}
|
|
505
462
|
|
|
506
463
|
/** @private */
|
|
@@ -7,9 +7,10 @@ import { html, LitElement } from 'lit';
|
|
|
7
7
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
8
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
9
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
|
+
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
|
|
10
11
|
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
11
12
|
import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
|
|
12
|
-
import {
|
|
13
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
14
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -23,7 +24,9 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
23
24
|
* @mixes ThemableMixin
|
|
24
25
|
* @private
|
|
25
26
|
*/
|
|
26
|
-
class AvatarGroupOverlay extends PositionMixin(
|
|
27
|
+
class AvatarGroupOverlay extends PositionMixin(
|
|
28
|
+
OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))),
|
|
29
|
+
) {
|
|
27
30
|
static get is() {
|
|
28
31
|
return 'vaadin-avatar-group-overlay';
|
|
29
32
|
}
|
|
@@ -35,8 +38,7 @@ class AvatarGroupOverlay extends PositionMixin(OverlayMixin(DirMixin(ThemableMix
|
|
|
35
38
|
/** @protected */
|
|
36
39
|
render() {
|
|
37
40
|
return html`
|
|
38
|
-
<div
|
|
39
|
-
<div part="overlay" id="overlay" tabindex="0">
|
|
41
|
+
<div part="overlay" id="overlay">
|
|
40
42
|
<div part="content" id="content">
|
|
41
43
|
<slot></slot>
|
|
42
44
|
</div>
|
|
@@ -15,13 +15,13 @@ export { AvatarGroupI18n, AvatarGroupItem, AvatarI18n };
|
|
|
15
15
|
*
|
|
16
16
|
* To create the avatar group, first add the component to the page:
|
|
17
17
|
*
|
|
18
|
-
* ```
|
|
18
|
+
* ```html
|
|
19
19
|
* <vaadin-avatar-group></vaadin-avatar-group>
|
|
20
20
|
* ```
|
|
21
21
|
*
|
|
22
22
|
* And then use [`items`](#/elements/vaadin-avatar-group#property-items) property to initialize the structure:
|
|
23
23
|
*
|
|
24
|
-
* ```
|
|
24
|
+
* ```js
|
|
25
25
|
* document.querySelector('vaadin-avatar-group').items = [
|
|
26
26
|
* {name: 'John Doe'},
|
|
27
27
|
* {abbr: 'AB'}
|
|
@@ -35,6 +35,8 @@ export { AvatarGroupI18n, AvatarGroupItem, AvatarI18n };
|
|
|
35
35
|
* Part name | Description
|
|
36
36
|
* ----------- | ---------------
|
|
37
37
|
* `container` | The container element
|
|
38
|
+
* `overlay` | The overflow avatar menu overlay
|
|
39
|
+
* `content` | The overflow avatar menu overlay content
|
|
38
40
|
*
|
|
39
41
|
* See the [`<vaadin-avatar>`](#/elements/vaadin-avatar) documentation for the available
|
|
40
42
|
* state attributes and stylable shadow parts of avatar elements.
|
|
@@ -46,7 +48,6 @@ export { AvatarGroupI18n, AvatarGroupItem, AvatarI18n };
|
|
|
46
48
|
* In addition to `<vaadin-avatar-group>` itself, the following internal
|
|
47
49
|
* components are themable:
|
|
48
50
|
*
|
|
49
|
-
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
50
51
|
* - `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
51
52
|
* - `<vaadin-avatar-group-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
|
|
52
53
|
*/
|
|
@@ -12,22 +12,23 @@ import { html, LitElement } from 'lit';
|
|
|
12
12
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
13
13
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
14
14
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
15
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
15
16
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
17
|
+
import { avatarGroupStyles } from './styles/vaadin-avatar-group-base-styles.js';
|
|
16
18
|
import { AvatarGroupMixin } from './vaadin-avatar-group-mixin.js';
|
|
17
|
-
import { avatarGroupStyles } from './vaadin-avatar-group-styles.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* `<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality.
|
|
21
22
|
*
|
|
22
23
|
* To create the avatar group, first add the component to the page:
|
|
23
24
|
*
|
|
24
|
-
* ```
|
|
25
|
+
* ```html
|
|
25
26
|
* <vaadin-avatar-group></vaadin-avatar-group>
|
|
26
27
|
* ```
|
|
27
28
|
*
|
|
28
29
|
* And then use [`items`](#/elements/vaadin-avatar-group#property-items) property to initialize the structure:
|
|
29
30
|
*
|
|
30
|
-
* ```
|
|
31
|
+
* ```js
|
|
31
32
|
* document.querySelector('vaadin-avatar-group').items = [
|
|
32
33
|
* {name: 'John Doe'},
|
|
33
34
|
* {abbr: 'AB'}
|
|
@@ -41,6 +42,8 @@ import { avatarGroupStyles } from './vaadin-avatar-group-styles.js';
|
|
|
41
42
|
* Part name | Description
|
|
42
43
|
* ----------- | ---------------
|
|
43
44
|
* `container` | The container element
|
|
45
|
+
* `overlay` | The overflow avatar menu overlay
|
|
46
|
+
* `content` | The overflow avatar menu overlay content
|
|
44
47
|
*
|
|
45
48
|
* See the [`<vaadin-avatar>`](#/elements/vaadin-avatar) documentation for the available
|
|
46
49
|
* state attributes and stylable shadow parts of avatar elements.
|
|
@@ -52,7 +55,6 @@ import { avatarGroupStyles } from './vaadin-avatar-group-styles.js';
|
|
|
52
55
|
* In addition to `<vaadin-avatar-group>` itself, the following internal
|
|
53
56
|
* components are themable:
|
|
54
57
|
*
|
|
55
|
-
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
56
58
|
* - `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
57
59
|
* - `<vaadin-avatar-group-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
|
|
58
60
|
*
|
|
@@ -62,7 +64,7 @@ import { avatarGroupStyles } from './vaadin-avatar-group-styles.js';
|
|
|
62
64
|
* @mixes AvatarGroupMixin
|
|
63
65
|
* @mixes ThemableMixin
|
|
64
66
|
*/
|
|
65
|
-
class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
67
|
+
class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
66
68
|
static get is() {
|
|
67
69
|
return 'vaadin-avatar-group';
|
|
68
70
|
}
|
|
@@ -80,13 +82,17 @@ class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(PolylitMix
|
|
|
80
82
|
</div>
|
|
81
83
|
<vaadin-avatar-group-overlay
|
|
82
84
|
id="overlay"
|
|
85
|
+
.owner="${this}"
|
|
83
86
|
.opened="${this._opened}"
|
|
84
87
|
.positionTarget="${this._overflow}"
|
|
85
88
|
no-vertical-overlap
|
|
89
|
+
exportparts="overlay, content"
|
|
86
90
|
@vaadin-overlay-close="${this._onVaadinOverlayClose}"
|
|
87
91
|
@vaadin-overlay-open="${this._onVaadinOverlayOpen}"
|
|
88
92
|
@opened-changed="${this._onOpenedChanged}"
|
|
89
|
-
|
|
93
|
+
>
|
|
94
|
+
<slot name="overlay"></slot>
|
|
95
|
+
</vaadin-avatar-group-overlay>
|
|
90
96
|
`;
|
|
91
97
|
}
|
|
92
98
|
|
package/vaadin-avatar-group.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-avatar-group.js';
|
|
2
2
|
export * from './src/vaadin-avatar-group.js';
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/avatar-group",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha20",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-avatar-group",
|
|
11
|
-
"description": "`<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality.\n\nTo create the avatar group, first add the component to the page:\n\n
|
|
11
|
+
"description": "`<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality.\n\nTo create the avatar group, first add the component to the page:\n\n```html\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar-group#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-avatar-group').items = [\n {name: 'John Doe'},\n {abbr: 'AB'}\n];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n----------- | ---------------\n`container` | The container element\n`overlay` | The overflow avatar menu overlay\n`content` | The overflow avatar menu overlay content\n\nSee the [`<vaadin-avatar>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar) documentation for the available\nstate attributes and stylable shadow parts of avatar elements.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-avatar-group>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-list-box).\n- `<vaadin-avatar-group-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-item).",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "i18n",
|
|
@@ -19,17 +19,6 @@
|
|
|
19
19
|
]
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
-
{
|
|
23
|
-
"name": "overlay-class",
|
|
24
|
-
"description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
|
|
25
|
-
"value": {
|
|
26
|
-
"type": [
|
|
27
|
-
"string",
|
|
28
|
-
"null",
|
|
29
|
-
"undefined"
|
|
30
|
-
]
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
22
|
{
|
|
34
23
|
"name": "max-items-visible",
|
|
35
24
|
"description": "The maximum number of avatars to display. By default, all the avatars are displayed.\nWhen _maxItemsVisible_ is set, the overflowing avatars are grouped into one avatar with\na dropdown. Setting 0 or 1 has no effect so there are always at least two avatars visible.",
|
|
@@ -57,27 +46,16 @@
|
|
|
57
46
|
"properties": [
|
|
58
47
|
{
|
|
59
48
|
"name": "i18n",
|
|
60
|
-
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n
|
|
49
|
+
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n```js\n{\n // Translation of the anonymous user avatar tooltip.\n anonymous: 'anonymous',\n // Translation of the avatar group accessible label.\n // {count} is replaced with the actual count of users.\n activeUsers: {\n one: 'Currently one active user',\n many: 'Currently {count} active users'\n },\n // Screen reader announcement when user joins group.\n // {user} is replaced with the name or abbreviation.\n // When neither is set, \"anonymous\" is used instead.\n joined: '{user} joined',\n // Screen reader announcement when user leaves group.\n // {user} is replaced with the name or abbreviation.\n // When neither is set, \"anonymous\" is used instead.\n left: '{user} left'\n}\n```",
|
|
61
50
|
"value": {
|
|
62
51
|
"type": [
|
|
63
52
|
"AvatarGroupI18n"
|
|
64
53
|
]
|
|
65
54
|
}
|
|
66
55
|
},
|
|
67
|
-
{
|
|
68
|
-
"name": "overlayClass",
|
|
69
|
-
"description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
|
|
70
|
-
"value": {
|
|
71
|
-
"type": [
|
|
72
|
-
"string",
|
|
73
|
-
"null",
|
|
74
|
-
"undefined"
|
|
75
|
-
]
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
56
|
{
|
|
79
57
|
"name": "items",
|
|
80
|
-
"description": "An array containing the items which will be stamped as avatars.\n\nThe items objects allow to configure [`name`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-
|
|
58
|
+
"description": "An array containing the items which will be stamped as avatars.\n\nThe items objects allow to configure [`name`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-colorIndex) properties on the\nstamped avatars, and set `className` to provide CSS class names.\n\n#### Example\n\n```js\ngroup.items = [\n {\n name: 'User name',\n img: 'url-to-image.png',\n className: 'even'\n },\n {\n abbr: 'JD',\n colorIndex: 1,\n className: 'odd'\n },\n];\n```",
|
|
81
59
|
"value": {
|
|
82
60
|
"type": [
|
|
83
61
|
"Array.<AvatarGroupItem>",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/avatar-group",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha20",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,26 +16,19 @@
|
|
|
16
16
|
"elements": [
|
|
17
17
|
{
|
|
18
18
|
"name": "vaadin-avatar-group",
|
|
19
|
-
"description": "`<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality.\n\nTo create the avatar group, first add the component to the page:\n\n
|
|
19
|
+
"description": "`<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality.\n\nTo create the avatar group, first add the component to the page:\n\n```html\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar-group#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-avatar-group').items = [\n {name: 'John Doe'},\n {abbr: 'AB'}\n];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n----------- | ---------------\n`container` | The container element\n`overlay` | The overflow avatar menu overlay\n`content` | The overflow avatar menu overlay content\n\nSee the [`<vaadin-avatar>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar) documentation for the available\nstate attributes and stylable shadow parts of avatar elements.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-avatar-group>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-list-box).\n- `<vaadin-avatar-group-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-item).",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
23
23
|
"name": ".i18n",
|
|
24
|
-
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n
|
|
25
|
-
"value": {
|
|
26
|
-
"kind": "expression"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"name": ".overlayClass",
|
|
31
|
-
"description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
|
|
24
|
+
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n```js\n{\n // Translation of the anonymous user avatar tooltip.\n anonymous: 'anonymous',\n // Translation of the avatar group accessible label.\n // {count} is replaced with the actual count of users.\n activeUsers: {\n one: 'Currently one active user',\n many: 'Currently {count} active users'\n },\n // Screen reader announcement when user joins group.\n // {user} is replaced with the name or abbreviation.\n // When neither is set, \"anonymous\" is used instead.\n joined: '{user} joined',\n // Screen reader announcement when user leaves group.\n // {user} is replaced with the name or abbreviation.\n // When neither is set, \"anonymous\" is used instead.\n left: '{user} left'\n}\n```",
|
|
32
25
|
"value": {
|
|
33
26
|
"kind": "expression"
|
|
34
27
|
}
|
|
35
28
|
},
|
|
36
29
|
{
|
|
37
30
|
"name": ".items",
|
|
38
|
-
"description": "An array containing the items which will be stamped as avatars.\n\nThe items objects allow to configure [`name`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-
|
|
31
|
+
"description": "An array containing the items which will be stamped as avatars.\n\nThe items objects allow to configure [`name`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha20/#/elements/vaadin-avatar#property-colorIndex) properties on the\nstamped avatars, and set `className` to provide CSS class names.\n\n#### Example\n\n```js\ngroup.items = [\n {\n name: 'User name',\n img: 'url-to-image.png',\n className: 'even'\n },\n {\n abbr: 'JD',\n colorIndex: 1,\n className: 'odd'\n },\n];\n```",
|
|
39
32
|
"value": {
|
|
40
33
|
"kind": "expression"
|
|
41
34
|
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2020 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
7
|
-
|
|
8
|
-
export const avatarGroupStyles = css`
|
|
9
|
-
:host {
|
|
10
|
-
display: block;
|
|
11
|
-
width: 100%; /* prevent collapsing inside non-stretching column flex */
|
|
12
|
-
--vaadin-avatar-group-overlap: 8px;
|
|
13
|
-
--vaadin-avatar-group-overlap-border: 2px;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
:host([hidden]) {
|
|
17
|
-
display: none !important;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
[part='container'] {
|
|
21
|
-
display: flex;
|
|
22
|
-
position: relative;
|
|
23
|
-
width: 100%;
|
|
24
|
-
flex-wrap: nowrap;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
::slotted(vaadin-avatar:not(:first-child)) {
|
|
28
|
-
-webkit-mask-image: url('data:image/svg+xml;utf8,<svg viewBox=%220 0 300 300%22 fill=%22none%22 xmlns=%22http://www.w3.org/2000/svg%22><path fill-rule=%22evenodd%22 clip-rule=%22evenodd%22 d=%22M300 0H0V300H300V0ZM150 200C177.614 200 200 177.614 200 150C200 122.386 177.614 100 150 100C122.386 100 100 122.386 100 150C100 177.614 122.386 200 150 200Z%22 fill=%22black%22/></svg>');
|
|
29
|
-
mask-image: url('data:image/svg+xml;utf8,<svg viewBox=%220 0 300 300%22 fill=%22none%22 xmlns=%22http://www.w3.org/2000/svg%22><path fill-rule=%22evenodd%22 clip-rule=%22evenodd%22 d=%22M300 0H0V300H300V0ZM150 200C177.614 200 200 177.614 200 150C200 122.386 177.614 100 150 100C122.386 100 100 122.386 100 150C100 177.614 122.386 200 150 200Z%22 fill=%22black%22/></svg>');
|
|
30
|
-
-webkit-mask-size: calc(
|
|
31
|
-
300% + var(--vaadin-avatar-group-overlap-border) * 6 - var(--vaadin-avatar-outline-width) * 6
|
|
32
|
-
);
|
|
33
|
-
mask-size: calc(300% + var(--vaadin-avatar-group-overlap-border) * 6 - var(--vaadin-avatar-outline-width) * 6);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
::slotted(vaadin-avatar:not([dir='rtl']):not(:first-child)) {
|
|
37
|
-
margin-left: calc(var(--vaadin-avatar-group-overlap) * -1 - var(--vaadin-avatar-outline-width));
|
|
38
|
-
-webkit-mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap));
|
|
39
|
-
mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
::slotted(vaadin-avatar[dir='rtl']:not(:first-child)) {
|
|
43
|
-
margin-right: calc(var(--vaadin-avatar-group-overlap) * -1);
|
|
44
|
-
-webkit-mask-position: calc(
|
|
45
|
-
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width)
|
|
46
|
-
);
|
|
47
|
-
mask-position: calc(
|
|
48
|
-
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width)
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
`;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/color.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/sizing.js';
|
|
3
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
4
|
-
import { item } from '@vaadin/item/theme/lumo/vaadin-item-styles.js';
|
|
5
|
-
import { listBox } from '@vaadin/list-box/theme/lumo/vaadin-list-box-styles.js';
|
|
6
|
-
import { menuOverlayCore } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
|
|
7
|
-
import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
|
|
8
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
9
|
-
|
|
10
|
-
registerStyles(
|
|
11
|
-
'vaadin-avatar-group',
|
|
12
|
-
css`
|
|
13
|
-
:host {
|
|
14
|
-
--vaadin-avatar-size: var(--lumo-size-m);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
:host([theme~='xlarge']) {
|
|
18
|
-
--vaadin-avatar-group-overlap: 12px;
|
|
19
|
-
--vaadin-avatar-group-overlap-border: 3px;
|
|
20
|
-
--vaadin-avatar-size: var(--lumo-size-xl);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
:host([theme~='large']) {
|
|
24
|
-
--vaadin-avatar-group-overlap: 10px;
|
|
25
|
-
--vaadin-avatar-group-overlap-border: 3px;
|
|
26
|
-
--vaadin-avatar-size: var(--lumo-size-l);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
:host([theme~='small']) {
|
|
30
|
-
--vaadin-avatar-group-overlap: 6px;
|
|
31
|
-
--vaadin-avatar-group-overlap-border: 2px;
|
|
32
|
-
--vaadin-avatar-size: var(--lumo-size-s);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
:host([theme~='xsmall']) {
|
|
36
|
-
--vaadin-avatar-group-overlap: 4px;
|
|
37
|
-
--vaadin-avatar-group-overlap-border: 2px;
|
|
38
|
-
--vaadin-avatar-size: var(--lumo-size-xs);
|
|
39
|
-
}
|
|
40
|
-
`,
|
|
41
|
-
{ moduleId: 'lumo-avatar-group' },
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const avatarGroupOverlay = css`
|
|
45
|
-
:host {
|
|
46
|
-
--_lumo-list-box-item-selected-icon-display: none;
|
|
47
|
-
--_lumo-list-box-item-padding-left: calc(var(--lumo-space-m) + var(--lumo-border-radius-m) / 4);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
[part='overlay'] {
|
|
51
|
-
outline: none;
|
|
52
|
-
}
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
registerStyles('vaadin-avatar-group-overlay', [overlay, menuOverlayCore, avatarGroupOverlay], {
|
|
56
|
-
moduleId: 'lumo-avatar-group-overlay',
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
registerStyles('vaadin-avatar-group-menu', listBox, { moduleId: 'lumo-avatar-group-menu' });
|
|
60
|
-
|
|
61
|
-
registerStyles(
|
|
62
|
-
'vaadin-avatar-group-menu-item',
|
|
63
|
-
[
|
|
64
|
-
item,
|
|
65
|
-
css`
|
|
66
|
-
:host {
|
|
67
|
-
padding: var(--lumo-space-xs);
|
|
68
|
-
padding-inline-end: var(--lumo-space-m);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
[part='content'] {
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
[part='content'] ::slotted(vaadin-avatar) {
|
|
77
|
-
width: var(--lumo-size-xs);
|
|
78
|
-
height: var(--lumo-size-xs);
|
|
79
|
-
margin-inline-end: var(--lumo-space-s);
|
|
80
|
-
}
|
|
81
|
-
`,
|
|
82
|
-
],
|
|
83
|
-
{ moduleId: 'lumo-avatar-group-menu-item' },
|
|
84
|
-
);
|
/package/src/{vaadin-avatar-group-styles.d.ts → styles/vaadin-avatar-group-base-styles.d.ts}
RENAMED
|
File without changes
|