Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@vaadin/combo-box

Package Overview
Dependencies
Maintainers
14
Versions
413
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/combo-box - npm Package Compare versions

Comparing version 23.1.1 to 23.2.0-alpha1

30

package.json
{
"name": "@vaadin/combo-box",
"version": "23.1.1",
"version": "23.2.0-alpha1",
"publishConfig": {

@@ -22,6 +22,6 @@ "access": "public"

"files": [
"lit.d.ts",
"lit.js",
"src",
"theme",
"lit.js",
"lit.d.ts",
"vaadin-*.d.ts",

@@ -40,21 +40,21 @@ "vaadin-*.js"

"@polymer/polymer": "^3.0.0",
"@vaadin/component-base": "^23.1.1",
"@vaadin/field-base": "^23.1.1",
"@vaadin/input-container": "^23.1.1",
"@vaadin/item": "^23.1.1",
"@vaadin/lit-renderer": "^23.1.1",
"@vaadin/vaadin-lumo-styles": "^23.1.1",
"@vaadin/vaadin-material-styles": "^23.1.1",
"@vaadin/vaadin-overlay": "^23.1.1",
"@vaadin/vaadin-themable-mixin": "^23.1.1"
"@vaadin/component-base": "23.2.0-alpha1",
"@vaadin/field-base": "23.2.0-alpha1",
"@vaadin/input-container": "23.2.0-alpha1",
"@vaadin/item": "23.2.0-alpha1",
"@vaadin/lit-renderer": "23.2.0-alpha1",
"@vaadin/vaadin-lumo-styles": "23.2.0-alpha1",
"@vaadin/vaadin-material-styles": "23.2.0-alpha1",
"@vaadin/vaadin-overlay": "23.2.0-alpha1",
"@vaadin/vaadin-themable-mixin": "23.2.0-alpha1"
},
"devDependencies": {
"@esm-bundle/chai": "^4.3.4",
"@vaadin/polymer-legacy-adapter": "^23.1.1",
"@vaadin/polymer-legacy-adapter": "23.2.0-alpha1",
"@vaadin/testing-helpers": "^0.3.2",
"@vaadin/text-field": "^23.1.1",
"@vaadin/text-field": "23.2.0-alpha1",
"lit": "^2.0.0",
"sinon": "^13.0.2"
},
"gitHead": "390458d6519433a2dd502cef90da48e84573a275"
"gitHead": "f226a2976c270d3d53c824f6e0a740a5d3382d91"
}

@@ -81,3 +81,3 @@ /**

this.clearCache();
this.$.dropdown.addEventListener('index-requested', (e) => {
this._scroller.addEventListener('index-requested', (e) => {
const index = e.detail.index;

@@ -181,43 +181,40 @@ const currentScrollerPos = e.detail.currentScrollerPos;

// Make sure same page isn't requested multiple times.
if (!this._pendingRequests[page] && this.dataProvider) {
this.loading = true;
if (this._pendingRequests[page] || !this.dataProvider) {
return;
}
const params = {
page,
pageSize: this.pageSize,
filter: this.filter,
};
const params = {
page,
pageSize: this.pageSize,
filter: this.filter,
};
const callback = (items, size) => {
if (this._pendingRequests[page] === callback) {
if (!this.filteredItems) {
const filteredItems = [];
filteredItems.splice(params.page * params.pageSize, items.length, ...items);
this.filteredItems = filteredItems;
} else {
this.splice('filteredItems', params.page * params.pageSize, items.length, ...items);
}
// Update selectedItem from filteredItems if value is set
if (this._isValidValue(this.value) && this._getItemValue(this.selectedItem) !== this.value) {
this._selectItemForValue(this.value);
}
if (!this.opened && !this.hasAttribute('focused')) {
this._commitValue();
}
this.size = size;
const callback = (items, size) => {
if (this._pendingRequests[page] !== callback) {
return;
}
delete this._pendingRequests[page];
const filteredItems = this.filteredItems ? [...this.filteredItems] : [];
filteredItems.splice(params.page * params.pageSize, items.length, ...items);
this.filteredItems = filteredItems;
if (Object.keys(this._pendingRequests).length === 0) {
this.loading = false;
}
}
};
if (!this.opened && !this.hasAttribute('focused')) {
this._commitValue();
}
this.size = size;
if (!this._pendingRequests[page]) {
// Don't request page if it's already being requested
this._pendingRequests[page] = callback;
this.dataProvider(params, callback);
delete this._pendingRequests[page];
if (Object.keys(this._pendingRequests).length === 0) {
this.loading = false;
}
}
};
this._pendingRequests[page] = callback;
// Set the `loading` flag only after marking the request as pending
// to prevent the same page from getting requested multiple times
// as a result of `__loadingChanged` in the scroller which requests
// a virtualizer update which in turn may trigger a data provider page request.
this.loading = true;
this.dataProvider(params, callback);
}

@@ -292,3 +289,3 @@

if (dataProvider && value !== '' && (this.selectedItem === undefined || this.selectedItem === null)) {
const valueIndex = this._indexOfValue(value, this.filteredItems);
const valueIndex = this.__getItemIndexByValue(this.filteredItems, value);
if (valueIndex < 0 || !this._getItemLabel(this.filteredItems[valueIndex])) {

@@ -295,0 +292,0 @@ console.warn(

@@ -6,3 +6,5 @@ /**

*/
import './vaadin-combo-box-dropdown.js';
import './vaadin-combo-box-item.js';
import './vaadin-combo-box-overlay.js';
import './vaadin-combo-box-scroller.js';
import { dashToCamelCase } from '@polymer/polymer/lib/utils/case-map.js';

@@ -79,15 +81,12 @@ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';

<vaadin-combo-box-dropdown
id="dropdown"
opened="[[opened]]"
<vaadin-combo-box-overlay
id="overlay"
hidden$="[[_isOverlayHidden(filteredItems, loading)]]"
opened="[[_overlayOpened]]"
loading$="[[loading]]"
theme$="[[_theme]]"
position-target="[[inputElement]]"
restore-focus-on-close="[[__restoreFocusOnClose]]"
no-vertical-overlap
restore-focus-node="[[inputElement]]"
renderer="[[renderer]]"
_focused-index="[[_focusedIndex]]"
_item-id-path="[[itemIdPath]]"
_item-label-path="[[itemLabelPath]]"
loading="[[loading]]"
theme="[[_theme]]"
></vaadin-combo-box-dropdown>
></vaadin-combo-box-overlay>
`;

@@ -94,0 +93,0 @@ }

@@ -151,2 +151,7 @@ /**

/**
* Tag name prefix used by scroller and items.
*/
protected readonly _tagNamePrefix: string;
/**
* Requests an update for the content of items.

@@ -181,4 +186,2 @@ * While performing the update, it invokes the renderer (passed in the `renderer` property) once an item.

protected _revertInputValue(): void;
protected _getItemElements(): HTMLElement[];
}

@@ -16,2 +16,30 @@ /**

/**
* Checks if the value is supported as an item value in this control.
*
* @param {unknown} value
* @return {boolean}
*/
function isValidValue(value) {
return value !== undefined && value !== null;
}
/**
* Returns the index of the first item that satisfies the provided testing function
* ignoring placeholder items.
*
* @param {Array<ComboBoxItem | string>} items
* @param {Function} callback
* @return {number}
*/
function findItemIndex(items, callback) {
return items.findIndex((item) => {
if (item instanceof ComboBoxPlaceholder) {
return false;
}
return callback(item);
});
}
/**
* @polymerMixin

@@ -99,2 +127,3 @@ * @param {function(new:HTMLElement)} subclass

type: Array,
observer: '_filteredItemsChanged',
},

@@ -116,3 +145,2 @@

reflectToAttribute: true,
observer: '_loadingChanged',
},

@@ -202,3 +230,9 @@

/** @private */
__restoreFocusOnClose: Boolean,
_scroller: Object,
/** @private */
_overlayOpened: {
type: Boolean,
observer: '_overlayOpenedChanged',
},
};

@@ -210,5 +244,5 @@ }

'_filterChanged(filter, itemValuePath, itemLabelPath)',
'_itemsOrPathsChanged(items.*, itemValuePath, itemLabelPath)',
'_filteredItemsChanged(filteredItems.*, itemValuePath, itemLabelPath)',
'_selectedItemChanged(selectedItem, itemValuePath, itemLabelPath)',
'_openedOrItemsChanged(opened, filteredItems, loading)',
'_updateScroller(_scroller, filteredItems, opened, loading, selectedItem, itemIdPath, _focusedIndex, renderer, theme)',
];

@@ -222,4 +256,2 @@ }

this._boundOnClearButtonMouseDown = this.__onClearButtonMouseDown.bind(this);
this._boundClose = this.close.bind(this);
this._boundOnOpened = this._onOpened.bind(this);
this._boundOnClick = this._onClick.bind(this);

@@ -231,2 +263,11 @@ this._boundOnOverlayTouchAction = this._onOverlayTouchAction.bind(this);

/**
* Tag name prefix used by scroller and items.
* @protected
* @return {string}
*/
get _tagNamePrefix() {
return 'vaadin-combo-box';
}
/**
* @return {string | undefined}

@@ -284,2 +325,5 @@ * @protected

this._initOverlay();
this._initScroller();
this.addEventListener('focusout', this._boundOnFocusout);

@@ -289,10 +333,3 @@

this.$.dropdown.addEventListener('selection-changed', this._boundOverlaySelectedItemChanged);
this.addEventListener('vaadin-combo-box-dropdown-closed', this._boundClose);
this.addEventListener('vaadin-combo-box-dropdown-opened', this._boundOnOpened);
this.addEventListener('click', this._boundOnClick);
this.$.dropdown.addEventListener('vaadin-overlay-touch-action', this._boundOnOverlayTouchAction);
this.addEventListener('touchend', this._boundOnTouchend);

@@ -302,3 +339,3 @@

requestAnimationFrame(() => {
this.$.dropdown.$.overlay.bringToFront();
this.$.overlay.bringToFront();
});

@@ -315,2 +352,10 @@ };

/** @protected */
disconnectedCallback() {
super.disconnectedCallback();
// Close the overlay on detach
this.close();
}
/**

@@ -323,7 +368,7 @@ * Requests an update for the content of items.

requestContentUpdate() {
if (!this.$.dropdown._scroller) {
if (!this._scroller) {
return;
}
this.$.dropdown._scroller.requestContentUpdate();
this._scroller.requestContentUpdate();

@@ -353,2 +398,100 @@ this._getItemElements().forEach((item) => {

/** @private */
_initOverlay() {
const overlay = this.$.overlay;
// Store instance for detecting "dir" attribute on opening
overlay._comboBox = this;
overlay.addEventListener('touchend', this._boundOnOverlayTouchAction);
overlay.addEventListener('touchmove', this._boundOnOverlayTouchAction);
// Prevent blurring the input when clicking inside the overlay
overlay.addEventListener('mousedown', (e) => e.preventDefault());
// Preventing the default modal behavior of the overlay on input click
overlay.addEventListener('vaadin-overlay-outside-click', (e) => {
e.preventDefault();
});
// Manual two-way binding for the overlay "opened" property
overlay.addEventListener('opened-changed', (e) => {
this._overlayOpened = e.detail.value;
});
}
/**
* Create and initialize the scroller element.
* Override to provide custom host reference.
*
* @protected
*/
_initScroller(host) {
const scrollerTag = `${this._tagNamePrefix}-scroller`;
const overlay = this.$.overlay;
overlay.renderer = (root) => {
if (!root.firstChild) {
root.appendChild(document.createElement(scrollerTag));
}
};
// Ensure the scroller is rendered
if (!this.opened) {
overlay.requestContentUpdate();
}
const scroller = overlay.querySelector(scrollerTag);
scroller.comboBox = host || this;
scroller.getItemLabel = this._getItemLabel.bind(this);
scroller.addEventListener('selection-changed', this._boundOverlaySelectedItemChanged);
// Trigger the observer to set properties
this._scroller = scroller;
}
/** @private */
// eslint-disable-next-line max-params
_updateScroller(scroller, items, opened, loading, selectedItem, itemIdPath, focusedIndex, renderer, theme) {
if (scroller) {
scroller.setProperties({
items: opened ? items : [],
opened,
loading,
selectedItem,
itemIdPath,
focusedIndex,
renderer,
theme,
});
}
}
/** @protected */
_isOverlayHidden(items, loading) {
return !loading && !(items && items.length);
}
/** @private */
_openedOrItemsChanged(opened, items, loading) {
// Close the overlay if there are no items to display.
// See https://github.com/vaadin/vaadin-combo-box/pull/964
this._overlayOpened = !!(opened && (loading || (items && items.length)));
}
/** @private */
_overlayOpenedChanged(opened, wasOpened) {
if (opened) {
this.dispatchEvent(new CustomEvent('vaadin-combo-box-dropdown-opened', { bubbles: true, composed: true }));
this._onOpened();
} else if (wasOpened && this.filteredItems && this.filteredItems.length) {
this.close();
this.dispatchEvent(new CustomEvent('vaadin-combo-box-dropdown-closed', { bubbles: true, composed: true }));
}
}
/** @private */
_focusedIndexChanged(index, oldIndex) {

@@ -391,3 +534,3 @@ if (oldIndex === undefined) {

this.__restoreFocusOnClose = true;
this.$.overlay.restoreFocusOnClose = true;
} else {

@@ -405,3 +548,3 @@ this._onClosed();

if (opened) {
input.setAttribute('aria-controls', this.$.dropdown.scrollerId);
input.setAttribute('aria-controls', this._scroller.id);
} else {

@@ -496,3 +639,3 @@ input.removeAttribute('aria-controls');

if (e.key === 'Tab') {
this.__restoreFocusOnClose = false;
this.$.overlay.restoreFocusOnClose = false;
} else if (e.key === 'ArrowDown') {

@@ -517,3 +660,7 @@ this._closeOnBlurIsPrevented = true;

_getItemLabel(item) {
return this.$.dropdown.getItemLabel(item);
let label = item && this.itemLabelPath ? this.get(this.itemLabelPath, item) : undefined;
if (label === undefined || label === null) {
label = item ? item.toString() : '';
}
return label;
}

@@ -533,3 +680,3 @@

if (this.opened) {
const items = this._getOverlayItems();
const items = this.filteredItems;
if (items) {

@@ -550,3 +697,3 @@ this._focusedIndex = Math.min(items.length - 1, this._focusedIndex + 1);

} else {
const items = this._getOverlayItems();
const items = this.filteredItems;
if (items) {

@@ -566,3 +713,4 @@ this._focusedIndex = items.length - 1;

if (this._focusedIndex > -1) {
this._inputElementValue = this._getItemLabel(this.$.dropdown.focusedItem);
const focusedItem = this.filteredItems[this._focusedIndex];
this._inputElementValue = this._getItemLabel(focusedItem);
this._markAllSelectionRange();

@@ -724,4 +872,8 @@ }

requestAnimationFrame(() => {
this.$.dropdown.adjustScrollPosition();
// When opened is set as attribute, this logic needs to be delayed until scroller is created.
this._scroller.style.maxHeight =
getComputedStyle(this).getPropertyValue(`--${this._tagNamePrefix}-overlay-max-height`) || '65vh';
this._scrollIntoView(this._focusedIndex);
// Set attribute after the items are rendered when overlay is opened for the first time.

@@ -744,5 +896,4 @@ this._updateActiveDescendant(this._focusedIndex);

_commitValue() {
const items = this._getOverlayItems();
if (items && this._focusedIndex > -1) {
const focusedItem = items[this._focusedIndex];
if (this._focusedIndex > -1) {
const focusedItem = this.filteredItems[this._focusedIndex];
if (this.selectedItem !== focusedItem) {

@@ -760,14 +911,10 @@ this.selectedItem = focusedItem;

} else {
const toLowerCase = (item) => item && item.toLowerCase && item.toLowerCase();
// Try to find an item which label matches the input value.
const items = [...(this.filteredItems || []), this.selectedItem];
const itemMatchingInputValue = items[this.__getItemIndexByLabel(items, this._inputElementValue)];
// Try to find an item whose label matches the input value. A matching item is searched from
// the filteredItems array (if available) and the selectedItem (if available).
const itemMatchingByLabel = [...(this.filteredItems || []), this.selectedItem].find((item) => {
return toLowerCase(this._getItemLabel(item)) === toLowerCase(this._inputElementValue);
});
if (
this.allowCustomValue &&
// To prevent a repetitive input value being saved after pressing ESC and Tab.
!itemMatchingByLabel
!itemMatchingInputValue
) {

@@ -789,8 +936,7 @@ const customValue = this._inputElementValue;

if (!e.defaultPrevented) {
this._selectItemForValue(customValue);
this.value = customValue;
}
} else if (!this.allowCustomValue && !this.opened && itemMatchingByLabel) {
} else if (!this.allowCustomValue && !this.opened && itemMatchingInputValue) {
// An item matching by label was found, select it.
this.value = this._getItemValue(itemMatchingByLabel);
this.value = this._getItemValue(itemMatchingInputValue);
} else {

@@ -861,3 +1007,3 @@ // Revert the input value

/** @private */
_filterChanged(filter, itemValuePath, itemLabelPath) {
_filterChanged(filter, _itemValuePath, _itemLabelPath) {
if (filter === undefined) {

@@ -868,4 +1014,6 @@ return;

// Scroll to the top of the list whenever the filter changes.
this.$.dropdown._scrollIntoView(0);
this._scrollIntoView(0);
this._focusedIndex = -1;
if (this.items) {

@@ -877,13 +1025,6 @@ this.filteredItems = this._filterItems(this.items, filter);

// observer should still be invoked to update focused item.
this._filteredItemsChanged({ path: 'filteredItems', value: this.filteredItems }, itemValuePath, itemLabelPath);
this._filteredItemsChanged(this.filteredItems);
}
}
/** @private */
_loadingChanged(loading) {
if (loading) {
this._focusedIndex = -1;
}
}
/** @protected */

@@ -934,5 +1075,3 @@ _revertInputValue() {

this.$.dropdown._selectedItem = selectedItem;
const items = this._getOverlayItems();
if (this.filteredItems && items) {
if (this.filteredItems) {
this._focusedIndex = this.filteredItems.indexOf(selectedItem);

@@ -954,3 +1093,3 @@ }

if (this._isValidValue(value)) {
if (isValidValue(value)) {
let item;

@@ -988,49 +1127,49 @@ if (this._getItemValue(this.selectedItem) !== value) {

});
if (items) {
this.filteredItems = items.slice(0);
} else if (oldItems) {
// Only clear filteredItems if the component had items previously but got cleared
this.filteredItems = null;
}
}
/** @private */
_itemsOrPathsChanged(e) {
if (e.path === 'items' || e.path === 'items.splices') {
if (this.items) {
this.filteredItems = this.items.slice(0);
} else if (this.__previousItems) {
// Only clear filteredItems if the component had items previously but got cleared
this.filteredItems = null;
}
_filteredItemsChanged(filteredItems, oldFilteredItems) {
// Store the currently focused item if any. The focused index preserves
// in the case when more filtered items are loading but it is reset
// when the user types in a filter query.
const focusedItem = oldFilteredItems ? oldFilteredItems[this._focusedIndex] : null;
const valueIndex = this._indexOfValue(this.value, this.items);
this._focusedIndex = valueIndex;
// Try to sync `selectedItem` based on `value` once a new set of `filteredItems` is available
// (as a result of external filtering or when they have been loaded by the data provider).
// When `value` is specified but `selectedItem` is not, it means that there was no item
// matching `value` at the moment `value` was set, so `selectedItem` has remained unsynced.
const valueIndex = this.__getItemIndexByValue(filteredItems, this.value);
if ((this.selectedItem === null || this.selectedItem === undefined) && valueIndex >= 0) {
this.selectedItem = filteredItems[valueIndex];
}
const item = valueIndex > -1 && this.items[valueIndex];
if (item) {
this.selectedItem = item;
}
// Try to first set focus on the item that had been focused before `filteredItems` were updated
// if it is still present in the `filteredItems` array. Otherwise, set the focused index
// depending on the selected item or the filter query.
const focusedItemIndex = this.__getItemIndexByValue(filteredItems, this._getItemValue(focusedItem));
if (focusedItemIndex > -1) {
this._focusedIndex = focusedItemIndex;
} else {
this.__setInitialFocusedIndex();
}
this.__previousItems = e.value;
}
/** @private */
_filteredItemsChanged(e) {
if (e.path === 'filteredItems' || e.path === 'filteredItems.splices') {
this._setOverlayItems(this.filteredItems);
// When the external filtering is used and `value` was provided before `filteredItems`,
// initialize the selected item with the current value here. This will also cause
// the input element value to sync. In other cases, the selected item is already initialized
// in other observers such as `valueChanged`, `_itemsOrPathsChanged`.
const valueIndex = this._indexOfValue(this.value, this.filteredItems);
if (this.selectedItem === null && valueIndex >= 0) {
this._selectItemForValue(this.value);
}
const inputValue = this._inputElementValue;
if (inputValue === undefined || inputValue === this._getItemLabel(this.selectedItem)) {
// When the input element value is the same as the current value or not defined,
// set the focused index to the item that matches the value.
this._focusedIndex = this.$.dropdown.indexOfLabel(this._getItemLabel(this.selectedItem));
} else {
// When the user filled in something that is different from the current value = filtering is enabled,
// set the focused index to the item that matches the filter query.
this._focusedIndex = this.$.dropdown.indexOfLabel(this.filter);
}
__setInitialFocusedIndex() {
const inputValue = this._inputElementValue;
if (inputValue === undefined || inputValue === this._getItemLabel(this.selectedItem)) {
// When the input element value is the same as the current value or not defined,
// set the focused index to the item that matches the value.
this._focusedIndex = this.__getItemIndexByLabel(this.filteredItems, this._getItemLabel(this.selectedItem));
} else {
// When the user filled in something that is different from the current value = filtering is enabled,
// set the focused index to the item that matches the filter query.
this._focusedIndex = this.__getItemIndexByLabel(this.filteredItems, this.filter);
}

@@ -1056,3 +1195,3 @@ }

_selectItemForValue(value) {
const valueIndex = this._indexOfValue(value, this.filteredItems);
const valueIndex = this.__getItemIndexByValue(this.filteredItems, value);
const previouslySelectedItem = this.selectedItem;

@@ -1073,28 +1212,26 @@

/** @protected */
/** @private */
_getItemElements() {
return Array.from(this.$.dropdown._scroller.querySelectorAll('vaadin-combo-box-item'));
return Array.from(this._scroller.querySelectorAll(`${this._tagNamePrefix}-item`));
}
/** @private */
_getOverlayItems() {
return this.$.dropdown._items;
_scrollIntoView(index) {
if (!this._scroller) {
return;
}
this._scroller.scrollIntoView(index);
}
/** @private */
_setOverlayItems(items) {
this.$.dropdown.set('_items', items);
}
/** @private */
_indexOfValue(value, items) {
if (!items || !this._isValidValue(value)) {
/**
* Returns the first item that matches the provided value.
*
* @private
*/
__getItemIndexByValue(items, value) {
if (!items || !isValidValue(value)) {
return -1;
}
return items.findIndex((item) => {
if (item instanceof ComboBoxPlaceholder) {
return false;
}
return findItemIndex(items, (item) => {
return this._getItemValue(item) === value;

@@ -1105,7 +1242,15 @@ });

/**
* Checks if the value is supported as an item value in this control.
* Returns the first item that matches the provided label.
* Labels are matched against each other case insensitively.
*
* @private
*/
_isValidValue(value) {
return value !== undefined && value !== null;
__getItemIndexByLabel(items, label) {
if (!items || !label) {
return -1;
}
return findItemIndex(items, (item) => {
return this._getItemLabel(item).toString().toLowerCase() === label.toString().toLowerCase();
});
}

@@ -1141,3 +1286,3 @@

// Fixes the problem with `focusout` happening when clicking on the scroll bar on Edge
if (event.relatedTarget === this.$.dropdown.$.overlay) {
if (event.relatedTarget === this.$.overlay) {
event.composedPath()[0].focus();

@@ -1218,2 +1363,14 @@ return;

*/
/**
* Fired after the `vaadin-combo-box-overlay` opens.
*
* @event vaadin-combo-box-dropdown-opened
*/
/**
* Fired after the `vaadin-combo-box-overlay` closes.
*
* @event vaadin-combo-box-dropdown-closed
*/
};

@@ -55,5 +55,3 @@ /**

const dropdown = this.__dataHost;
const comboBox = dropdown && dropdown.getRootNode().host;
this._comboBox = comboBox;
const comboBox = this._comboBox;

@@ -60,0 +58,0 @@ const hostDir = comboBox && comboBox.getAttribute('dir');

@@ -7,2 +7,3 @@ /**

import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
import { Virtualizer } from '@vaadin/component-base/src/virtualizer.js';

@@ -94,2 +95,3 @@ import { ComboBoxPlaceholder } from './vaadin-combo-box-placeholder.js';

type: Object,
observer: '__selectedItemChanged',
},

@@ -150,2 +152,5 @@

// Ensure every instance has unique ID
this.id = `${this.localName}-${generateUniqueId()}`;
// Allow extensions to customize tag name for the items

@@ -224,3 +229,3 @@ this.__hostTagName = this.constructor.is.replace('-scroller', '');

__isItemFocused(focusedIndex, itemIndex) {
return focusedIndex === itemIndex;
return !this.loading && focusedIndex === itemIndex;
}

@@ -250,5 +255,5 @@

/** @private */
__loadingChanged(loading) {
if (this.__virtualizer && !loading) {
setTimeout(() => this.requestContentUpdate());
__loadingChanged() {
if (this.__virtualizer) {
this.requestContentUpdate();
}

@@ -258,2 +263,9 @@ }

/** @private */
__selectedItemChanged() {
if (this.__virtualizer) {
this.requestContentUpdate();
}
}
/** @private */
__focusedIndexChanged(index, oldIndex) {

@@ -260,0 +272,0 @@ if (!this.__virtualizer) {

@@ -7,3 +7,5 @@ /**

import '@vaadin/input-container/src/vaadin-input-container.js';
import './vaadin-combo-box-dropdown.js';
import './vaadin-combo-box-item.js';
import './vaadin-combo-box-overlay.js';
import './vaadin-combo-box-scroller.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';

@@ -200,15 +202,12 @@ import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';

<vaadin-combo-box-dropdown
id="dropdown"
opened="[[opened]]"
renderer="[[renderer]]"
<vaadin-combo-box-overlay
id="overlay"
hidden$="[[_isOverlayHidden(filteredItems, loading)]]"
opened="[[_overlayOpened]]"
loading$="[[loading]]"
theme$="[[_theme]]"
position-target="[[_positionTarget]]"
restore-focus-on-close="[[__restoreFocusOnClose]]"
no-vertical-overlap
restore-focus-node="[[inputElement]]"
_focused-index="[[_focusedIndex]]"
_item-id-path="[[itemIdPath]]"
_item-label-path="[[itemLabelPath]]"
loading="[[loading]]"
theme="[[_theme]]"
></vaadin-combo-box-dropdown>
></vaadin-combo-box-overlay>
`;

@@ -278,3 +277,3 @@ }

// Do not blur when focus moves to the overlay
if (event.relatedTarget === this.$.dropdown.$.overlay) {
if (event.relatedTarget === this.$.overlay) {
event.composedPath()[0].focus();

@@ -281,0 +280,0 @@ return false;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc