@vaadin/vaadin-avatar
Advanced tools
Comparing version 22.0.0-alpha1 to 22.0.0-alpha10
{ | ||
"name": "@vaadin/vaadin-avatar", | ||
"version": "22.0.0-alpha1", | ||
"version": "22.0.0-alpha10", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"description": "vaadin-avatar", | ||
"license": "Apache-2.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/vaadin/web-components.git", | ||
"directory": "packages/vaadin-avatar" | ||
}, | ||
"author": "Vaadin Ltd", | ||
"homepage": "https://vaadin.com/components", | ||
"bugs": { | ||
"url": "https://github.com/vaadin/vaadin-avatar/issues" | ||
}, | ||
"main": "vaadin-avatar-group.js", | ||
"module": "vaadin-avatar-group.js", | ||
"repository": "vaadin/vaadin-avatar", | ||
"files": [ | ||
"src", | ||
"theme", | ||
"vaadin-*.d.ts", | ||
"vaadin-*.js" | ||
], | ||
"keywords": [ | ||
@@ -15,35 +34,12 @@ "Vaadin", | ||
], | ||
"author": "Vaadin Ltd", | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/vaadin/vaadin-avatar/issues" | ||
}, | ||
"homepage": "https://vaadin.com/components", | ||
"files": [ | ||
"vaadin-*.d.ts", | ||
"vaadin-*.js", | ||
"src", | ||
"theme" | ||
], | ||
"dependencies": { | ||
"@polymer/iron-a11y-announcer": "^3.0.0", | ||
"@polymer/iron-resizable-behavior": "^3.0.0", | ||
"@polymer/polymer": "^3.0.0", | ||
"@vaadin/vaadin-element-mixin": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-item": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-list-box": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-lumo-styles": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-material-styles": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-overlay": "^22.0.0-alpha1", | ||
"@vaadin/vaadin-themable-mixin": "^22.0.0-alpha1" | ||
"@vaadin/avatar": "22.0.0-alpha10", | ||
"@vaadin/avatar-group": "22.0.0-alpha10" | ||
}, | ||
"devDependencies": { | ||
"@esm-bundle/chai": "^4.1.5", | ||
"@vaadin/testing-helpers": "^0.2.1", | ||
"@esm-bundle/chai": "^4.3.4", | ||
"@vaadin/testing-helpers": "^0.3.0", | ||
"sinon": "^9.2.1" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"gitHead": "c9694d6549bff1f7fffb9ece26178e57fc228a51" | ||
"gitHead": "6d3055383b9c3c8306ea34c6f2e2087e63c49348" | ||
} |
@@ -10,6 +10,3 @@ # <vaadin-avatar> | ||
[](https://www.npmjs.com/package/@vaadin/vaadin-avatar) | ||
[](https://www.webcomponents.org/element/vaadin/vaadin-avatar) | ||
[](https://travis-ci.org/vaadin/vaadin-avatar) | ||
[](https://vaadin.com/directory/component/vaadinvaadin-avatar) | ||
[](https://vaadin.com/directory/component/vaadinvaadin-avatar) | ||
[](https://discord.gg/PHmkCKC) | ||
@@ -24,5 +21,5 @@ | ||
document.querySelector('vaadin-avatar-group').items = [ | ||
{name: 'Foo Bar', colorIndex: 1}, | ||
{colorIndex: 2}, | ||
{name: 'Foo Bar', colorIndex: 3} | ||
{ name: 'Foo Bar', colorIndex: 1 }, | ||
{ colorIndex: 2 }, | ||
{ name: 'Foo Bar', colorIndex: 3 } | ||
]; | ||
@@ -34,3 +31,2 @@ </script> | ||
## Installation | ||
@@ -74,43 +70,6 @@ | ||
## Running API docs and tests in a browser | ||
1. Fork the `vaadin-avatar` repository and clone it locally. | ||
1. Make sure you have [node.js](https://nodejs.org/) 12.x installed. | ||
1. Make sure you have [npm](https://www.npmjs.com/) installed. | ||
1. When in the `vaadin-avatar` directory, run `npm install` to install dependencies. | ||
1. Run `npm start`, browser will automatically open the component API documentation. | ||
1. You can also open visual tests, for example: | ||
- http://127.0.0.1:3000/test/visual/default.html | ||
## Running tests from the command line | ||
1. When in the `vaadin-avatar` directory, run `npm test` | ||
## Debugging tests in the browser | ||
1. Run `npm run debug`, then choose manual mode (M) and open the link in browser. | ||
## Following the coding style | ||
We are using [ESLint](http://eslint.org/) for linting JavaScript code. You can check if your code is following our standards by running `npm run lint`, which will automatically lint all `.js` files. | ||
## Big Thanks | ||
Cross-browser Testing Platform and Open Source <3 Provided by [Sauce Labs](https://saucelabs.com). | ||
## Contributing | ||
To contribute to the component, please read [the guideline](https://github.com/vaadin/vaadin-core/blob/master/CONTRIBUTING.md) first. | ||
Read the [contributing guide](https://vaadin.com/docs/latest/guide/contributing/overview) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components. | ||
## License | ||
@@ -117,0 +76,0 @@ |
@@ -1,115 +0,18 @@ | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
/** | ||
* @license | ||
* Copyright (c) 2021 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { AvatarGroup } from '@vaadin/avatar-group/src/vaadin-avatar-group.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
/** | ||
* @deprecated Import `AvatarGroup` from `@vaadin/avatar-group` instead. | ||
*/ | ||
export type AvatarGroupElement = AvatarGroup; | ||
import { AvatarGroupItem, AvatarGroupI18n } from './interfaces'; | ||
/** | ||
* `<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality. | ||
* | ||
* To create the avatar group, first add the component to the page: | ||
* | ||
* ``` | ||
* <vaadin-avatar-group></vaadin-avatar-group> | ||
* ``` | ||
* | ||
* And then use [`items`](#/elements/vaadin-avatar-group#property-items) property to initialize the structure: | ||
* | ||
* ``` | ||
* document.querySelector('vaadin-avatar-group').items = [ | ||
* {name: 'John Doe'}, | ||
* {abbr: 'AB'} | ||
* ]; | ||
* ``` | ||
* | ||
* ### Styling | ||
* | ||
* The following shadow DOM parts are exposed for styling: | ||
* | ||
* Part name | Description | ||
* ----------- | --------------- | ||
* `container` | The container element | ||
* `avatar` | Individual avatars | ||
* | ||
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation. | ||
* | ||
* ### Internal components | ||
* | ||
* In addition to `<vaadin-avatar-group>` itself, the following internal | ||
* components are themable: | ||
* | ||
* - `<vaadin-avatar-group-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box). | ||
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay). | ||
* @deprecated Import `AvatarGroup` from `@vaadin/avatar-group` instead. | ||
*/ | ||
declare class AvatarGroupElement extends ElementMixin(ThemableMixin(HTMLElement)) { | ||
readonly _avatars: HTMLElement[]; | ||
export const AvatarGroupElement: typeof AvatarGroup; | ||
/** | ||
* An array containing the items which will be stamped as avatars. | ||
* | ||
* The items objects allow to configure [`name`](#/elements/vaadin-avatar#property-name), | ||
* [`abbr`](#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img) | ||
* and [`colorIndex`](#/elements/vaadin-avatar#property-colorIndex) properties on the | ||
* stamped avatars. | ||
* | ||
* #### Example | ||
* | ||
* ```js | ||
* group.items = [ | ||
* { | ||
* name: 'User name', | ||
* img: 'url-to-image.png' | ||
* }, | ||
* { | ||
* abbr: 'JD', | ||
* colorIndex: 1 | ||
* }, | ||
* ]; | ||
* ``` | ||
*/ | ||
items: AvatarGroupItem[] | undefined; | ||
/** | ||
* The maximum number of avatars to display. By default, all the avatars are displayed. | ||
* When _maxItemsVisible_ is set, the overflowing avatars are grouped into one avatar with | ||
* a dropdown. Setting 0 or 1 has no effect so there are always at least two avatars visible. | ||
*/ | ||
maxItemsVisible: number | null | undefined; | ||
/** | ||
* The object used to localize this component. | ||
* To change the default localization, replace the entire | ||
* _i18n_ object or just the property you want to modify. | ||
* | ||
* The object has the following JSON structure and default values: | ||
* ``` | ||
* { | ||
* // Translation of the anonymous user avatar title. | ||
* anonymous: 'anonymous', | ||
* // Translation of the avatar group accessible label. | ||
* // {count} is replaced with the actual count of users. | ||
* activeUsers: { | ||
* one: 'Currently one active user', | ||
* many: 'Currently {count} active users' | ||
* }, | ||
* // Screen reader announcement when user joins group. | ||
* // {user} is replaced with the name or abbreviation. | ||
* // When neither is set, "anonymous" is used instead. | ||
* joined: '{user} joined', | ||
* // Screen reader announcement when user leaves group. | ||
* // {user} is replaced with the name or abbreviation. | ||
* // When neither is set, "anonymous" is used instead. | ||
* left: '{user} left' | ||
* } | ||
* ``` | ||
*/ | ||
i18n: AvatarGroupI18n; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'vaadin-avatar-group': AvatarGroupElement; | ||
} | ||
} | ||
export { AvatarGroupElement }; | ||
export * from '@vaadin/avatar-group/src/vaadin-avatar-group.js'; |
@@ -6,601 +6,9 @@ /** | ||
*/ | ||
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; | ||
import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js'; | ||
import { calculateSplices } from '@polymer/polymer/lib/utils/array-splice.js'; | ||
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js'; | ||
import { timeOut } from '@polymer/polymer/lib/utils/async.js'; | ||
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js'; | ||
import { IronA11yAnnouncer } from '@polymer/iron-a11y-announcer/iron-a11y-announcer.js'; | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import '@vaadin/vaadin-item/src/vaadin-item.js'; | ||
import './vaadin-avatar-group-list-box.js'; | ||
import './vaadin-avatar-group-overlay.js'; | ||
import './vaadin-avatar.js'; | ||
import { AvatarGroup } from '@vaadin/avatar-group/src/vaadin-avatar-group.js'; | ||
const MINIMUM_DISPLAYED_AVATARS = 2; | ||
/** | ||
* `<vaadin-avatar-group>` is a Web Component providing avatar group displaying functionality. | ||
* | ||
* To create the avatar group, first add the component to the page: | ||
* | ||
* ``` | ||
* <vaadin-avatar-group></vaadin-avatar-group> | ||
* ``` | ||
* | ||
* And then use [`items`](#/elements/vaadin-avatar-group#property-items) property to initialize the structure: | ||
* | ||
* ``` | ||
* document.querySelector('vaadin-avatar-group').items = [ | ||
* {name: 'John Doe'}, | ||
* {abbr: 'AB'} | ||
* ]; | ||
* ``` | ||
* | ||
* ### Styling | ||
* | ||
* The following shadow DOM parts are exposed for styling: | ||
* | ||
* Part name | Description | ||
* ----------- | --------------- | ||
* `container` | The container element | ||
* `avatar` | Individual avatars | ||
* | ||
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation. | ||
* | ||
* ### Internal components | ||
* | ||
* In addition to `<vaadin-avatar-group>` itself, the following internal | ||
* components are themable: | ||
* | ||
* - `<vaadin-avatar-group-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box). | ||
* - `<vaadin-avatar-group-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay). | ||
* | ||
* @extends HTMLElement | ||
* @mixes ElementMixin | ||
* @mixes ThemableMixin | ||
* @deprecated Import `AvatarGroup` from `@vaadin/avatar-group` instead. | ||
*/ | ||
class AvatarGroupElement extends ElementMixin(ThemableMixin(mixinBehaviors([IronResizableBehavior], PolymerElement))) { | ||
static get template() { | ||
return html` | ||
<style> | ||
:host { | ||
display: block; | ||
width: 100%; /* prevent collapsing inside non-stretching column flex */ | ||
--vaadin-avatar-group-overlap: 8px; | ||
--vaadin-avatar-group-overlap-border: 2px; | ||
--vaadin-avatar-size: 64px; | ||
} | ||
export const AvatarGroupElement = AvatarGroup; | ||
:host([hidden]) { | ||
display: none !important; | ||
} | ||
[part='container'] { | ||
display: flex; | ||
position: relative; | ||
width: 100%; | ||
flex-wrap: nowrap; | ||
} | ||
[part='avatar']:not(:first-child) { | ||
-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>'); | ||
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>'); | ||
-webkit-mask-size: calc( | ||
300% + var(--vaadin-avatar-group-overlap-border) * 6 - var(--vaadin-avatar-outline-width) * 6 | ||
); | ||
mask-size: calc( | ||
300% + var(--vaadin-avatar-group-overlap-border) * 6 - var(--vaadin-avatar-outline-width) * 6 | ||
); | ||
} | ||
[part='avatar']:not([dir='rtl']):not(:first-child) { | ||
margin-left: calc(var(--vaadin-avatar-group-overlap) * -1 - var(--vaadin-avatar-outline-width)); | ||
-webkit-mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap)); | ||
mask-position: calc(50% - var(--vaadin-avatar-size) + var(--vaadin-avatar-group-overlap)); | ||
} | ||
[part='avatar'][dir='rtl']:not(:first-child) { | ||
margin-right: calc(var(--vaadin-avatar-group-overlap) * -1); | ||
-webkit-mask-position: calc( | ||
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width) | ||
); | ||
mask-position: calc( | ||
50% + var(--vaadin-avatar-size) - var(--vaadin-avatar-group-overlap) + var(--vaadin-avatar-outline-width) | ||
); | ||
} | ||
</style> | ||
<div id="container" part="container"> | ||
<template id="items" is="dom-repeat" items="[[__computeItems(items.*, __itemsInView, maxItemsVisible)]]"> | ||
<vaadin-avatar | ||
name="[[item.name]]" | ||
abbr="[[item.abbr]]" | ||
img="[[item.img]]" | ||
part="avatar" | ||
theme$="[[theme]]" | ||
i18n="[[i18n]]" | ||
color-index="[[item.colorIndex]]" | ||
></vaadin-avatar> | ||
</template> | ||
<vaadin-avatar | ||
id="overflow" | ||
part="avatar" | ||
hidden$="[[__computeMoreHidden(items.length, __itemsInView, __maxReached)]]" | ||
abbr="[[__computeMore(items.length, __itemsInView, maxItemsVisible)]]" | ||
theme$="[[theme]]" | ||
on-click="_onOverflowClick" | ||
on-keydown="_onOverflowKeyDown" | ||
aria-haspopup="listbox" | ||
></vaadin-avatar> | ||
</div> | ||
<vaadin-avatar-group-overlay id="overlay" opened="{{_opened}}" on-vaadin-overlay-close="_onVaadinOverlayClose"> | ||
<template> | ||
<vaadin-avatar-group-list-box on-keydown="_onListKeyDown"> | ||
<template is="dom-repeat" items="[[__computeExtraItems(items.*, __itemsInView, maxItemsVisible)]]"> | ||
<vaadin-item theme="avatar-group-item" role="option"> | ||
<vaadin-avatar | ||
name="[[item.name]]" | ||
abbr="[[item.abbr]]" | ||
img="[[item.img]]" | ||
i18n="[[i18n]]" | ||
part="avatar" | ||
theme$="[[theme]]" | ||
color-index="[[item.colorIndex]]" | ||
tabindex="-1" | ||
aria-hidden="true" | ||
></vaadin-avatar> | ||
[[item.name]] | ||
</vaadin-item> | ||
</template> | ||
</vaadin-avatar-group-list-box> | ||
</template> | ||
</vaadin-avatar-group-overlay> | ||
`; | ||
} | ||
static get is() { | ||
return 'vaadin-avatar-group'; | ||
} | ||
static get version() { | ||
return '22.0.0-alpha1'; | ||
} | ||
static get properties() { | ||
return { | ||
/** | ||
* An array containing the items which will be stamped as avatars. | ||
* | ||
* The items objects allow to configure [`name`](#/elements/vaadin-avatar#property-name), | ||
* [`abbr`](#/elements/vaadin-avatar#property-abbr), [`img`](#/elements/vaadin-avatar#property-img) | ||
* and [`colorIndex`](#/elements/vaadin-avatar#property-colorIndex) properties on the | ||
* stamped avatars. | ||
* | ||
* #### Example | ||
* | ||
* ```js | ||
* group.items = [ | ||
* { | ||
* name: 'User name', | ||
* img: 'url-to-image.png' | ||
* }, | ||
* { | ||
* abbr: 'JD', | ||
* colorIndex: 1 | ||
* }, | ||
* ]; | ||
* ``` | ||
* | ||
* @type {!Array<!AvatarGroupItem> | undefined} | ||
*/ | ||
items: { | ||
type: Array | ||
}, | ||
/** | ||
* The maximum number of avatars to display. By default, all the avatars are displayed. | ||
* When _maxItemsVisible_ is set, the overflowing avatars are grouped into one avatar with | ||
* a dropdown. Setting 0 or 1 has no effect so there are always at least two avatars visible. | ||
*/ | ||
maxItemsVisible: { | ||
type: Number | ||
}, | ||
/** | ||
* The object used to localize this component. | ||
* To change the default localization, replace the entire | ||
* _i18n_ object or just the property you want to modify. | ||
* | ||
* The object has the following JSON structure and default values: | ||
* ``` | ||
* { | ||
* // Translation of the anonymous user avatar title. | ||
* anonymous: 'anonymous', | ||
* // Translation of the avatar group accessible label. | ||
* // {count} is replaced with the actual count of users. | ||
* activeUsers: { | ||
* one: 'Currently one active user', | ||
* many: 'Currently {count} active users' | ||
* }, | ||
* // Screen reader announcement when user joins group. | ||
* // {user} is replaced with the name or abbreviation. | ||
* // When neither is set, "anonymous" is used instead. | ||
* joined: '{user} joined', | ||
* // Screen reader announcement when user leaves group. | ||
* // {user} is replaced with the name or abbreviation. | ||
* // When neither is set, "anonymous" is used instead. | ||
* left: '{user} left' | ||
* } | ||
* ``` | ||
* @type {!AvatarGroupI18n} | ||
* @default {English/US} | ||
*/ | ||
i18n: { | ||
type: Object, | ||
value: () => { | ||
return { | ||
anonymous: 'anonymous', | ||
activeUsers: { | ||
one: 'Currently one active user', | ||
many: 'Currently {count} active users' | ||
}, | ||
joined: '{user} joined', | ||
left: '{user} left' | ||
}; | ||
} | ||
}, | ||
/** @private */ | ||
__maxReached: { | ||
type: Boolean, | ||
computed: '__computeMaxReached(items.length, maxItemsVisible)' | ||
}, | ||
/** @private */ | ||
__itemsInView: { | ||
type: Number, | ||
value: null | ||
}, | ||
/** @private */ | ||
_opened: { | ||
type: Boolean, | ||
observer: '__openedChanged', | ||
value: false | ||
} | ||
}; | ||
} | ||
static get observers() { | ||
return [ | ||
'__computeMoreTitle(items.length, __itemsInView, maxItemsVisible)', | ||
'__itemsChanged(items.splices, items.*)', | ||
'__i18nItemsChanged(i18n.*, items.length)' | ||
]; | ||
} | ||
/** @protected */ | ||
ready() { | ||
super.ready(); | ||
IronA11yAnnouncer.requestAvailability(); | ||
this.__boundSetPosition = this.__setPosition.bind(this); | ||
this.addEventListener('iron-resize', this._onResize.bind(this)); | ||
this._overlayElement = this.shadowRoot.querySelector('vaadin-avatar-group-overlay'); | ||
afterNextRender(this, () => { | ||
this.__setItemsInView(); | ||
}); | ||
} | ||
/** | ||
* @param {string} name | ||
* @param {?string} oldValue | ||
* @param {?string} newValue | ||
* @protected | ||
*/ | ||
attributeChangedCallback(name, oldValue, newValue) { | ||
super.attributeChangedCallback(name, oldValue, newValue); | ||
if (name === 'dir') { | ||
this.__setPosition(); | ||
} | ||
} | ||
/** | ||
* @return {!Array<!HTMLElement>} | ||
* @protected | ||
*/ | ||
get _avatars() { | ||
return this.shadowRoot.querySelectorAll('vaadin-avatar'); | ||
} | ||
/** @private */ | ||
__announce(text) { | ||
this.dispatchEvent( | ||
new CustomEvent('iron-announce', { | ||
bubbles: true, | ||
composed: true, | ||
detail: { | ||
text | ||
} | ||
}) | ||
); | ||
} | ||
/** @private */ | ||
__getMessage(user, action) { | ||
return action.replace('{user}', user.name || user.abbr || this.i18n.anonymous); | ||
} | ||
/** @private */ | ||
_onOverflowClick(e) { | ||
e.stopPropagation(); | ||
if (this._opened) { | ||
this.$.overlay.close(); | ||
} else if (!e.defaultPrevented) { | ||
this._opened = true; | ||
} | ||
} | ||
/** @private */ | ||
_onOverflowKeyDown(e) { | ||
if (!this._opened) { | ||
if (/^(Enter|SpaceBar|\s)$/.test(e.key)) { | ||
e.preventDefault(); | ||
this._opened = true; | ||
} | ||
} | ||
} | ||
/** @private */ | ||
_onListKeyDown(event) { | ||
if (event.key === 'Escape' || event.key === 'Esc' || /^(Tab)$/.test(event.key)) { | ||
this._opened = false; | ||
} | ||
} | ||
/** @private */ | ||
_onResize() { | ||
this.__debounceResize = Debouncer.debounce(this.__debounceResize, timeOut.after(0), () => { | ||
this.__setItemsInView(); | ||
this.__setPosition(); | ||
}); | ||
} | ||
/** @private */ | ||
_onVaadinOverlayClose(e) { | ||
if (e.detail.sourceEvent && e.detail.sourceEvent.composedPath().indexOf(this) !== -1) { | ||
e.preventDefault(); | ||
} | ||
} | ||
/** @private */ | ||
__computeItems(arr, itemsInView, maxItemsVisible) { | ||
const items = arr.base || []; | ||
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible); | ||
return limit ? items.slice(0, limit) : items; | ||
} | ||
/** @private */ | ||
__computeExtraItems(arr, itemsInView, maxItemsVisible) { | ||
const items = arr.base || []; | ||
const limit = this.__getLimit(items.length, itemsInView, maxItemsVisible); | ||
return limit ? items.slice(limit) : items; | ||
} | ||
/** @private */ | ||
__computeMaxReached(items, maxItemsVisible) { | ||
return maxItemsVisible != null && items > this.__getMax(maxItemsVisible); | ||
} | ||
/** @private */ | ||
__computeMore(items, itemsInView, maxItemsVisible) { | ||
return `+${items - this.__getLimit(items, itemsInView, maxItemsVisible)}`; | ||
} | ||
/** @private */ | ||
__computeMoreHidden(items, itemsInView, maxReached) { | ||
return !maxReached && !(itemsInView && itemsInView < items); | ||
} | ||
/** @private */ | ||
__computeMoreTitle(items, itemsInView, maxItemsVisible) { | ||
const limit = this.__getLimit(items, itemsInView, maxItemsVisible); | ||
if (limit == null) { | ||
return; | ||
} | ||
const result = []; | ||
for (let i = limit; i < items; i++) { | ||
const item = this.items[i]; | ||
result.push(item.name || item.abbr || 'anonymous'); | ||
} | ||
// override generated title attribute | ||
this.$.overflow.setAttribute('title', result.join('\n')); | ||
} | ||
/** @private */ | ||
__getLimit(items, itemsInView, maxItemsVisible) { | ||
let limit = null; | ||
// handle max set to 0 or 1 | ||
const adjustedMax = this.__getMax(maxItemsVisible); | ||
if (maxItemsVisible != null && adjustedMax < items) { | ||
limit = adjustedMax - 1; | ||
} else if (itemsInView && itemsInView < items) { | ||
limit = itemsInView; | ||
} | ||
return Math.min(limit, this.__calculateAvatarsFitWidth()); | ||
} | ||
/** @private */ | ||
__getMax(maxItemsVisible) { | ||
return Math.max(maxItemsVisible, MINIMUM_DISPLAYED_AVATARS); | ||
} | ||
/** @private */ | ||
__itemsChanged(splices, itemsChange) { | ||
const items = itemsChange.base; | ||
this.$.items.render(); | ||
this.__setItemsInView(); | ||
// mutation using group.splice('items') | ||
if (splices && Array.isArray(splices.indexSplices)) { | ||
splices.indexSplices.forEach((mutation) => { | ||
this.__announceItemsChange(items, mutation); | ||
}); | ||
} else if (Array.isArray(items) && Array.isArray(this.__oldItems)) { | ||
// mutation using group.set('items') | ||
const diff = calculateSplices(items, this.__oldItems); | ||
diff.forEach((mutation) => { | ||
this.__announceItemsChange(items, mutation); | ||
}); | ||
} | ||
this.__oldItems = items; | ||
} | ||
/** @private */ | ||
__announceItemsChange(items, mutation) { | ||
const { addedCount, index, removed } = mutation; | ||
let addedMsg = []; | ||
let removedMsg = []; | ||
if (addedCount) { | ||
addedMsg = items | ||
.slice(index, index + addedCount) | ||
.map((user) => this.__getMessage(user, this.i18n.joined || '{user} joined')); | ||
} | ||
if (removed) { | ||
removedMsg = removed.map((user) => this.__getMessage(user, this.i18n.left || '{user} left')); | ||
} | ||
const messages = removedMsg.concat(addedMsg); | ||
if (messages.length > 0) { | ||
this.__announce(messages.join(', ')); | ||
} | ||
} | ||
/** @private */ | ||
__i18nItemsChanged(i18n, items) { | ||
const { base } = i18n; | ||
if (base && base.activeUsers) { | ||
const field = items === 1 ? 'one' : 'many'; | ||
if (base.activeUsers[field]) { | ||
this.setAttribute('aria-label', base.activeUsers[field].replace('{count}', items || 0)); | ||
} | ||
} | ||
} | ||
/** @private */ | ||
__openedChanged(opened, wasOpened) { | ||
if (opened) { | ||
if (!this._menuElement) { | ||
this._menuElement = this._overlayElement.content.querySelector('vaadin-avatar-group-list-box'); | ||
this._menuElement.setAttribute('role', 'listbox'); | ||
} | ||
this._openedWithFocusRing = this.$.overflow.hasAttribute('focus-ring'); | ||
const avatars = this._menuElement.querySelectorAll('vaadin-avatar'); | ||
avatars.forEach((avatar) => avatar.removeAttribute('title')); | ||
this._menuElement.focus(); | ||
this.__setPosition(); | ||
window.addEventListener('scroll', this.__boundSetPosition, true); | ||
} else if (wasOpened) { | ||
this.$.overflow.focus(); | ||
if (this._openedWithFocusRing) { | ||
this.$.overflow.setAttribute('focus-ring', ''); | ||
} | ||
window.removeEventListener('scroll', this.__boundSetPosition, true); | ||
} | ||
this.$.overflow.setAttribute('aria-expanded', opened === true); | ||
} | ||
/** @private */ | ||
__setItemsInView() { | ||
const avatars = this._avatars; | ||
const items = this.items; | ||
// always show at least two avatars | ||
if (!items || !avatars || avatars.length < 3) { | ||
return; | ||
} | ||
let result = this.__calculateAvatarsFitWidth(); | ||
// only show overlay if two or more avatars don't fit | ||
if (result === items.length - 1) { | ||
result = items.length; | ||
} | ||
// close overlay if all avatars become visible | ||
if (result >= items.length && this._opened) { | ||
this.$.overlay.close(); | ||
// FIXME: hack to avoid jump before closing | ||
this.$.overlay._flushAnimation('closing'); | ||
} | ||
// reserve space for overflow avatar | ||
this.__itemsInView = result; | ||
} | ||
/** @private **/ | ||
__calculateAvatarsFitWidth() { | ||
if (!this.shadowRoot || this._avatars.length < MINIMUM_DISPLAYED_AVATARS) { | ||
return MINIMUM_DISPLAYED_AVATARS; | ||
} | ||
const avatars = this._avatars; | ||
// assume all the avatars have the same width | ||
const avatarWidth = avatars[0].clientWidth; | ||
// take negative margin into account | ||
const { marginLeft, marginRight } = getComputedStyle(avatars[1]); | ||
const offset = | ||
this.getAttribute('dir') == 'rtl' | ||
? parseInt(marginRight, 0) - parseInt(marginLeft, 0) | ||
: parseInt(marginLeft, 0) - parseInt(marginRight, 0); | ||
return Math.floor((this.$.container.offsetWidth - avatarWidth) / (avatarWidth + offset)); | ||
} | ||
/** @private */ | ||
__setPosition() { | ||
if (!this._opened) { | ||
return; | ||
} | ||
const btnRect = this.$.overflow.getBoundingClientRect(); | ||
const viewportHeight = Math.min(window.innerHeight, document.documentElement.clientHeight); | ||
const bottomAlign = btnRect.top > (viewportHeight - btnRect.height) / 2; | ||
const isRtl = this.getAttribute('dir') === 'rtl'; | ||
if (isRtl) { | ||
this._overlayElement.style.right = document.documentElement.clientWidth - btnRect.right + 'px'; | ||
} else { | ||
this._overlayElement.style.left = btnRect.left + 'px'; | ||
} | ||
if (bottomAlign) { | ||
this._overlayElement.setAttribute('bottom-aligned', ''); | ||
this._overlayElement.style.removeProperty('top'); | ||
this._overlayElement.style.bottom = viewportHeight - btnRect.top + 'px'; | ||
} else { | ||
this._overlayElement.removeAttribute('bottom-aligned'); | ||
this._overlayElement.style.removeProperty('bottom'); | ||
this._overlayElement.style.top = btnRect.bottom + 'px'; | ||
} | ||
} | ||
} | ||
customElements.define(AvatarGroupElement.is, AvatarGroupElement); | ||
export { AvatarGroupElement }; | ||
export * from '@vaadin/avatar-group/src/vaadin-avatar-group.js'; |
@@ -1,74 +0,18 @@ | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
/** | ||
* @license | ||
* Copyright (c) 2021 Vaadin Ltd. | ||
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ | ||
*/ | ||
import { Avatar } from '@vaadin/avatar/src/vaadin-avatar.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
/** | ||
* @deprecated Import `Avatar` from `@vaadin/avatar` instead. | ||
*/ | ||
export type AvatarElement = Avatar; | ||
import { AvatarI18n } from './interfaces'; | ||
/** | ||
* `<vaadin-avatar>` is a Web Component providing avatar displaying functionality. | ||
* | ||
* ```html | ||
* <vaadin-avatar img="avatars/avatar-1.jpg"></vaadin-avatar> | ||
* ``` | ||
* | ||
* ### Styling | ||
* | ||
* The following shadow DOM parts are exposed for styling: | ||
* | ||
* Part name | Description | ||
* --------- | --------------- | ||
* `abbr` | The abbreviation element | ||
* `icon` | The icon element | ||
* | ||
* The following attributes are exposed for styling: | ||
* | ||
* Attribute | Description | ||
* --------- | ----------- | ||
* `has-color-index` | Set when the avatar has `colorIndex` and the corresponding custom CSS property exists. | ||
* | ||
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation. | ||
* @deprecated Import `Avatar` from `@vaadin/avatar` instead. | ||
*/ | ||
declare class AvatarElement extends ElementMixin(ThemableMixin(HTMLElement)) { | ||
/** | ||
* The path to the image | ||
*/ | ||
img: string | null | undefined; | ||
export const AvatarElement: typeof Avatar; | ||
/** | ||
* A shortened form of name that is displayed | ||
* in the avatar when `img` is not provided. | ||
*/ | ||
abbr: string | null | undefined; | ||
/** | ||
* Full name of the user | ||
* used for the title of the avatar. | ||
*/ | ||
name: string | null | undefined; | ||
/** | ||
* Color index used for avatar background. | ||
*/ | ||
colorIndex: number | null | undefined; | ||
/** | ||
* The object used to localize this component. | ||
* To change the default localization, replace the entire | ||
* _i18n_ object or just the property you want to modify. | ||
* | ||
* The object has the following JSON structure and default values: | ||
* { | ||
* // Translation of the anonymous user avatar title. | ||
* anonymous: 'anonymous' | ||
* } | ||
*/ | ||
i18n: AvatarI18n; | ||
} | ||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'vaadin-avatar': AvatarElement; | ||
} | ||
} | ||
export { AvatarElement }; | ||
export * from '@vaadin/avatar/src/vaadin-avatar.js'; |
@@ -6,348 +6,9 @@ /** | ||
*/ | ||
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js'; | ||
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; | ||
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js'; | ||
import './vaadin-avatar-icons.js'; | ||
import { Avatar } from '@vaadin/avatar/src/vaadin-avatar.js'; | ||
// We consider the keyboard to be active if the window has received a keydown | ||
// event since the last mousedown event. | ||
let keyboardActive = false; | ||
// Listen for top-level Tab keydown and mousedown events. | ||
// Use capture phase so we detect events even if they're handled. | ||
window.addEventListener( | ||
'keydown', | ||
(e) => { | ||
keyboardActive = e.keyCode === 9; | ||
}, | ||
true | ||
); | ||
window.addEventListener( | ||
'mousedown', | ||
() => { | ||
keyboardActive = false; | ||
}, | ||
true | ||
); | ||
/** | ||
* `<vaadin-avatar>` is a Web Component providing avatar displaying functionality. | ||
* | ||
* ```html | ||
* <vaadin-avatar img="avatars/avatar-1.jpg"></vaadin-avatar> | ||
* ``` | ||
* | ||
* ### Styling | ||
* | ||
* The following shadow DOM parts are exposed for styling: | ||
* | ||
* Part name | Description | ||
* --------- | --------------- | ||
* `abbr` | The abbreviation element | ||
* `icon` | The icon element | ||
* | ||
* The following attributes are exposed for styling: | ||
* | ||
* Attribute | Description | ||
* --------- | ----------- | ||
* `has-color-index` | Set when the avatar has `colorIndex` and the corresponding custom CSS property exists. | ||
* | ||
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation. | ||
* | ||
* @extends HTMLElement | ||
* @mixes ElementMixin | ||
* @mixes ThemableMixin | ||
* @deprecated Import `Avatar` from `@vaadin/avatar` instead. | ||
*/ | ||
class AvatarElement extends ElementMixin(ThemableMixin(PolymerElement)) { | ||
static get template() { | ||
return html` | ||
<style> | ||
:host { | ||
display: inline-block; | ||
flex: none; | ||
border-radius: 50%; | ||
overflow: hidden; | ||
height: var(--vaadin-avatar-size); | ||
width: var(--vaadin-avatar-size); | ||
border: var(--vaadin-avatar-outline-width) solid transparent; | ||
margin: calc(var(--vaadin-avatar-outline-width) * -1); | ||
background-clip: content-box; | ||
--vaadin-avatar-outline-width: 2px; | ||
--vaadin-avatar-size: 64px; | ||
} | ||
export const AvatarElement = Avatar; | ||
img { | ||
height: 100%; | ||
width: 100%; | ||
object-fit: cover; | ||
} | ||
[part='icon'] { | ||
font-size: 5.6em; | ||
} | ||
[part='abbr'] { | ||
font-size: 2.2em; | ||
} | ||
[part='icon'] > text { | ||
font-family: 'vaadin-avatar-icons'; | ||
} | ||
:host([hidden]) { | ||
display: none !important; | ||
} | ||
svg[hidden] { | ||
display: none !important; | ||
} | ||
:host([has-color-index]) { | ||
position: relative; | ||
background-color: var(--vaadin-avatar-user-color); | ||
} | ||
:host([has-color-index])::before { | ||
position: absolute; | ||
content: ''; | ||
top: 0; | ||
left: 0; | ||
bottom: 0; | ||
right: 0; | ||
border-radius: inherit; | ||
box-shadow: inset 0 0 0 2px var(--vaadin-avatar-user-color); | ||
} | ||
</style> | ||
<img hidden$="[[!__imgVisible]]" src$="[[img]]" aria-hidden="true" on-error="__onImageLoadError" /> | ||
<svg | ||
part="icon" | ||
hidden$="[[!__iconVisible]]" | ||
id="avatar-icon" | ||
viewBox="-50 -50 100 100" | ||
preserveAspectRatio="xMidYMid meet" | ||
aria-hidden="true" | ||
> | ||
<text dy=".35em" text-anchor="middle"></text> | ||
</svg> | ||
<svg | ||
part="abbr" | ||
hidden$="[[!__abbrVisible]]" | ||
id="avatar-abbr" | ||
viewBox="-50 -50 100 100" | ||
preserveAspectRatio="xMidYMid meet" | ||
aria-hidden="true" | ||
> | ||
<text dy=".35em" text-anchor="middle">[[abbr]]</text> | ||
</svg> | ||
`; | ||
} | ||
static get is() { | ||
return 'vaadin-avatar'; | ||
} | ||
static get version() { | ||
return '22.0.0-alpha1'; | ||
} | ||
static get properties() { | ||
return { | ||
/** | ||
* The path to the image | ||
*/ | ||
img: { | ||
type: String, | ||
reflectToAttribute: true, | ||
observer: '__imgChanged' | ||
}, | ||
/** | ||
* A shortened form of name that is displayed | ||
* in the avatar when `img` is not provided. | ||
*/ | ||
abbr: { | ||
type: String, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* Full name of the user | ||
* used for the title of the avatar. | ||
*/ | ||
name: { | ||
type: String, | ||
reflectToAttribute: true | ||
}, | ||
/** | ||
* Color index used for avatar background. | ||
*/ | ||
colorIndex: { | ||
type: Number, | ||
observer: '__colorIndexChanged' | ||
}, | ||
/** | ||
* The object used to localize this component. | ||
* To change the default localization, replace the entire | ||
* _i18n_ object or just the property you want to modify. | ||
* | ||
* The object has the following JSON structure and default values: | ||
{ | ||
// Translation of the anonymous user avatar title. | ||
anonymous: 'anonymous' | ||
} | ||
* @type {!AvatarI18n} | ||
* @default {English/US} | ||
*/ | ||
i18n: { | ||
type: Object, | ||
value: () => { | ||
return { | ||
anonymous: 'anonymous' | ||
}; | ||
} | ||
}, | ||
/** @private */ | ||
__imgVisible: Boolean, | ||
/** @private */ | ||
__iconVisible: Boolean, | ||
/** @private */ | ||
__abbrVisible: Boolean | ||
}; | ||
} | ||
static get observers() { | ||
return ['__imgOrAbbrOrNameChanged(img, abbr, name)', '__i18nChanged(i18n.*)']; | ||
} | ||
/** @protected */ | ||
ready() { | ||
super.ready(); | ||
this.__updateVisibility(); | ||
// Should set `anonymous` if name / abbr is not provided | ||
if (!this.name && !this.abbr) { | ||
this.__setTitle(this.name); | ||
} | ||
this.setAttribute('role', 'button'); | ||
if (!this.hasAttribute('tabindex')) { | ||
this.setAttribute('tabindex', '0'); | ||
} | ||
this.addEventListener('focusin', () => { | ||
this.__setFocused(true); | ||
}); | ||
this.addEventListener('focusout', () => { | ||
this.__setFocused(false); | ||
}); | ||
} | ||
/** @private */ | ||
__setFocused(focused) { | ||
if (focused) { | ||
this.setAttribute('focused', ''); | ||
if (keyboardActive) { | ||
this.setAttribute('focus-ring', ''); | ||
} | ||
} else { | ||
this.removeAttribute('focused'); | ||
this.removeAttribute('focus-ring'); | ||
} | ||
} | ||
/** @private */ | ||
__colorIndexChanged(index) { | ||
if (index != null) { | ||
const prop = `--vaadin-user-color-${index}`; | ||
// check if custom CSS property is defined | ||
const isValid = Boolean(getComputedStyle(document.documentElement).getPropertyValue(prop)); | ||
if (isValid) { | ||
this.setAttribute('has-color-index', ''); | ||
this.style.setProperty('--vaadin-avatar-user-color', `var(${prop})`); | ||
} else { | ||
this.removeAttribute('has-color-index'); | ||
console.warn(`The CSS property --vaadin-user-color-${index} is not defined`); | ||
} | ||
} else { | ||
this.removeAttribute('has-color-index'); | ||
} | ||
} | ||
/** @private */ | ||
__imgChanged() { | ||
this.__imgFailedToLoad = false; | ||
} | ||
/** @private */ | ||
__imgOrAbbrOrNameChanged(img, abbr, name) { | ||
this.__updateVisibility(); | ||
if (abbr && abbr !== this.__generatedAbbr) { | ||
this.__setTitle(name ? `${name} (${abbr})` : abbr); | ||
return; | ||
} | ||
if (name) { | ||
this.abbr = this.__generatedAbbr = name | ||
.split(' ') | ||
.map((word) => word.charAt(0)) | ||
.join(''); | ||
} else { | ||
this.abbr = undefined; | ||
} | ||
this.__setTitle(name); | ||
} | ||
/** @private */ | ||
__i18nChanged(i18n) { | ||
if (i18n.base && i18n.base.anonymous) { | ||
if (this.__oldAnonymous && this.getAttribute('title') === this.__oldAnonymous) { | ||
this.__setTitle(); | ||
} | ||
this.__oldAnonymous = i18n.base.anonymous; | ||
} | ||
} | ||
/** @private */ | ||
__updateVisibility() { | ||
this.__imgVisible = !!this.img && !this.__imgFailedToLoad; | ||
this.__abbrVisible = !this.__imgVisible && !!this.abbr; | ||
this.__iconVisible = !this.__imgVisible && !this.abbr; | ||
} | ||
/** @private */ | ||
__setTitle(title) { | ||
if (title) { | ||
this.setAttribute('title', title); | ||
} else { | ||
this.setAttribute('title', this.i18n.anonymous); | ||
} | ||
} | ||
/** @private */ | ||
__onImageLoadError() { | ||
if (this.img) { | ||
console.warn(`<vaadin-avatar> The specified image could not be loaded: ${this.img}`); | ||
this.__imgFailedToLoad = true; | ||
this.__updateVisibility(); | ||
} | ||
} | ||
} | ||
customElements.define(AvatarElement.is, AvatarElement); | ||
export { AvatarElement }; | ||
export * from '@vaadin/avatar/src/vaadin-avatar.js'; |
@@ -1,5 +0,1 @@ | ||
import './vaadin-avatar.js'; | ||
import './vaadin-avatar-group-styles.js'; | ||
import '@vaadin/vaadin-item/theme/lumo/vaadin-item.js'; | ||
import '@vaadin/vaadin-list-box/theme/lumo/vaadin-list-box.js'; | ||
import '../../src/vaadin-avatar-group.js'; | ||
import '@vaadin/avatar-group/theme/lumo/vaadin-avatar-group.js'; |
@@ -1,2 +0,1 @@ | ||
import './vaadin-avatar-styles.js'; | ||
import '../../src/vaadin-avatar.js'; | ||
import '@vaadin/avatar/theme/lumo/vaadin-avatar.js'; |
@@ -1,5 +0,1 @@ | ||
import './vaadin-avatar.js'; | ||
import './vaadin-avatar-group-styles.js'; | ||
import '@vaadin/vaadin-item/theme/material/vaadin-item.js'; | ||
import '@vaadin/vaadin-list-box/theme/material/vaadin-list-box.js'; | ||
import '../../src/vaadin-avatar-group.js'; | ||
import '@vaadin/avatar-group/theme/material/vaadin-avatar-group.js'; |
@@ -1,2 +0,1 @@ | ||
import './vaadin-avatar-styles.js'; | ||
import '../../src/vaadin-avatar.js'; | ||
import '@vaadin/avatar/theme/material/vaadin-avatar.js'; |
export * from './src/vaadin-avatar-group.js'; | ||
export * from './src/interfaces'; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
2
0
16649
15
62
76
1
+ Added@vaadin/avatar@22.0.0-alpha10(transitive)
+ Added@vaadin/avatar-group@22.0.0-alpha10(transitive)
+ Added@vaadin/component-base@22.0.0-alpha10(transitive)
+ Added@vaadin/icon@22.0.0-alpha10(transitive)
+ Added@vaadin/item@22.0.0-alpha10(transitive)
+ Added@vaadin/list-box@22.0.0-alpha10(transitive)
+ Added@vaadin/vaadin-list-mixin@22.0.0-alpha10(transitive)
+ Added@vaadin/vaadin-lumo-styles@22.0.0-alpha10(transitive)
+ Added@vaadin/vaadin-material-styles@22.0.0-alpha10(transitive)
+ Added@vaadin/vaadin-overlay@22.0.0-alpha10(transitive)
+ Added@vaadin/vaadin-themable-mixin@22.0.0-alpha10(transitive)
- Removed@polymer/iron-a11y-announcer@^3.0.0
- Removed@polymer/polymer@^3.0.0
- Removed@vaadin/vaadin-item@^22.0.0-alpha1
- Removed@open-wc/dedupe-mixin@1.4.0(transitive)
- Removed@vaadin/component-base@22.1.0(transitive)
- Removed@vaadin/icon@22.1.0(transitive)
- Removed@vaadin/item@22.1.0(transitive)
- Removed@vaadin/list-box@22.1.0(transitive)
- Removed@vaadin/vaadin-element-mixin@22.0.0-alpha6(transitive)
- Removed@vaadin/vaadin-item@22.1.0(transitive)
- Removed@vaadin/vaadin-list-box@22.1.0(transitive)
- Removed@vaadin/vaadin-list-mixin@22.1.0(transitive)
- Removed@vaadin/vaadin-lumo-styles@22.1.0(transitive)
- Removed@vaadin/vaadin-material-styles@22.1.0(transitive)
- Removed@vaadin/vaadin-overlay@22.1.0(transitive)
- Removed@vaadin/vaadin-themable-mixin@22.1.0(transitive)