@vaadin/vaadin-combo-box 21.0.1 → 22.0.0-alpha10
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 +23 -40
- package/src/vaadin-combo-box-light.d.ts +14 -95
- package/src/vaadin-combo-box-light.js +4 -197
- package/src/vaadin-combo-box.d.ts +14 -244
- package/src/vaadin-combo-box.js +4 -414
- package/theme/lumo/vaadin-combo-box-light.js +1 -3
- package/theme/lumo/vaadin-combo-box.js +1 -4
- package/theme/material/vaadin-combo-box-light.js +1 -3
- package/theme/material/vaadin-combo-box.js +1 -4
- package/vaadin-combo-box.d.ts +0 -1
- package/src/interfaces.d.ts +0 -71
- package/src/vaadin-combo-box-data-provider-mixin.d.ts +0 -44
- package/src/vaadin-combo-box-data-provider-mixin.js +0 -323
- package/src/vaadin-combo-box-dropdown-wrapper.js +0 -498
- package/src/vaadin-combo-box-dropdown.js +0 -289
- package/src/vaadin-combo-box-item.js +0 -170
- package/src/vaadin-combo-box-mixin.d.ts +0 -209
- package/src/vaadin-combo-box-mixin.js +0 -1127
- package/src/vaadin-combo-box-placeholder.js +0 -16
- package/theme/lumo/vaadin-combo-box-dropdown-styles.js +0 -87
- package/theme/lumo/vaadin-combo-box-item-styles.js +0 -47
- package/theme/lumo/vaadin-combo-box-styles.js +0 -18
- package/theme/material/vaadin-combo-box-dropdown-styles.js +0 -124
- package/theme/material/vaadin-combo-box-item-styles.js +0 -35
- package/theme/material/vaadin-combo-box-styles.js +0 -25
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
|
|
7
|
-
import '@polymer/iron-list/iron-list.js';
|
|
8
|
-
import './vaadin-combo-box-item.js';
|
|
9
|
-
import './vaadin-combo-box-dropdown.js';
|
|
10
|
-
import { ComboBoxPlaceholder } from './vaadin-combo-box-placeholder.js';
|
|
11
|
-
|
|
12
|
-
const TOUCH_DEVICE = (() => {
|
|
13
|
-
try {
|
|
14
|
-
document.createEvent('TouchEvent');
|
|
15
|
-
return true;
|
|
16
|
-
} catch (e) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
})();
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Element for internal use only.
|
|
23
|
-
*
|
|
24
|
-
* @extends HTMLElement
|
|
25
|
-
* @private
|
|
26
|
-
*/
|
|
27
|
-
class ComboBoxDropdownWrapperElement extends PolymerElement {
|
|
28
|
-
static get template() {
|
|
29
|
-
return html`
|
|
30
|
-
<vaadin-combo-box-dropdown
|
|
31
|
-
id="dropdown"
|
|
32
|
-
hidden="[[_hidden(_items.*, loading)]]"
|
|
33
|
-
position-target="[[positionTarget]]"
|
|
34
|
-
on-position-changed="_setOverlayHeight"
|
|
35
|
-
disable-upgrade=""
|
|
36
|
-
theme="[[theme]]"
|
|
37
|
-
>
|
|
38
|
-
<template>
|
|
39
|
-
<style>
|
|
40
|
-
#scroller {
|
|
41
|
-
overflow: auto;
|
|
42
|
-
|
|
43
|
-
/* Fixes item background from getting on top of scrollbars on Safari */
|
|
44
|
-
transform: translate3d(0, 0, 0);
|
|
45
|
-
|
|
46
|
-
/* Enable momentum scrolling on iOS (iron-list v1.2+ no longer does it for us) */
|
|
47
|
-
-webkit-overflow-scrolling: touch;
|
|
48
|
-
|
|
49
|
-
/* Fixes scrollbar disappearing when 'Show scroll bars: Always' enabled in Safari */
|
|
50
|
-
box-shadow: 0 0 0 white;
|
|
51
|
-
}
|
|
52
|
-
</style>
|
|
53
|
-
<div id="scroller" on-click="_stopPropagation">
|
|
54
|
-
<iron-list id="selector" role="listbox" items="[[_getItems(opened, _items)]]" scroll-target="[[_scroller]]">
|
|
55
|
-
<template>
|
|
56
|
-
<vaadin-combo-box-item
|
|
57
|
-
on-click="_onItemClick"
|
|
58
|
-
index="[[__requestItemByIndex(item, index, _resetScrolling)]]"
|
|
59
|
-
item="[[item]]"
|
|
60
|
-
label="[[getItemLabel(item, _itemLabelPath)]]"
|
|
61
|
-
selected="[[_isItemSelected(item, _selectedItem, _itemIdPath)]]"
|
|
62
|
-
renderer="[[renderer]]"
|
|
63
|
-
role$="[[_getAriaRole(index)]]"
|
|
64
|
-
aria-selected$="[[_getAriaSelected(_focusedIndex,index)]]"
|
|
65
|
-
focused="[[_isItemFocused(_focusedIndex,index)]]"
|
|
66
|
-
tabindex="-1"
|
|
67
|
-
theme$="[[theme]]"
|
|
68
|
-
></vaadin-combo-box-item>
|
|
69
|
-
</template>
|
|
70
|
-
</iron-list>
|
|
71
|
-
</div>
|
|
72
|
-
</template>
|
|
73
|
-
</vaadin-combo-box-dropdown>
|
|
74
|
-
`;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static get is() {
|
|
78
|
-
return 'vaadin-combo-box-dropdown-wrapper';
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
static get properties() {
|
|
82
|
-
return {
|
|
83
|
-
/**
|
|
84
|
-
* True if the device supports touch events.
|
|
85
|
-
*/
|
|
86
|
-
touchDevice: {
|
|
87
|
-
type: Boolean,
|
|
88
|
-
value: TOUCH_DEVICE
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
opened: Boolean,
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* The element to position/align the dropdown by.
|
|
95
|
-
*/
|
|
96
|
-
positionTarget: {
|
|
97
|
-
type: Object
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Custom function for rendering the content of the `<vaadin-combo-box-item>` propagated from the combo box element.
|
|
102
|
-
*/
|
|
103
|
-
renderer: Function,
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* `true` when new items are being loaded.
|
|
107
|
-
*/
|
|
108
|
-
loading: {
|
|
109
|
-
type: Boolean,
|
|
110
|
-
value: false,
|
|
111
|
-
reflectToAttribute: true,
|
|
112
|
-
observer: '_setOverlayHeight'
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Used to propagate the `theme` attribute from the host element.
|
|
117
|
-
*/
|
|
118
|
-
theme: String,
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Used to recognize if the filter changed, so to skip the
|
|
122
|
-
* scrolling restore. If true, then scroll to 0 position. Restore
|
|
123
|
-
* the previous position otherwise.
|
|
124
|
-
*/
|
|
125
|
-
filterChanged: {
|
|
126
|
-
type: Boolean,
|
|
127
|
-
value: false
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Used to recognize scroller reset after new items have been set
|
|
132
|
-
* to iron-list and to ignore unwanted pages load. If 'true', then
|
|
133
|
-
* skip loading of the pages until it becomes 'false'.
|
|
134
|
-
*/
|
|
135
|
-
_resetScrolling: {
|
|
136
|
-
type: Boolean,
|
|
137
|
-
value: false
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
_selectedItem: {
|
|
141
|
-
type: Object
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
_items: {
|
|
145
|
-
type: Object
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
_focusedIndex: {
|
|
149
|
-
type: Number,
|
|
150
|
-
value: -1,
|
|
151
|
-
observer: '_focusedIndexChanged'
|
|
152
|
-
},
|
|
153
|
-
|
|
154
|
-
_focusedItem: {
|
|
155
|
-
type: String,
|
|
156
|
-
computed: '_getFocusedItem(_focusedIndex)'
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
_itemLabelPath: {
|
|
160
|
-
type: String,
|
|
161
|
-
value: 'label'
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
_itemValuePath: {
|
|
165
|
-
type: String,
|
|
166
|
-
value: 'value'
|
|
167
|
-
},
|
|
168
|
-
|
|
169
|
-
_selector: Object,
|
|
170
|
-
|
|
171
|
-
_itemIdPath: String,
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Stores the scroller position before updating the 'items', in
|
|
175
|
-
* order to restore it immediately after 'items' have been updated
|
|
176
|
-
*/
|
|
177
|
-
_oldScrollerPosition: {
|
|
178
|
-
type: Number,
|
|
179
|
-
value: 0
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
static get observers() {
|
|
185
|
-
return ['_loadingChanged(loading)', '_openedChanged(opened, _items, loading)', '_restoreScrollerPosition(_items)'];
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
_fireTouchAction(sourceEvent) {
|
|
189
|
-
this.dispatchEvent(
|
|
190
|
-
new CustomEvent('vaadin-overlay-touch-action', {
|
|
191
|
-
detail: { sourceEvent: sourceEvent }
|
|
192
|
-
})
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
_getItems(opened, items) {
|
|
197
|
-
if (opened) {
|
|
198
|
-
if (this._isNotEmpty(items) && this._selector && !this.filterChanged) {
|
|
199
|
-
// iron-list triggers the scroller's reset after items update, and
|
|
200
|
-
// this is not appropriate for undefined size lazy loading.
|
|
201
|
-
// see https://github.com/vaadin/vaadin-combo-box-flow/issues/386
|
|
202
|
-
// We store iron-list scrolling position in order to restore
|
|
203
|
-
// it later on after the items have been updated.
|
|
204
|
-
const currentScrollerPosition = this._selector.firstVisibleIndex;
|
|
205
|
-
if (currentScrollerPosition !== 0) {
|
|
206
|
-
this._oldScrollerPosition = currentScrollerPosition;
|
|
207
|
-
this._resetScrolling = true;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
// Let the position to be restored in the future calls unless it's not
|
|
211
|
-
// caused by filtering
|
|
212
|
-
this.filterChanged = false;
|
|
213
|
-
return items;
|
|
214
|
-
}
|
|
215
|
-
return [];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
_restoreScrollerPosition(items) {
|
|
219
|
-
if (this._isNotEmpty(items) && this._selector && this._oldScrollerPosition !== 0) {
|
|
220
|
-
// new items size might be less than old scrolling position
|
|
221
|
-
this._scrollIntoView(Math.min(items.length - 1, this._oldScrollerPosition));
|
|
222
|
-
this._resetScrolling = false;
|
|
223
|
-
// reset position to 0 again in order to properly handle the filter
|
|
224
|
-
// cases (scroll to 0 after typing the filter)
|
|
225
|
-
this._oldScrollerPosition = 0;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
_isNotEmpty(items) {
|
|
230
|
-
return !this._isEmpty(items);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
_isEmpty(items) {
|
|
234
|
-
return !items || !items.length;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
_openedChanged(opened, items, loading) {
|
|
238
|
-
if (this.$.dropdown.hasAttribute('disable-upgrade')) {
|
|
239
|
-
if (!opened) {
|
|
240
|
-
return;
|
|
241
|
-
} else {
|
|
242
|
-
this._initDropdown();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (this._isEmpty(items)) {
|
|
247
|
-
this.$.dropdown.__emptyItems = true;
|
|
248
|
-
}
|
|
249
|
-
this.$.dropdown.opened = !!(opened && (loading || this._isNotEmpty(items)));
|
|
250
|
-
this.$.dropdown.__emptyItems = false;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_initDropdown() {
|
|
254
|
-
this.$.dropdown.removeAttribute('disable-upgrade');
|
|
255
|
-
|
|
256
|
-
this._selector = this.$.dropdown.$.overlay.content.querySelector('#selector');
|
|
257
|
-
this._scroller = this.$.dropdown.$.overlay.content.querySelector('#scroller');
|
|
258
|
-
|
|
259
|
-
this._patchWheelOverScrolling();
|
|
260
|
-
|
|
261
|
-
this._loadingChanged(this.loading);
|
|
262
|
-
|
|
263
|
-
this.$.dropdown.$.overlay.addEventListener('touchend', (e) => this._fireTouchAction(e));
|
|
264
|
-
this.$.dropdown.$.overlay.addEventListener('touchmove', (e) => this._fireTouchAction(e));
|
|
265
|
-
|
|
266
|
-
// Prevent blurring the input when clicking inside the overlay.
|
|
267
|
-
this.$.dropdown.$.overlay.addEventListener('mousedown', (e) => e.preventDefault());
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
_loadingChanged(loading) {
|
|
271
|
-
if (this.$.dropdown.hasAttribute('disable-upgrade')) {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (loading) {
|
|
276
|
-
this.$.dropdown.$.overlay.setAttribute('loading', '');
|
|
277
|
-
} else {
|
|
278
|
-
this.$.dropdown.$.overlay.removeAttribute('loading');
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
_setOverlayHeight() {
|
|
283
|
-
if (!this.opened || !this.positionTarget) {
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const targetRect = this.positionTarget.getBoundingClientRect();
|
|
288
|
-
|
|
289
|
-
this._scroller.style.maxHeight =
|
|
290
|
-
getComputedStyle(this).getPropertyValue('--vaadin-combo-box-overlay-max-height') || '65vh';
|
|
291
|
-
|
|
292
|
-
const maxHeight = this._maxOverlayHeight(targetRect);
|
|
293
|
-
|
|
294
|
-
// overlay max height is restrained by the #scroller max height which is set to 65vh in CSS.
|
|
295
|
-
this.$.dropdown.$.overlay.style.maxHeight = maxHeight;
|
|
296
|
-
|
|
297
|
-
// we need to set height for iron-list to make its `firstVisibleIndex` work correctly.
|
|
298
|
-
this._selector.style.maxHeight = maxHeight;
|
|
299
|
-
|
|
300
|
-
this.updateViewportBoundaries();
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
_maxOverlayHeight(targetRect) {
|
|
304
|
-
const margin = 8;
|
|
305
|
-
const minHeight = 116; // Height of two items in combo-box
|
|
306
|
-
if (this.$.dropdown.alignedAbove) {
|
|
307
|
-
return Math.max(targetRect.top - margin + Math.min(document.body.scrollTop, 0), minHeight) + 'px';
|
|
308
|
-
} else {
|
|
309
|
-
return Math.max(document.documentElement.clientHeight - targetRect.bottom - margin, minHeight) + 'px';
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
_getFocusedItem(focusedIndex) {
|
|
314
|
-
if (focusedIndex >= 0) {
|
|
315
|
-
return this._items[focusedIndex];
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
_isItemSelected(item, selectedItem, itemIdPath) {
|
|
320
|
-
if (item instanceof ComboBoxPlaceholder) {
|
|
321
|
-
return false;
|
|
322
|
-
} else if (itemIdPath && item !== undefined && selectedItem !== undefined) {
|
|
323
|
-
return this.get(itemIdPath, item) === this.get(itemIdPath, selectedItem);
|
|
324
|
-
} else {
|
|
325
|
-
return item === selectedItem;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
_onItemClick(e) {
|
|
330
|
-
this.dispatchEvent(new CustomEvent('selection-changed', { detail: { item: e.model.item } }));
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Gets the index of the item with the provided label.
|
|
335
|
-
* @return {number}
|
|
336
|
-
*/
|
|
337
|
-
indexOfLabel(label) {
|
|
338
|
-
if (this._items && label) {
|
|
339
|
-
for (let i = 0; i < this._items.length; i++) {
|
|
340
|
-
if (this.getItemLabel(this._items[i]).toString().toLowerCase() === label.toString().toLowerCase()) {
|
|
341
|
-
return i;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return -1;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* If dataProvider is used, dispatch a request for the item’s index if
|
|
351
|
-
* the item is a placeholder object.
|
|
352
|
-
*
|
|
353
|
-
* @return {number}
|
|
354
|
-
*/
|
|
355
|
-
__requestItemByIndex(item, index, resetScrolling) {
|
|
356
|
-
if (item instanceof ComboBoxPlaceholder && index !== undefined && !resetScrolling) {
|
|
357
|
-
this.dispatchEvent(
|
|
358
|
-
new CustomEvent('index-requested', { detail: { index, currentScrollerPos: this._oldScrollerPosition } })
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return index;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Gets the label string for the item based on the `_itemLabelPath`.
|
|
367
|
-
* @return {string}
|
|
368
|
-
*/
|
|
369
|
-
getItemLabel(item, itemLabelPath) {
|
|
370
|
-
itemLabelPath = itemLabelPath || this._itemLabelPath;
|
|
371
|
-
let label = item && itemLabelPath ? this.get(itemLabelPath, item) : undefined;
|
|
372
|
-
if (label === undefined || label === null) {
|
|
373
|
-
label = item ? item.toString() : '';
|
|
374
|
-
}
|
|
375
|
-
return label;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
_isItemFocused(focusedIndex, itemIndex) {
|
|
379
|
-
return focusedIndex == itemIndex;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
_getAriaSelected(focusedIndex, itemIndex) {
|
|
383
|
-
return this._isItemFocused(focusedIndex, itemIndex).toString();
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
_getAriaRole(itemIndex) {
|
|
387
|
-
return itemIndex !== undefined ? 'option' : false;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
_focusedIndexChanged(index) {
|
|
391
|
-
if (index >= 0) {
|
|
392
|
-
this._scrollIntoView(index);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
_scrollIntoView(index) {
|
|
397
|
-
if (!(this.opened && index >= 0)) {
|
|
398
|
-
return;
|
|
399
|
-
}
|
|
400
|
-
const visibleItemsCount = this._visibleItemsCount();
|
|
401
|
-
|
|
402
|
-
let targetIndex = index;
|
|
403
|
-
|
|
404
|
-
if (index > this._selector.lastVisibleIndex - 1) {
|
|
405
|
-
// Index is below the bottom, scrolling down. Make the item appear at the bottom.
|
|
406
|
-
// First scroll to target (will be at the top of the scroller) to make sure it's rendered.
|
|
407
|
-
this._selector.scrollToIndex(index);
|
|
408
|
-
// Then calculate the index for the following scroll (to get the target to bottom of the scroller).
|
|
409
|
-
targetIndex = index - visibleItemsCount + 1;
|
|
410
|
-
} else if (index > this._selector.firstVisibleIndex) {
|
|
411
|
-
// The item is already visible, scrolling is unnecessary per se. But we need to trigger iron-list to set
|
|
412
|
-
// the correct scrollTop on the scrollTarget. Scrolling to firstVisibleIndex.
|
|
413
|
-
targetIndex = this._selector.firstVisibleIndex;
|
|
414
|
-
}
|
|
415
|
-
this._selector.scrollToIndex(Math.max(0, targetIndex));
|
|
416
|
-
|
|
417
|
-
// Sometimes the item is partly below the bottom edge, detect and adjust.
|
|
418
|
-
const pidx = this._selector._getPhysicalIndex(index),
|
|
419
|
-
physicalItem = this._selector._physicalItems[pidx];
|
|
420
|
-
if (!physicalItem) {
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
const physicalItemRect = physicalItem.getBoundingClientRect(),
|
|
424
|
-
scrollerRect = this._scroller.getBoundingClientRect(),
|
|
425
|
-
scrollTopAdjust = physicalItemRect.bottom - scrollerRect.bottom + this._viewportTotalPaddingBottom;
|
|
426
|
-
if (scrollTopAdjust > 0) {
|
|
427
|
-
this._scroller.scrollTop += scrollTopAdjust;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
ensureItemsRendered() {
|
|
432
|
-
this._selector._render();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
adjustScrollPosition() {
|
|
436
|
-
if (this.opened && this._items) {
|
|
437
|
-
this._scrollIntoView(this._focusedIndex);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* We want to prevent the kinetic scrolling energy from being transferred from the overlay contents over to the parent.
|
|
443
|
-
* Further improvement ideas: after the contents have been scrolled to the top or bottom and scrolling has stopped, it could allow
|
|
444
|
-
* scrolling the parent similarly to touch scrolling.
|
|
445
|
-
*/
|
|
446
|
-
_patchWheelOverScrolling() {
|
|
447
|
-
const selector = this._selector;
|
|
448
|
-
selector.addEventListener('wheel', (e) => {
|
|
449
|
-
const scroller = selector._scroller || selector.scrollTarget;
|
|
450
|
-
const scrolledToTop = scroller.scrollTop === 0;
|
|
451
|
-
const scrolledToBottom = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight <= 1;
|
|
452
|
-
|
|
453
|
-
if (scrolledToTop && e.deltaY < 0) {
|
|
454
|
-
e.preventDefault();
|
|
455
|
-
} else if (scrolledToBottom && e.deltaY > 0) {
|
|
456
|
-
e.preventDefault();
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
updateViewportBoundaries() {
|
|
462
|
-
this._cachedViewportTotalPaddingBottom = undefined;
|
|
463
|
-
this._selector.updateViewportBoundaries();
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
get _viewportTotalPaddingBottom() {
|
|
467
|
-
if (this._cachedViewportTotalPaddingBottom === undefined) {
|
|
468
|
-
const itemsStyle = window.getComputedStyle(this._selector.$.items);
|
|
469
|
-
this._cachedViewportTotalPaddingBottom = [itemsStyle.paddingBottom, itemsStyle.borderBottomWidth]
|
|
470
|
-
.map((v) => {
|
|
471
|
-
return parseInt(v, 10);
|
|
472
|
-
})
|
|
473
|
-
.reduce((sum, v) => {
|
|
474
|
-
return sum + v;
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return this._cachedViewportTotalPaddingBottom;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
_visibleItemsCount() {
|
|
482
|
-
// Ensure items are positioned
|
|
483
|
-
this._selector.scrollToIndex(this._selector.firstVisibleIndex);
|
|
484
|
-
// Ensure viewport boundaries are up-to-date
|
|
485
|
-
this.updateViewportBoundaries();
|
|
486
|
-
return this._selector.lastVisibleIndex - this._selector.firstVisibleIndex + 1;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
_stopPropagation(e) {
|
|
490
|
-
e.stopPropagation();
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
_hidden() {
|
|
494
|
-
return !this.loading && this._isEmpty(this._items);
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
customElements.define(ComboBoxDropdownWrapperElement.is, ComboBoxDropdownWrapperElement);
|