@vaadin/avatar-group 23.3.0-alpha5 → 24.0.0-alpha2
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 +11 -10
- package/src/vaadin-avatar-group.d.ts +5 -3
- package/src/vaadin-avatar-group.js +204 -86
- package/theme/lumo/vaadin-avatar-group-styles.js +3 -14
- package/theme/material/vaadin-avatar-group-styles.js +3 -14
- package/web-types.json +3 -3
- package/web-types.lit.json +3 -3
- package/src/vaadin-avatar-group-list-box.js +0 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/avatar-group",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "24.0.0-alpha2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,14 +37,15 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@polymer/polymer": "^3.0.0",
|
|
40
|
-
"@vaadin/avatar": "
|
|
41
|
-
"@vaadin/component-base": "
|
|
42
|
-
"@vaadin/item": "
|
|
43
|
-
"@vaadin/list-box": "
|
|
44
|
-
"@vaadin/overlay": "
|
|
45
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
46
|
-
"@vaadin/vaadin-material-styles": "
|
|
47
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
40
|
+
"@vaadin/avatar": "24.0.0-alpha2",
|
|
41
|
+
"@vaadin/component-base": "24.0.0-alpha2",
|
|
42
|
+
"@vaadin/item": "24.0.0-alpha2",
|
|
43
|
+
"@vaadin/list-box": "24.0.0-alpha2",
|
|
44
|
+
"@vaadin/overlay": "24.0.0-alpha2",
|
|
45
|
+
"@vaadin/vaadin-lumo-styles": "24.0.0-alpha2",
|
|
46
|
+
"@vaadin/vaadin-material-styles": "24.0.0-alpha2",
|
|
47
|
+
"@vaadin/vaadin-themable-mixin": "24.0.0-alpha2",
|
|
48
|
+
"lit": "^2.0.0"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@esm-bundle/chai": "^4.3.4",
|
|
@@ -55,5 +56,5 @@
|
|
|
55
56
|
"web-types.json",
|
|
56
57
|
"web-types.lit.json"
|
|
57
58
|
],
|
|
58
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "0c16c01a6807e629a84f5a982793afecc1a7ced0"
|
|
59
60
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { AvatarI18n } from '@vaadin/avatar/src/vaadin-avatar.js';
|
|
7
|
+
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
7
8
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
8
9
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
9
10
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
@@ -51,7 +52,9 @@ export interface AvatarGroupItem {
|
|
|
51
52
|
* Part name | Description
|
|
52
53
|
* ----------- | ---------------
|
|
53
54
|
* `container` | The container element
|
|
54
|
-
*
|
|
55
|
+
*
|
|
56
|
+
* See the [`<vaadin-avatar>`](#/elements/vaadin-avatar) documentation for the available
|
|
57
|
+
* state attributes and stylable shadow parts of avatar elements.
|
|
55
58
|
*
|
|
56
59
|
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
57
60
|
*
|
|
@@ -60,10 +63,9 @@ export interface AvatarGroupItem {
|
|
|
60
63
|
* In addition to `<vaadin-avatar-group>` itself, the following internal
|
|
61
64
|
* components are themable:
|
|
62
65
|
*
|
|
63
|
-
* - `<vaadin-avatar-group-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
64
66
|
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
65
67
|
*/
|
|
66
|
-
declare class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(HTMLElement))) {
|
|
68
|
+
declare class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(ControllerMixin(HTMLElement)))) {
|
|
67
69
|
readonly _avatars: HTMLElement[];
|
|
68
70
|
|
|
69
71
|
/**
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
* Copyright (c) 2020 - 2022 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import '@polymer/polymer/lib/elements/dom-repeat.js';
|
|
7
6
|
import '@vaadin/avatar/src/vaadin-avatar.js';
|
|
8
7
|
import '@vaadin/item/src/vaadin-item.js';
|
|
9
|
-
import '
|
|
8
|
+
import '@vaadin/list-box/src/vaadin-list-box.js';
|
|
10
9
|
import './vaadin-avatar-group-overlay.js';
|
|
11
10
|
import { calculateSplices } from '@polymer/polymer/lib/utils/array-splice.js';
|
|
12
11
|
import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
|
|
13
|
-
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
12
|
+
import { html as legacyHtml, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
13
|
+
import { html, render } from 'lit';
|
|
14
14
|
import { announce } from '@vaadin/component-base/src/a11y-announcer.js';
|
|
15
|
+
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
15
16
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
16
17
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
18
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
17
19
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
18
20
|
|
|
19
21
|
const MINIMUM_DISPLAYED_AVATARS = 2;
|
|
@@ -43,7 +45,9 @@ const MINIMUM_DISPLAYED_AVATARS = 2;
|
|
|
43
45
|
* Part name | Description
|
|
44
46
|
* ----------- | ---------------
|
|
45
47
|
* `container` | The container element
|
|
46
|
-
*
|
|
48
|
+
*
|
|
49
|
+
* See the [`<vaadin-avatar>`](#/elements/vaadin-avatar) documentation for the available
|
|
50
|
+
* state attributes and stylable shadow parts of avatar elements.
|
|
47
51
|
*
|
|
48
52
|
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
49
53
|
*
|
|
@@ -52,17 +56,17 @@ const MINIMUM_DISPLAYED_AVATARS = 2;
|
|
|
52
56
|
* In addition to `<vaadin-avatar-group>` itself, the following internal
|
|
53
57
|
* components are themable:
|
|
54
58
|
*
|
|
55
|
-
* - `<vaadin-avatar-group-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
56
59
|
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
57
60
|
*
|
|
58
61
|
* @extends HTMLElement
|
|
62
|
+
* @mixes ControllerMixin
|
|
59
63
|
* @mixes ElementMixin
|
|
60
64
|
* @mixes ThemableMixin
|
|
61
65
|
* @mixes ResizeMixin
|
|
62
66
|
*/
|
|
63
|
-
class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement))) {
|
|
67
|
+
class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(ControllerMixin(PolymerElement)))) {
|
|
64
68
|
static get template() {
|
|
65
|
-
return
|
|
69
|
+
return legacyHtml`
|
|
66
70
|
<style>
|
|
67
71
|
:host {
|
|
68
72
|
display: block;
|
|
@@ -82,7 +86,7 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
82
86
|
flex-wrap: nowrap;
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
::slotted(vaadin-avatar:not(:first-child)) {
|
|
86
90
|
-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>');
|
|
87
91
|
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>');
|
|
88
92
|
-webkit-mask-size: calc(
|
|
@@ -93,13 +97,13 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
93
97
|
);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
::slotted(vaadin-avatar:not([dir='rtl']):not(:first-child)) {
|
|
97
101
|
margin-left: calc(var(--vaadin-avatar-group-overlap) * -1 - var(--vaadin-avatar-outline-width));
|
|
98
102
|
-webkit-mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap));
|
|
99
103
|
mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap));
|
|
100
104
|
}
|
|
101
105
|
|
|
102
|
-
|
|
106
|
+
::slotted(vaadin-avatar[dir='rtl']:not(:first-child)) {
|
|
103
107
|
margin-right: calc(var(--vaadin-avatar-group-overlap) * -1);
|
|
104
108
|
-webkit-mask-position: calc(
|
|
105
109
|
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width)
|
|
@@ -110,58 +114,16 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
110
114
|
}
|
|
111
115
|
</style>
|
|
112
116
|
<div id="container" part="container">
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
name="[[item.name]]"
|
|
116
|
-
abbr="[[item.abbr]]"
|
|
117
|
-
img="[[item.img]]"
|
|
118
|
-
part="avatar"
|
|
119
|
-
theme$="[[_theme]]"
|
|
120
|
-
i18n="[[i18n]]"
|
|
121
|
-
color-index="[[item.colorIndex]]"
|
|
122
|
-
with-tooltip
|
|
123
|
-
></vaadin-avatar>
|
|
124
|
-
</template>
|
|
125
|
-
<vaadin-avatar
|
|
126
|
-
id="overflow"
|
|
127
|
-
part="avatar"
|
|
128
|
-
hidden$="[[__computeMoreHidden(items.length, __itemsInView, __maxReached)]]"
|
|
129
|
-
abbr="[[__computeMore(items.length, __itemsInView, maxItemsVisible)]]"
|
|
130
|
-
theme$="[[_theme]]"
|
|
131
|
-
on-click="_onOverflowClick"
|
|
132
|
-
on-keydown="_onOverflowKeyDown"
|
|
133
|
-
aria-haspopup="listbox"
|
|
134
|
-
>
|
|
135
|
-
<vaadin-tooltip slot="tooltip" generator="[[__overflowTextGenerator]]"></vaadin-tooltip>
|
|
136
|
-
</vaadin-avatar>
|
|
117
|
+
<slot></slot>
|
|
118
|
+
<slot name="overflow"></slot>
|
|
137
119
|
</div>
|
|
138
120
|
<vaadin-avatar-group-overlay
|
|
139
121
|
id="overlay"
|
|
140
122
|
opened="{{_opened}}"
|
|
123
|
+
position-target="[[_overflow]]"
|
|
141
124
|
no-vertical-overlap
|
|
142
125
|
on-vaadin-overlay-close="_onVaadinOverlayClose"
|
|
143
|
-
>
|
|
144
|
-
<template>
|
|
145
|
-
<vaadin-avatar-group-list-box on-keydown="_onListKeyDown">
|
|
146
|
-
<template is="dom-repeat" items="[[__computeExtraItems(items.*, __itemsInView, maxItemsVisible)]]">
|
|
147
|
-
<vaadin-item theme="avatar-group-item" role="option">
|
|
148
|
-
<vaadin-avatar
|
|
149
|
-
name="[[item.name]]"
|
|
150
|
-
abbr="[[item.abbr]]"
|
|
151
|
-
img="[[item.img]]"
|
|
152
|
-
i18n="[[i18n]]"
|
|
153
|
-
part="avatar"
|
|
154
|
-
theme$="[[_theme]]"
|
|
155
|
-
color-index="[[item.colorIndex]]"
|
|
156
|
-
tabindex="-1"
|
|
157
|
-
aria-hidden="true"
|
|
158
|
-
></vaadin-avatar>
|
|
159
|
-
[[item.name]]
|
|
160
|
-
</vaadin-item>
|
|
161
|
-
</template>
|
|
162
|
-
</vaadin-avatar-group-list-box>
|
|
163
|
-
</template>
|
|
164
|
-
</vaadin-avatar-group-overlay>
|
|
126
|
+
></vaadin-avatar-group-overlay>
|
|
165
127
|
`;
|
|
166
128
|
}
|
|
167
129
|
|
|
@@ -254,35 +216,63 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
254
216
|
},
|
|
255
217
|
},
|
|
256
218
|
|
|
219
|
+
/** @private */
|
|
220
|
+
_avatars: {
|
|
221
|
+
type: Array,
|
|
222
|
+
value: () => [],
|
|
223
|
+
},
|
|
224
|
+
|
|
257
225
|
/** @private */
|
|
258
226
|
__maxReached: {
|
|
259
227
|
type: Boolean,
|
|
260
228
|
computed: '__computeMaxReached(items.length, maxItemsVisible)',
|
|
261
229
|
},
|
|
262
230
|
|
|
231
|
+
/** @private */
|
|
232
|
+
__items: {
|
|
233
|
+
type: Array,
|
|
234
|
+
},
|
|
235
|
+
|
|
263
236
|
/** @private */
|
|
264
237
|
__itemsInView: {
|
|
265
238
|
type: Number,
|
|
266
239
|
value: null,
|
|
267
240
|
},
|
|
268
241
|
|
|
242
|
+
/** @private */
|
|
243
|
+
_overflow: {
|
|
244
|
+
type: Object,
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
/** @private */
|
|
248
|
+
_overflowItems: {
|
|
249
|
+
type: Array,
|
|
250
|
+
observer: '__overflowItemsChanged',
|
|
251
|
+
computed: '__computeOverflowItems(items.*, __itemsInView, maxItemsVisible)',
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
/** @private */
|
|
255
|
+
_overflowTooltip: {
|
|
256
|
+
type: Object,
|
|
257
|
+
},
|
|
258
|
+
|
|
269
259
|
/** @private */
|
|
270
260
|
_opened: {
|
|
271
261
|
type: Boolean,
|
|
272
262
|
observer: '__openedChanged',
|
|
273
|
-
value: false,
|
|
274
263
|
},
|
|
275
|
-
|
|
276
|
-
/** @private */
|
|
277
|
-
__overflowTextGenerator: Object,
|
|
278
264
|
};
|
|
279
265
|
}
|
|
280
266
|
|
|
281
267
|
static get observers() {
|
|
282
268
|
return [
|
|
283
|
-
'__computeMoreTooltip(items.length, __itemsInView, maxItemsVisible)',
|
|
284
269
|
'__itemsChanged(items.splices, items.*)',
|
|
285
270
|
'__i18nItemsChanged(i18n.*, items.length)',
|
|
271
|
+
'__updateAvatarsTheme(_overflow, _avatars, _theme)',
|
|
272
|
+
'__updateAvatars(items.*, __itemsInView, maxItemsVisible, _overflow, i18n)',
|
|
273
|
+
'__updateOverflowAbbr(_overflow, items.length, __itemsInView, maxItemsVisible)',
|
|
274
|
+
'__updateOverflowHidden(_overflow, items.length, __itemsInView, __maxReached)',
|
|
275
|
+
'__updateOverflowTooltip(_overflowTooltip, items.length, __itemsInView, maxItemsVisible)',
|
|
286
276
|
];
|
|
287
277
|
}
|
|
288
278
|
|
|
@@ -290,8 +280,27 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
290
280
|
ready() {
|
|
291
281
|
super.ready();
|
|
292
282
|
|
|
293
|
-
this.
|
|
294
|
-
|
|
283
|
+
this._overflowController = new SlotController(
|
|
284
|
+
this,
|
|
285
|
+
'overflow',
|
|
286
|
+
() => document.createElement('vaadin-avatar'),
|
|
287
|
+
(_, overflow) => {
|
|
288
|
+
overflow.setAttribute('aria-haspopup', 'listbox');
|
|
289
|
+
overflow.setAttribute('aria-expanded', 'false');
|
|
290
|
+
overflow.addEventListener('click', (e) => this._onOverflowClick(e));
|
|
291
|
+
overflow.addEventListener('keydown', (e) => this._onOverflowKeyDown(e));
|
|
292
|
+
|
|
293
|
+
const tooltip = document.createElement('vaadin-tooltip');
|
|
294
|
+
tooltip.setAttribute('slot', 'tooltip');
|
|
295
|
+
overflow.appendChild(tooltip);
|
|
296
|
+
|
|
297
|
+
this._overflow = overflow;
|
|
298
|
+
this._overflowTooltip = tooltip;
|
|
299
|
+
},
|
|
300
|
+
);
|
|
301
|
+
this.addController(this._overflowController);
|
|
302
|
+
|
|
303
|
+
this.$.overlay.renderer = this.__overlayRenderer.bind(this);
|
|
295
304
|
|
|
296
305
|
afterNextRender(this, () => {
|
|
297
306
|
this.__setItemsInView();
|
|
@@ -305,17 +314,64 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
305
314
|
this._opened = false;
|
|
306
315
|
}
|
|
307
316
|
|
|
317
|
+
/** @private */
|
|
318
|
+
__getMessage(user, action) {
|
|
319
|
+
return action.replace('{user}', user.name || user.abbr || this.i18n.anonymous);
|
|
320
|
+
}
|
|
321
|
+
|
|
308
322
|
/**
|
|
309
|
-
*
|
|
310
|
-
* @
|
|
323
|
+
* Renders items when they are provided by the `items` property and clears the content otherwise.
|
|
324
|
+
* @param {!HTMLElement} root
|
|
325
|
+
* @param {!Select} _select
|
|
326
|
+
* @private
|
|
311
327
|
*/
|
|
312
|
-
|
|
313
|
-
|
|
328
|
+
__overlayRenderer(root) {
|
|
329
|
+
let listBox = root.firstElementChild;
|
|
330
|
+
if (!listBox) {
|
|
331
|
+
listBox = document.createElement('vaadin-list-box');
|
|
332
|
+
listBox.addEventListener('keydown', (event) => this._onListKeyDown(event));
|
|
333
|
+
root.appendChild(listBox);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
listBox.textContent = '';
|
|
337
|
+
|
|
338
|
+
if (!this._overflowItems) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
this._overflowItems.forEach((item) => {
|
|
343
|
+
listBox.appendChild(this.__createItemElement(item));
|
|
344
|
+
});
|
|
314
345
|
}
|
|
315
346
|
|
|
316
347
|
/** @private */
|
|
317
|
-
|
|
318
|
-
|
|
348
|
+
__createItemElement(item) {
|
|
349
|
+
const itemElement = document.createElement('vaadin-item');
|
|
350
|
+
itemElement.setAttribute('theme', 'avatar-group-item');
|
|
351
|
+
itemElement.setAttribute('role', 'option');
|
|
352
|
+
|
|
353
|
+
const avatar = document.createElement('vaadin-avatar');
|
|
354
|
+
itemElement.appendChild(avatar);
|
|
355
|
+
|
|
356
|
+
avatar.setAttribute('aria-hidden', 'true');
|
|
357
|
+
avatar.setAttribute('tabindex', '-1');
|
|
358
|
+
avatar.i18n = this.i18n;
|
|
359
|
+
|
|
360
|
+
if (this._theme) {
|
|
361
|
+
avatar.setAttribute('theme', this._theme);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
avatar.name = item.name;
|
|
365
|
+
avatar.abbr = item.abbr;
|
|
366
|
+
avatar.img = item.img;
|
|
367
|
+
avatar.colorIndex = item.colorIndex;
|
|
368
|
+
|
|
369
|
+
if (item.name) {
|
|
370
|
+
const text = document.createTextNode(item.name);
|
|
371
|
+
itemElement.appendChild(text);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return itemElement;
|
|
319
375
|
}
|
|
320
376
|
|
|
321
377
|
/** @private */
|
|
@@ -361,17 +417,47 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
361
417
|
}
|
|
362
418
|
|
|
363
419
|
/** @private */
|
|
364
|
-
|
|
420
|
+
__renderAvatars(items) {
|
|
421
|
+
render(
|
|
422
|
+
html`
|
|
423
|
+
${items.map(
|
|
424
|
+
(item) =>
|
|
425
|
+
html`
|
|
426
|
+
<vaadin-avatar
|
|
427
|
+
.name="${item.name}"
|
|
428
|
+
.abbr="${item.abbr}"
|
|
429
|
+
.img="${item.img}"
|
|
430
|
+
.colorIndex="${item.colorIndex}"
|
|
431
|
+
.i18n="${this.i18n}"
|
|
432
|
+
with-tooltip
|
|
433
|
+
></vaadin-avatar>
|
|
434
|
+
`,
|
|
435
|
+
)}
|
|
436
|
+
`,
|
|
437
|
+
this,
|
|
438
|
+
{ renderBefore: this._overflow },
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/** @private */
|
|
443
|
+
__updateAvatars(arr, itemsInView, maxItemsVisible, overflow) {
|
|
444
|
+
if (!overflow) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
365
448
|
const items = arr.base || [];
|
|
366
449
|
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
367
|
-
|
|
450
|
+
|
|
451
|
+
this.__renderAvatars(limit ? items.slice(0, limit) : items);
|
|
452
|
+
|
|
453
|
+
this._avatars = [...this.querySelectorAll('vaadin-avatar')];
|
|
368
454
|
}
|
|
369
455
|
|
|
370
456
|
/** @private */
|
|
371
|
-
|
|
457
|
+
__computeOverflowItems(arr, itemsInView, maxItemsVisible) {
|
|
372
458
|
const items = arr.base || [];
|
|
373
459
|
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible);
|
|
374
|
-
return limit ? items.slice(limit) :
|
|
460
|
+
return limit ? items.slice(limit) : [];
|
|
375
461
|
}
|
|
376
462
|
|
|
377
463
|
/** @private */
|
|
@@ -380,21 +466,43 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
380
466
|
}
|
|
381
467
|
|
|
382
468
|
/** @private */
|
|
383
|
-
|
|
384
|
-
|
|
469
|
+
__updateOverflowAbbr(overflow, items, itemsInView, maxItemsVisible) {
|
|
470
|
+
if (overflow) {
|
|
471
|
+
overflow.abbr = `+${items - this.__getLimit(items, itemsInView, maxItemsVisible)}`;
|
|
472
|
+
}
|
|
385
473
|
}
|
|
386
474
|
|
|
387
475
|
/** @private */
|
|
388
|
-
|
|
389
|
-
|
|
476
|
+
__updateOverflowHidden(overflow, items, itemsInView, maxReached) {
|
|
477
|
+
if (overflow) {
|
|
478
|
+
overflow.toggleAttribute('hidden', !maxReached && !(itemsInView && itemsInView < items));
|
|
479
|
+
}
|
|
390
480
|
}
|
|
391
481
|
|
|
392
482
|
/** @private */
|
|
393
|
-
|
|
483
|
+
__updateAvatarsTheme(overflow, avatars, theme) {
|
|
484
|
+
if (overflow) {
|
|
485
|
+
[overflow, ...avatars].forEach((avatar) => {
|
|
486
|
+
if (theme) {
|
|
487
|
+
avatar.setAttribute('theme', theme);
|
|
488
|
+
} else {
|
|
489
|
+
avatar.removeAttribute('theme');
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/** @private */
|
|
496
|
+
__updateOverflowTooltip(tooltip, items, itemsInView, maxItemsVisible) {
|
|
497
|
+
if (!tooltip) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
394
501
|
const limit = this.__getLimit(items, itemsInView, maxItemsVisible);
|
|
395
502
|
if (limit == null) {
|
|
396
503
|
return;
|
|
397
504
|
}
|
|
505
|
+
|
|
398
506
|
const result = [];
|
|
399
507
|
for (let i = limit; i < items; i++) {
|
|
400
508
|
const item = this.items[i];
|
|
@@ -402,8 +510,8 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
402
510
|
result.push(item.name || item.abbr || 'anonymous');
|
|
403
511
|
}
|
|
404
512
|
}
|
|
405
|
-
|
|
406
|
-
|
|
513
|
+
|
|
514
|
+
tooltip.text = result.join('\n');
|
|
407
515
|
}
|
|
408
516
|
|
|
409
517
|
/** @private */
|
|
@@ -428,7 +536,6 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
428
536
|
/** @private */
|
|
429
537
|
__itemsChanged(splices, itemsChange) {
|
|
430
538
|
const items = itemsChange.base;
|
|
431
|
-
this.$.items.render();
|
|
432
539
|
this.__setItemsInView();
|
|
433
540
|
|
|
434
541
|
// Mutation using group.splice('items')
|
|
@@ -476,6 +583,10 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
476
583
|
if (base.activeUsers[field]) {
|
|
477
584
|
this.setAttribute('aria-label', base.activeUsers[field].replace('{count}', items || 0));
|
|
478
585
|
}
|
|
586
|
+
|
|
587
|
+
this._avatars.forEach((avatar) => {
|
|
588
|
+
avatar.i18n = base;
|
|
589
|
+
});
|
|
479
590
|
}
|
|
480
591
|
}
|
|
481
592
|
|
|
@@ -483,20 +594,27 @@ class AvatarGroup extends ResizeMixin(ElementMixin(ThemableMixin(PolymerElement)
|
|
|
483
594
|
__openedChanged(opened, wasOpened) {
|
|
484
595
|
if (opened) {
|
|
485
596
|
if (!this._menuElement) {
|
|
486
|
-
this._menuElement = this.
|
|
597
|
+
this._menuElement = this.$.overlay.querySelector('vaadin-list-box');
|
|
487
598
|
this._menuElement.setAttribute('role', 'listbox');
|
|
488
599
|
}
|
|
489
600
|
|
|
490
|
-
this._openedWithFocusRing = this
|
|
601
|
+
this._openedWithFocusRing = this._overflow.hasAttribute('focus-ring');
|
|
491
602
|
|
|
492
603
|
this._menuElement.focus();
|
|
493
604
|
} else if (wasOpened) {
|
|
494
|
-
this
|
|
605
|
+
this._overflow.focus();
|
|
495
606
|
if (this._openedWithFocusRing) {
|
|
496
|
-
this
|
|
607
|
+
this._overflow.setAttribute('focus-ring', '');
|
|
497
608
|
}
|
|
498
609
|
}
|
|
499
|
-
this
|
|
610
|
+
this._overflow.setAttribute('aria-expanded', opened === true);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/** @private */
|
|
614
|
+
__overflowItemsChanged(items, oldItems) {
|
|
615
|
+
if (items || oldItems) {
|
|
616
|
+
this.$.overlay.requestContentUpdate();
|
|
617
|
+
}
|
|
500
618
|
}
|
|
501
619
|
|
|
502
620
|
/** @private */
|
|
@@ -55,24 +55,13 @@ registerStyles('vaadin-avatar-group-overlay', [overlay, menuOverlayCore, avatarG
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
registerStyles(
|
|
58
|
-
'vaadin-
|
|
58
|
+
'vaadin-item',
|
|
59
59
|
css`
|
|
60
|
-
|
|
60
|
+
:host([theme='avatar-group-item']) {
|
|
61
61
|
padding: var(--lumo-space-xs);
|
|
62
|
-
padding-
|
|
62
|
+
padding-inline-end: var(--lumo-space-m);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
:host([dir='rtl']) [part='items'] ::slotted(vaadin-item[theme='avatar-group-item']) {
|
|
66
|
-
padding: var(--lumo-space-xs);
|
|
67
|
-
padding-left: var(--lumo-space-m);
|
|
68
|
-
}
|
|
69
|
-
`,
|
|
70
|
-
{ moduleId: 'lumo-avatar-group-list-box' },
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
registerStyles(
|
|
74
|
-
'vaadin-item',
|
|
75
|
-
css`
|
|
76
65
|
:host([theme='avatar-group-item']) [part='content'] {
|
|
77
66
|
display: flex;
|
|
78
67
|
align-items: center;
|
|
@@ -47,24 +47,13 @@ registerStyles('vaadin-avatar-group-overlay', [menuOverlay, avatarGroupOverlay],
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
registerStyles(
|
|
50
|
-
'vaadin-
|
|
50
|
+
'vaadin-item',
|
|
51
51
|
css`
|
|
52
|
-
|
|
52
|
+
:host([theme='avatar-group-item']) {
|
|
53
53
|
padding: 8px;
|
|
54
|
-
padding-
|
|
54
|
+
padding-inline-end: 24px;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
:host([dir='rtl']) [part='items'] ::slotted(vaadin-item[theme='avatar-group-item']) {
|
|
58
|
-
padding: 8px;
|
|
59
|
-
padding-left: 24px;
|
|
60
|
-
}
|
|
61
|
-
`,
|
|
62
|
-
{ moduleId: 'material-avatar-group-list-box' },
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
registerStyles(
|
|
66
|
-
'vaadin-item',
|
|
67
|
-
css`
|
|
68
57
|
:host([theme='avatar-group-item']) [part='content'] {
|
|
69
58
|
display: flex;
|
|
70
59
|
align-items: center;
|
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": "
|
|
4
|
+
"version": "24.0.0-alpha2",
|
|
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```\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/
|
|
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```\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar-group#property-items) property to initialize the structure:\n\n```\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\nSee the [`<vaadin-avatar>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/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/custom-theme/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/24.0.0-alpha2/#/elements/vaadin-overlay).",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "max-items-visible",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"properties": [
|
|
38
38
|
{
|
|
39
39
|
"name": "items",
|
|
40
|
-
"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/
|
|
40
|
+
"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/24.0.0-alpha2/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar#property-colorIndex) properties on the\nstamped avatars.\n\n#### Example\n\n```js\ngroup.items = [\n {\n name: 'User name',\n img: 'url-to-image.png'\n },\n {\n abbr: 'JD',\n colorIndex: 1\n },\n];\n```",
|
|
41
41
|
"value": {
|
|
42
42
|
"type": [
|
|
43
43
|
"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": "
|
|
4
|
+
"version": "24.0.0-alpha2",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,12 +16,12 @@
|
|
|
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```\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/
|
|
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```\n<vaadin-avatar-group></vaadin-avatar-group>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar-group#property-items) property to initialize the structure:\n\n```\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\nSee the [`<vaadin-avatar>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/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/custom-theme/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/24.0.0-alpha2/#/elements/vaadin-overlay).",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
23
23
|
"name": ".items",
|
|
24
|
-
"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/
|
|
24
|
+
"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/24.0.0-alpha2/#/elements/vaadin-avatar#property-name),\n[`abbr`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img)\nand [`colorIndex`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha2/#/elements/vaadin-avatar#property-colorIndex) properties on the\nstamped avatars.\n\n#### Example\n\n```js\ngroup.items = [\n {\n name: 'User name',\n img: 'url-to-image.png'\n },\n {\n abbr: 'JD',\n colorIndex: 1\n },\n];\n```",
|
|
25
25
|
"value": {
|
|
26
26
|
"kind": "expression"
|
|
27
27
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2020 - 2022 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { ListBox } from '@vaadin/list-box/src/vaadin-list-box.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* An element used internally by `<vaadin-avatar-group>`. Not intended to be used separately.
|
|
10
|
-
*
|
|
11
|
-
* @extends ListBox
|
|
12
|
-
* @private
|
|
13
|
-
*/
|
|
14
|
-
class AvatarGroupListBox extends ListBox {
|
|
15
|
-
static get is() {
|
|
16
|
-
return 'vaadin-avatar-group-list-box';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
customElements.define(AvatarGroupListBox.is, AvatarGroupListBox);
|