@vaadin/avatar-group 25.0.0-alpha7 → 25.0.0-alpha8
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 +13 -13
- package/src/styles/vaadin-avatar-group-base-styles.js +46 -47
- package/src/styles/vaadin-avatar-group-core-styles.js +3 -3
- package/src/styles/vaadin-avatar-group-menu-base-styles.js +9 -11
- package/src/styles/vaadin-avatar-group-menu-item-base-styles.js +4 -6
- package/src/vaadin-avatar-group-menu-item.js +1 -1
- package/src/vaadin-avatar-group-menu.js +1 -1
- package/src/vaadin-avatar-group-mixin.js +101 -129
- package/src/vaadin-avatar-group-overlay.js +17 -2
- package/src/vaadin-avatar-group.d.ts +4 -2
- package/src/vaadin-avatar-group.js +11 -5
- package/web-types.json +3 -3
- package/web-types.lit.json +3 -3
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-alpha8",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,20 +38,20 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
41
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
42
|
-
"@vaadin/avatar": "25.0.0-
|
|
43
|
-
"@vaadin/component-base": "25.0.0-
|
|
44
|
-
"@vaadin/item": "25.0.0-
|
|
45
|
-
"@vaadin/list-box": "25.0.0-
|
|
46
|
-
"@vaadin/overlay": "25.0.0-
|
|
47
|
-
"@vaadin/tooltip": "25.0.0-
|
|
48
|
-
"@vaadin/vaadin-lumo-styles": "25.0.0-
|
|
49
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-
|
|
41
|
+
"@vaadin/a11y-base": "25.0.0-alpha8",
|
|
42
|
+
"@vaadin/avatar": "25.0.0-alpha8",
|
|
43
|
+
"@vaadin/component-base": "25.0.0-alpha8",
|
|
44
|
+
"@vaadin/item": "25.0.0-alpha8",
|
|
45
|
+
"@vaadin/list-box": "25.0.0-alpha8",
|
|
46
|
+
"@vaadin/overlay": "25.0.0-alpha8",
|
|
47
|
+
"@vaadin/tooltip": "25.0.0-alpha8",
|
|
48
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-alpha8",
|
|
49
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha8",
|
|
50
50
|
"lit": "^3.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
54
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
53
|
+
"@vaadin/chai-plugins": "25.0.0-alpha8",
|
|
54
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha8",
|
|
55
55
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
56
56
|
"sinon": "^18.0.0"
|
|
57
57
|
},
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"web-types.json",
|
|
60
60
|
"web-types.lit.json"
|
|
61
61
|
],
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "ebf53673d5f639d2b1b6f2b31f640f530643ee2f"
|
|
63
63
|
}
|
|
@@ -3,62 +3,61 @@
|
|
|
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 '@vaadin/component-base/src/style-props.js';
|
|
6
7
|
import { css } from 'lit';
|
|
7
8
|
|
|
8
9
|
export const avatarGroupStyles = css`
|
|
9
|
-
|
|
10
|
-
:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
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
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
:host([theme~='reverse']) {
|
|
19
|
+
--_dir: -1;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
:host([hidden]) {
|
|
23
|
+
display: none !important;
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
[part='container'] {
|
|
27
|
+
display: flex;
|
|
28
|
+
position: relative;
|
|
29
|
+
width: 100%;
|
|
30
|
+
flex-wrap: nowrap;
|
|
31
|
+
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
::slotted(vaadin-avatar) {
|
|
34
|
+
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>');
|
|
35
|
+
mask-size: calc(300% + var(--vaadin-avatar-group-gap, 2px) * 6 - var(--vaadin-focus-ring-width) * 6);
|
|
36
|
+
mask-position: calc(
|
|
37
|
+
50% +
|
|
38
|
+
(
|
|
39
|
+
var(--vaadin-avatar-size, 32px) - var(--vaadin-avatar-group-overlap, 8px) +
|
|
40
|
+
var(--vaadin-avatar-group-gap, 2px)
|
|
41
|
+
) *
|
|
42
|
+
var(--_d)
|
|
43
|
+
);
|
|
44
|
+
--_d: var(--_dir);
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
:host(:dir(rtl)) ::slotted(vaadin-avatar) {
|
|
48
|
+
--_d: calc(var(--_dir) * -1);
|
|
49
|
+
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
::slotted(vaadin-avatar:not(:first-of-type)) {
|
|
52
|
+
margin-inline-start: calc(
|
|
53
|
+
var(--vaadin-avatar-group-overlap, 8px) * -1 - var(--vaadin-focus-ring-width) +
|
|
54
|
+
var(--vaadin-avatar-group-gap, 2px)
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
58
|
+
:host(:not([theme~='reverse'])) ::slotted(vaadin-avatar:last-child),
|
|
59
|
+
:host(:not([theme~='reverse']):not([has-overflow])) ::slotted(vaadin-avatar:nth-last-child(2)),
|
|
60
|
+
:host([theme~='reverse']) ::slotted(vaadin-avatar:first-of-type) {
|
|
61
|
+
mask-image: none;
|
|
63
62
|
}
|
|
64
63
|
`;
|
|
@@ -25,17 +25,17 @@ export const avatarGroupStyles = css`
|
|
|
25
25
|
flex-wrap: nowrap;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
::slotted(vaadin-avatar:not(:first-
|
|
28
|
+
::slotted(vaadin-avatar:not(:first-of-type)) {
|
|
29
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
30
|
mask-size: calc(300% + var(--vaadin-avatar-group-overlap-border) * 6 - var(--vaadin-avatar-outline-width) * 6);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
::slotted(vaadin-avatar:not([dir='rtl']):not(:first-
|
|
33
|
+
::slotted(vaadin-avatar:not([dir='rtl']):not(:first-of-type)) {
|
|
34
34
|
margin-left: calc(var(--vaadin-avatar-group-overlap) * -1 - var(--vaadin-avatar-outline-width));
|
|
35
35
|
mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
::slotted(vaadin-avatar[dir='rtl']:not(:first-
|
|
38
|
+
::slotted(vaadin-avatar[dir='rtl']:not(:first-of-type)) {
|
|
39
39
|
margin-right: calc(var(--vaadin-avatar-group-overlap) * -1);
|
|
40
40
|
mask-position: calc(
|
|
41
41
|
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width)
|
|
@@ -6,18 +6,16 @@
|
|
|
6
6
|
import { css } from 'lit';
|
|
7
7
|
|
|
8
8
|
export const avatarGroupMenuStyles = css`
|
|
9
|
-
|
|
10
|
-
:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
padding: var(--vaadin-item-overlay-padding, 4px);
|
|
12
|
+
}
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
:host([hidden]) {
|
|
15
|
+
display: none !important;
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
18
|
+
[part='items'] {
|
|
19
|
+
display: contents;
|
|
22
20
|
}
|
|
23
21
|
`;
|
|
@@ -7,12 +7,10 @@ import { css } from 'lit';
|
|
|
7
7
|
import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-base-styles.js';
|
|
8
8
|
|
|
9
9
|
const menuItemStyles = css`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
gap: inherit;
|
|
15
|
-
}
|
|
10
|
+
[part='content'] {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: inherit;
|
|
16
14
|
}
|
|
17
15
|
`;
|
|
18
16
|
|
|
@@ -22,7 +22,7 @@ import { avatarGroupMenuItemStyles } from './styles/vaadin-avatar-group-menu-ite
|
|
|
22
22
|
* @mixes ThemableMixin
|
|
23
23
|
* @protected
|
|
24
24
|
*/
|
|
25
|
-
class AvatarGroupMenuItem extends ItemMixin(ThemableMixin(DirMixin(LumoInjectionMixin(
|
|
25
|
+
class AvatarGroupMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
26
26
|
static get is() {
|
|
27
27
|
return 'vaadin-avatar-group-menu-item';
|
|
28
28
|
}
|
|
@@ -22,7 +22,7 @@ import { avatarGroupMenuStyles } from './styles/vaadin-avatar-group-menu-core-st
|
|
|
22
22
|
* @mixes ThemableMixin
|
|
23
23
|
* @protected
|
|
24
24
|
*/
|
|
25
|
-
class AvatarGroupMenu extends ListMixin(ThemableMixin(DirMixin(LumoInjectionMixin(
|
|
25
|
+
class AvatarGroupMenu extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
26
26
|
static get is() {
|
|
27
27
|
return 'vaadin-avatar-group-menu';
|
|
28
28
|
}
|
|
@@ -64,7 +64,6 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
64
64
|
*/
|
|
65
65
|
items: {
|
|
66
66
|
type: Array,
|
|
67
|
-
observer: '__itemsChanged',
|
|
68
67
|
sync: true,
|
|
69
68
|
},
|
|
70
69
|
|
|
@@ -79,13 +78,6 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
79
78
|
sync: true,
|
|
80
79
|
},
|
|
81
80
|
|
|
82
|
-
/** @private */
|
|
83
|
-
_avatars: {
|
|
84
|
-
type: Array,
|
|
85
|
-
value: () => [],
|
|
86
|
-
sync: true,
|
|
87
|
-
},
|
|
88
|
-
|
|
89
81
|
/** @private */
|
|
90
82
|
__itemsInView: {
|
|
91
83
|
type: Number,
|
|
@@ -93,23 +85,14 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
93
85
|
sync: true,
|
|
94
86
|
},
|
|
95
87
|
|
|
96
|
-
/** @private */
|
|
97
|
-
_overflow: {
|
|
98
|
-
type: Object,
|
|
99
|
-
sync: true,
|
|
100
|
-
},
|
|
101
|
-
|
|
102
88
|
/** @private */
|
|
103
89
|
_overflowItems: {
|
|
104
90
|
type: Array,
|
|
105
|
-
observer: '__overflowItemsChanged',
|
|
106
|
-
computed: '__computeOverflowItems(items, __itemsInView, maxItemsVisible)',
|
|
107
91
|
},
|
|
108
92
|
|
|
109
93
|
/** @private */
|
|
110
|
-
|
|
111
|
-
type:
|
|
112
|
-
sync: true,
|
|
94
|
+
_overflowLimit: {
|
|
95
|
+
type: Number,
|
|
113
96
|
},
|
|
114
97
|
|
|
115
98
|
/** @private */
|
|
@@ -120,17 +103,6 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
120
103
|
};
|
|
121
104
|
}
|
|
122
105
|
|
|
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
106
|
/**
|
|
135
107
|
* The object used to localize this component. To change the default
|
|
136
108
|
* localization, replace this with an object that provides all properties, or
|
|
@@ -167,16 +139,22 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
167
139
|
super.i18n = value;
|
|
168
140
|
}
|
|
169
141
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
this.__overlayRenderer = this.__overlayRenderer.bind(this);
|
|
142
|
+
/** @protected */
|
|
143
|
+
get _avatars() {
|
|
144
|
+
return [...this.children].filter((node) => node.localName === 'vaadin-avatar');
|
|
174
145
|
}
|
|
175
146
|
|
|
176
147
|
/** @protected */
|
|
177
148
|
ready() {
|
|
178
149
|
super.ready();
|
|
179
150
|
|
|
151
|
+
this._menuController = new SlotController(this, 'overlay', 'vaadin-avatar-group-menu', {
|
|
152
|
+
initializer: (menu) => {
|
|
153
|
+
menu.addEventListener('keydown', this._onListKeyDown.bind(this));
|
|
154
|
+
this._menuElement = menu;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
|
|
180
158
|
this._overflowController = new SlotController(this, 'overflow', 'vaadin-avatar', {
|
|
181
159
|
initializer: (overflow) => {
|
|
182
160
|
overflow.setAttribute('role', 'button');
|
|
@@ -193,6 +171,8 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
193
171
|
this._overflowTooltip = tooltip;
|
|
194
172
|
},
|
|
195
173
|
});
|
|
174
|
+
|
|
175
|
+
this.addController(this._menuController);
|
|
196
176
|
this.addController(this._overflowController);
|
|
197
177
|
|
|
198
178
|
this._overlayElement = this.$.overlay;
|
|
@@ -205,6 +185,58 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
205
185
|
this._opened = false;
|
|
206
186
|
}
|
|
207
187
|
|
|
188
|
+
/** @protected */
|
|
189
|
+
willUpdate(props) {
|
|
190
|
+
super.willUpdate(props);
|
|
191
|
+
|
|
192
|
+
if (props.has('items') || props.has('__itemsInView') || props.has('maxItemsVisible')) {
|
|
193
|
+
// Calculate overflow limit only once to reuse it in updated() observers
|
|
194
|
+
const count = Array.isArray(this.items) ? this.items.length : 0;
|
|
195
|
+
const limit = this.__getLimit(count, this.__itemsInView, this.maxItemsVisible);
|
|
196
|
+
this._overflowLimit = limit;
|
|
197
|
+
this._overflowItems = limit ? this.items.slice(limit) : [];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** @protected */
|
|
202
|
+
updated(props) {
|
|
203
|
+
super.updated(props);
|
|
204
|
+
|
|
205
|
+
if (props.has('items')) {
|
|
206
|
+
this.__itemsChanged(this.items, props.get('items'));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (props.has('items') || props.has('_overflowLimit') || props.has('__effectiveI18n') || props.has('_theme')) {
|
|
210
|
+
const limit = this._overflowLimit;
|
|
211
|
+
this.__renderAvatars(limit ? this.items.slice(0, limit) : this.items || []);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (props.has('items') || props.has('_overflowLimit')) {
|
|
215
|
+
this.__updateOverflowTooltip(this.items, this._overflowLimit);
|
|
216
|
+
this.__updateOverflowAvatar(this.items, this._overflowLimit, this.__itemsInView);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (props.has('__effectiveI18n') || props.has('items')) {
|
|
220
|
+
this.__i18nItemsChanged(this.__effectiveI18n, this.items);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (props.has('_opened')) {
|
|
224
|
+
this.__openedChanged(this._opened, props.get('_opened'));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (props.has('_theme')) {
|
|
228
|
+
if (this._theme) {
|
|
229
|
+
this._overflow.setAttribute('theme', this._theme);
|
|
230
|
+
} else {
|
|
231
|
+
this._overflow.removeAttribute('theme');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (props.has('_overflowItems') || props.has('__effectiveI18n') || props.has('_theme')) {
|
|
236
|
+
this.__renderMenu();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
208
240
|
/** @private */
|
|
209
241
|
__getMessage(user, action) {
|
|
210
242
|
return action.replace('{user}', user.name || user.abbr || this.__effectiveI18n.anonymous);
|
|
@@ -212,34 +244,31 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
212
244
|
|
|
213
245
|
/**
|
|
214
246
|
* Renders items when they are provided by the `items` property and clears the content otherwise.
|
|
215
|
-
* @param {!HTMLElement} root
|
|
216
247
|
* @private
|
|
217
248
|
*/
|
|
218
|
-
|
|
249
|
+
__renderMenu() {
|
|
219
250
|
render(
|
|
220
251
|
html`
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
<vaadin-avatar
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
)}
|
|
240
|
-
</vaadin-avatar-group-menu>
|
|
252
|
+
${(this._overflowItems || []).map(
|
|
253
|
+
(item) => html`
|
|
254
|
+
<vaadin-avatar-group-menu-item>
|
|
255
|
+
<vaadin-avatar
|
|
256
|
+
.name="${item.name}"
|
|
257
|
+
.abbr="${item.abbr}"
|
|
258
|
+
.img="${item.img}"
|
|
259
|
+
.colorIndex="${item.colorIndex}"
|
|
260
|
+
.i18n="${this.__effectiveI18n}"
|
|
261
|
+
class="${ifDefined(item.className)}"
|
|
262
|
+
theme="${ifDefined(this._theme)}"
|
|
263
|
+
aria-hidden="true"
|
|
264
|
+
tabindex="-1"
|
|
265
|
+
></vaadin-avatar>
|
|
266
|
+
${item.name || ''}
|
|
267
|
+
</vaadin-avatar-group-menu-item>
|
|
268
|
+
`,
|
|
269
|
+
)}
|
|
241
270
|
`,
|
|
242
|
-
|
|
271
|
+
this._menuElement,
|
|
243
272
|
{ host: this },
|
|
244
273
|
);
|
|
245
274
|
}
|
|
@@ -305,6 +334,7 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
305
334
|
.img="${item.img}"
|
|
306
335
|
.colorIndex="${item.colorIndex}"
|
|
307
336
|
.i18n="${this.__effectiveI18n}"
|
|
337
|
+
theme="${ifDefined(this._theme)}"
|
|
308
338
|
class="${ifDefined(item.className)}"
|
|
309
339
|
with-tooltip
|
|
310
340
|
></vaadin-avatar>
|
|
@@ -317,58 +347,25 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
317
347
|
}
|
|
318
348
|
|
|
319
349
|
/** @private */
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
326
|
-
|
|
327
|
-
this.__renderAvatars(limit ? items.slice(0, limit) : items);
|
|
328
|
-
|
|
329
|
-
this._avatars = [...this.querySelectorAll('vaadin-avatar')];
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/** @private */
|
|
333
|
-
__computeOverflowItems(items, itemsInView, maxItemsVisible) {
|
|
334
|
-
const count = Array.isArray(items) ? items.length : 0;
|
|
335
|
-
const limit = this.__getLimit(count, itemsInView, maxItemsVisible);
|
|
336
|
-
return limit ? items.slice(limit) : [];
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/** @private */
|
|
340
|
-
__updateOverflowAvatar(overflow, items, itemsInView, maxItemsVisible) {
|
|
350
|
+
__updateOverflowAvatar(items, limit, itemsInView) {
|
|
351
|
+
const overflow = this._overflow;
|
|
341
352
|
if (overflow) {
|
|
342
353
|
const count = Array.isArray(items) ? items.length : 0;
|
|
343
|
-
const maxReached = maxItemsVisible != null && count > this.__getMax(maxItemsVisible);
|
|
354
|
+
const maxReached = this.maxItemsVisible != null && count > this.__getMax(this.maxItemsVisible);
|
|
344
355
|
|
|
345
|
-
overflow.abbr = `+${count -
|
|
356
|
+
overflow.abbr = `+${count - limit}`;
|
|
346
357
|
const hasOverflow = maxReached || (itemsInView && itemsInView < count);
|
|
347
358
|
overflow.toggleAttribute('hidden', !hasOverflow);
|
|
348
|
-
this
|
|
359
|
+
this.toggleAttribute('has-overflow', hasOverflow);
|
|
349
360
|
}
|
|
350
361
|
}
|
|
351
362
|
|
|
352
363
|
/** @private */
|
|
353
|
-
|
|
354
|
-
if (
|
|
355
|
-
[overflow, ...avatars].forEach((avatar) => {
|
|
356
|
-
if (theme) {
|
|
357
|
-
avatar.setAttribute('theme', theme);
|
|
358
|
-
} else {
|
|
359
|
-
avatar.removeAttribute('theme');
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/** @private */
|
|
366
|
-
__updateOverflowTooltip(tooltip, items, itemsInView, maxItemsVisible) {
|
|
367
|
-
if (!tooltip || !Array.isArray(items)) {
|
|
364
|
+
__updateOverflowTooltip(items, limit) {
|
|
365
|
+
if (!Array.isArray(items)) {
|
|
368
366
|
return;
|
|
369
367
|
}
|
|
370
368
|
|
|
371
|
-
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
372
369
|
if (limit == null) {
|
|
373
370
|
return;
|
|
374
371
|
}
|
|
@@ -381,7 +378,7 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
381
378
|
}
|
|
382
379
|
}
|
|
383
380
|
|
|
384
|
-
|
|
381
|
+
this._overflowTooltip.text = result.join('\n');
|
|
385
382
|
}
|
|
386
383
|
|
|
387
384
|
/** @private */
|
|
@@ -450,46 +447,21 @@ export const AvatarGroupMixin = (superClass) =>
|
|
|
450
447
|
if (effectiveI18n.activeUsers[field]) {
|
|
451
448
|
this.setAttribute('aria-label', effectiveI18n.activeUsers[field].replace('{count}', count || 0));
|
|
452
449
|
}
|
|
453
|
-
|
|
454
|
-
this._avatars.forEach((avatar) => {
|
|
455
|
-
avatar.i18n = effectiveI18n;
|
|
456
|
-
});
|
|
457
450
|
}
|
|
458
451
|
}
|
|
459
452
|
|
|
460
453
|
/** @private */
|
|
461
|
-
__openedChanged(opened,
|
|
462
|
-
if (!overflow) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
|
|
454
|
+
__openedChanged(opened, oldOpened) {
|
|
466
455
|
if (opened) {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
this._openedWithFocusRing = overflow.hasAttribute('focus-ring');
|
|
472
|
-
} else if (this.__oldOpened) {
|
|
473
|
-
overflow.focus();
|
|
456
|
+
this._openedWithFocusRing = this._overflow.hasAttribute('focus-ring');
|
|
457
|
+
} else if (oldOpened) {
|
|
458
|
+
this._overflow.focus();
|
|
474
459
|
if (this._openedWithFocusRing) {
|
|
475
|
-
|
|
460
|
+
this._overflow.setAttribute('focus-ring', '');
|
|
476
461
|
}
|
|
477
462
|
}
|
|
478
463
|
|
|
479
|
-
|
|
480
|
-
this.__oldOpened = opened;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
/** @private */
|
|
484
|
-
__overflowItemsChanged(items, oldItems) {
|
|
485
|
-
// Prevent renderer from being called unnecessarily on initialization
|
|
486
|
-
if (items && items.length === 0 && (!oldItems || oldItems.length === 0)) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (items || oldItems) {
|
|
491
|
-
this.$.overlay.requestContentUpdate();
|
|
492
|
-
}
|
|
464
|
+
this._overflow.setAttribute('aria-expanded', opened === true);
|
|
493
465
|
}
|
|
494
466
|
|
|
495
467
|
/** @private */
|
|
@@ -25,7 +25,7 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
25
25
|
* @private
|
|
26
26
|
*/
|
|
27
27
|
class AvatarGroupOverlay extends PositionMixin(
|
|
28
|
-
OverlayMixin(DirMixin(ThemableMixin(LumoInjectionMixin(
|
|
28
|
+
OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))),
|
|
29
29
|
) {
|
|
30
30
|
static get is() {
|
|
31
31
|
return 'vaadin-avatar-group-overlay';
|
|
@@ -38,7 +38,6 @@ class AvatarGroupOverlay extends PositionMixin(
|
|
|
38
38
|
/** @protected */
|
|
39
39
|
render() {
|
|
40
40
|
return html`
|
|
41
|
-
<div id="backdrop" part="backdrop" ?hidden="${!this.withBackdrop}"></div>
|
|
42
41
|
<div part="overlay" id="overlay" tabindex="0">
|
|
43
42
|
<div part="content" id="content">
|
|
44
43
|
<slot></slot>
|
|
@@ -46,6 +45,22 @@ class AvatarGroupOverlay extends PositionMixin(
|
|
|
46
45
|
</div>
|
|
47
46
|
`;
|
|
48
47
|
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @protected
|
|
51
|
+
* @override
|
|
52
|
+
*/
|
|
53
|
+
_attachOverlay() {
|
|
54
|
+
this.showPopover();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @protected
|
|
59
|
+
* @override
|
|
60
|
+
*/
|
|
61
|
+
_detachOverlay() {
|
|
62
|
+
this.hidePopover();
|
|
63
|
+
}
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
defineCustomElement(AvatarGroupOverlay);
|
|
@@ -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.
|
|
@@ -22,13 +22,13 @@ import { AvatarGroupMixin } from './vaadin-avatar-group-mixin.js';
|
|
|
22
22
|
*
|
|
23
23
|
* To create the avatar group, first add the component to the page:
|
|
24
24
|
*
|
|
25
|
-
* ```
|
|
25
|
+
* ```html
|
|
26
26
|
* <vaadin-avatar-group></vaadin-avatar-group>
|
|
27
27
|
* ```
|
|
28
28
|
*
|
|
29
29
|
* And then use [`items`](#/elements/vaadin-avatar-group#property-items) property to initialize the structure:
|
|
30
30
|
*
|
|
31
|
-
* ```
|
|
31
|
+
* ```js
|
|
32
32
|
* document.querySelector('vaadin-avatar-group').items = [
|
|
33
33
|
* {name: 'John Doe'},
|
|
34
34
|
* {abbr: 'AB'}
|
|
@@ -42,6 +42,8 @@ import { AvatarGroupMixin } from './vaadin-avatar-group-mixin.js';
|
|
|
42
42
|
* Part name | Description
|
|
43
43
|
* ----------- | ---------------
|
|
44
44
|
* `container` | The container element
|
|
45
|
+
* `overlay` | The overflow avatar menu overlay
|
|
46
|
+
* `content` | The overflow avatar menu overlay content
|
|
45
47
|
*
|
|
46
48
|
* See the [`<vaadin-avatar>`](#/elements/vaadin-avatar) documentation for the available
|
|
47
49
|
* state attributes and stylable shadow parts of avatar elements.
|
|
@@ -63,7 +65,7 @@ import { AvatarGroupMixin } from './vaadin-avatar-group-mixin.js';
|
|
|
63
65
|
* @mixes AvatarGroupMixin
|
|
64
66
|
* @mixes ThemableMixin
|
|
65
67
|
*/
|
|
66
|
-
class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(LumoInjectionMixin(
|
|
68
|
+
class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
67
69
|
static get is() {
|
|
68
70
|
return 'vaadin-avatar-group';
|
|
69
71
|
}
|
|
@@ -81,14 +83,18 @@ class AvatarGroup extends AvatarGroupMixin(ElementMixin(ThemableMixin(LumoInject
|
|
|
81
83
|
</div>
|
|
82
84
|
<vaadin-avatar-group-overlay
|
|
83
85
|
id="overlay"
|
|
86
|
+
popover="manual"
|
|
87
|
+
.owner="${this}"
|
|
84
88
|
.opened="${this._opened}"
|
|
85
89
|
.positionTarget="${this._overflow}"
|
|
86
|
-
.renderer="${this.__overlayRenderer}"
|
|
87
90
|
no-vertical-overlap
|
|
91
|
+
exportparts="overlay, content"
|
|
88
92
|
@vaadin-overlay-close="${this._onVaadinOverlayClose}"
|
|
89
93
|
@vaadin-overlay-open="${this._onVaadinOverlayOpen}"
|
|
90
94
|
@opened-changed="${this._onOpenedChanged}"
|
|
91
|
-
|
|
95
|
+
>
|
|
96
|
+
<slot name="overlay"></slot>
|
|
97
|
+
</vaadin-avatar-group-overlay>
|
|
92
98
|
`;
|
|
93
99
|
}
|
|
94
100
|
|
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-alpha8",
|
|
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-alpha8/#/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-alpha8/#/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-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-overlay).\n- `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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-alpha8/#/elements/vaadin-item).",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "i18n",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"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-
|
|
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-alpha8/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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
81
|
"value": {
|
|
82
82
|
"type": [
|
|
83
83
|
"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-alpha8",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,7 +16,7 @@
|
|
|
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-alpha8/#/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-alpha8/#/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-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-overlay).\n- `<vaadin-avatar-group-menu>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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-alpha8/#/elements/vaadin-item).",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"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-
|
|
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-alpha8/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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
39
|
"value": {
|
|
40
40
|
"kind": "expression"
|
|
41
41
|
}
|