@vaadin/component-base 25.0.0-alpha17 → 25.0.0-alpha19
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 +5 -5
- package/src/define.js +1 -1
- package/src/virtualizer-iron-list-adapter.js +61 -126
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-alpha19",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
35
35
|
"@vaadin/vaadin-development-mode-detector": "^2.0.0",
|
|
36
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-
|
|
36
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha19",
|
|
37
37
|
"@vaadin/vaadin-usage-statistics": "^2.1.0",
|
|
38
38
|
"lit": "^3.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
42
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
41
|
+
"@vaadin/chai-plugins": "25.0.0-alpha19",
|
|
42
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha19",
|
|
43
43
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
44
44
|
"sinon": "^21.0.0"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "1f9af1ce5f0bae8daff044176c8a8df697763881"
|
|
47
47
|
}
|
package/src/define.js
CHANGED
|
@@ -13,7 +13,7 @@ function dashToCamelCase(dash) {
|
|
|
13
13
|
|
|
14
14
|
const experimentalMap = {};
|
|
15
15
|
|
|
16
|
-
export function defineCustomElement(CustomElement, version = '25.0.0-
|
|
16
|
+
export function defineCustomElement(CustomElement, version = '25.0.0-alpha19') {
|
|
17
17
|
Object.defineProperty(CustomElement, 'version', {
|
|
18
18
|
get() {
|
|
19
19
|
return version;
|
|
@@ -14,15 +14,29 @@ const MAX_VIRTUAL_COUNT = 100000;
|
|
|
14
14
|
const OFFSET_ADJUST_MIN_THRESHOLD = 1000;
|
|
15
15
|
|
|
16
16
|
export class IronListAdapter {
|
|
17
|
-
constructor({
|
|
17
|
+
constructor({
|
|
18
|
+
createElements,
|
|
19
|
+
updateElement,
|
|
20
|
+
scrollTarget,
|
|
21
|
+
scrollContainer,
|
|
22
|
+
reorderElements,
|
|
23
|
+
elementsContainer,
|
|
24
|
+
__disableHeightPlaceholder,
|
|
25
|
+
}) {
|
|
18
26
|
this.isAttached = true;
|
|
19
27
|
this._vidxOffset = 0;
|
|
20
28
|
this.createElements = createElements;
|
|
21
29
|
this.updateElement = updateElement;
|
|
22
30
|
this.scrollTarget = scrollTarget;
|
|
23
31
|
this.scrollContainer = scrollContainer;
|
|
24
|
-
this.elementsContainer = elementsContainer || scrollContainer;
|
|
25
32
|
this.reorderElements = reorderElements;
|
|
33
|
+
this.elementsContainer = elementsContainer || scrollContainer;
|
|
34
|
+
|
|
35
|
+
// Internal option that disables the heavy height placeholder calculation
|
|
36
|
+
// (see __afterElementsUpdated) for components that always render virtual
|
|
37
|
+
// elements with a non-zero height. Not for public use.
|
|
38
|
+
this.__disableHeightPlaceholder = __disableHeightPlaceholder ?? false;
|
|
39
|
+
|
|
26
40
|
// Iron-list uses this value to determine how many pages of elements to render
|
|
27
41
|
this._maxPages = 1.3;
|
|
28
42
|
|
|
@@ -33,7 +47,7 @@ export class IronListAdapter {
|
|
|
33
47
|
|
|
34
48
|
this.timeouts = {
|
|
35
49
|
SCROLL_REORDER: 500,
|
|
36
|
-
|
|
50
|
+
PREVENT_OVERSCROLL: 500,
|
|
37
51
|
FIX_INVALID_ITEM_POSITIONING: 100,
|
|
38
52
|
};
|
|
39
53
|
|
|
@@ -65,7 +79,6 @@ export class IronListAdapter {
|
|
|
65
79
|
attachObserver.observe(this.scrollTarget);
|
|
66
80
|
|
|
67
81
|
this._scrollLineHeight = this._getScrollLineHeight();
|
|
68
|
-
this.scrollTarget.addEventListener('wheel', (e) => this.__onWheel(e));
|
|
69
82
|
|
|
70
83
|
this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
|
|
71
84
|
this.elementsContainer.addEventListener('focusin', () => {
|
|
@@ -271,33 +284,35 @@ export class IronListAdapter {
|
|
|
271
284
|
* @param {!Array<!HTMLElement>} updatedElements
|
|
272
285
|
*/
|
|
273
286
|
__afterElementsUpdated(updatedElements) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
this.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
287
|
+
if (!this.__disableHeightPlaceholder) {
|
|
288
|
+
updatedElements.forEach((el) => {
|
|
289
|
+
const elementHeight = el.offsetHeight;
|
|
290
|
+
if (elementHeight === 0) {
|
|
291
|
+
// If the elements have 0 height after update (for example due to lazy rendering),
|
|
292
|
+
// it results in iron-list requesting to create an unlimited count of elements.
|
|
293
|
+
// Assign a temporary placeholder sizing to elements that would otherwise end up having
|
|
294
|
+
// no height.
|
|
295
|
+
el.style.paddingTop = `${this.__placeholderHeight}px`;
|
|
296
|
+
el.style.opacity = '0';
|
|
297
|
+
el.__virtualizerPlaceholder = true;
|
|
298
|
+
|
|
299
|
+
// Manually schedule the resize handler to make sure the placeholder padding is
|
|
300
|
+
// cleared in case the resize observer never triggers.
|
|
301
|
+
this.__placeholderClearDebouncer = Debouncer.debounce(this.__placeholderClearDebouncer, animationFrame, () =>
|
|
302
|
+
this._resizeHandler(),
|
|
303
|
+
);
|
|
304
|
+
} else {
|
|
305
|
+
// Add element height to the queue
|
|
306
|
+
this.__elementHeightQueue.push(elementHeight);
|
|
307
|
+
this.__elementHeightQueue.shift();
|
|
308
|
+
|
|
309
|
+
// Calculate new placeholder height based on the average of the defined values in the
|
|
310
|
+
// element height queue
|
|
311
|
+
const filteredHeights = this.__elementHeightQueue.filter((h) => h !== undefined);
|
|
312
|
+
this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
301
316
|
|
|
302
317
|
if (this.__pendingScrollToIndex !== undefined && !this.__hasPlaceholders()) {
|
|
303
318
|
this.scrollToIndex(this.__pendingScrollToIndex);
|
|
@@ -548,8 +563,8 @@ export class IronListAdapter {
|
|
|
548
563
|
return;
|
|
549
564
|
}
|
|
550
565
|
|
|
551
|
-
this._adjustVirtualIndexOffset(this._scrollTop -
|
|
552
|
-
const delta = this.
|
|
566
|
+
this._adjustVirtualIndexOffset(this._scrollTop - this._scrollPosition);
|
|
567
|
+
const delta = this._scrollTop - this._scrollPosition;
|
|
553
568
|
|
|
554
569
|
super._scrollHandler();
|
|
555
570
|
|
|
@@ -580,6 +595,18 @@ export class IronListAdapter {
|
|
|
580
595
|
timeOut.after(this.timeouts.FIX_INVALID_ITEM_POSITIONING),
|
|
581
596
|
() => this.__fixInvalidItemPositioning(),
|
|
582
597
|
);
|
|
598
|
+
|
|
599
|
+
if (!this.__overscrollDebouncer?.isActive()) {
|
|
600
|
+
this.scrollTarget.style.overscrollBehavior = 'none';
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
this.__overscrollDebouncer = Debouncer.debounce(
|
|
604
|
+
this.__overscrollDebouncer,
|
|
605
|
+
timeOut.after(this.timeouts.PREVENT_OVERSCROLL),
|
|
606
|
+
() => {
|
|
607
|
+
this.scrollTarget.style.overscrollBehavior = null;
|
|
608
|
+
},
|
|
609
|
+
);
|
|
583
610
|
}
|
|
584
611
|
|
|
585
612
|
if (this.reorderElements) {
|
|
@@ -590,11 +617,9 @@ export class IronListAdapter {
|
|
|
590
617
|
);
|
|
591
618
|
}
|
|
592
619
|
|
|
593
|
-
this.__previousScrollTop = this._scrollTop;
|
|
594
|
-
|
|
595
620
|
// If the first visible index is not 0 when scrolled to the top,
|
|
596
621
|
// scroll to index 0 to fix the issue.
|
|
597
|
-
if (this.
|
|
622
|
+
if (this._scrollPosition === 0 && this.firstVisibleIndex !== 0 && Math.abs(delta) > 0) {
|
|
598
623
|
this.scrollToIndex(0);
|
|
599
624
|
}
|
|
600
625
|
}
|
|
@@ -654,96 +679,6 @@ export class IronListAdapter {
|
|
|
654
679
|
}
|
|
655
680
|
}
|
|
656
681
|
|
|
657
|
-
/** @private */
|
|
658
|
-
__onWheel(e) {
|
|
659
|
-
if (e.ctrlKey || this._hasScrolledAncestor(e.target, e.deltaX, e.deltaY)) {
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
let deltaY = e.deltaY;
|
|
664
|
-
if (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
|
665
|
-
// Scrolling by "lines of text" instead of pixels
|
|
666
|
-
deltaY *= this._scrollLineHeight;
|
|
667
|
-
} else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
|
|
668
|
-
// Scrolling by "pages" instead of pixels
|
|
669
|
-
deltaY *= this._scrollPageHeight;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
if (!this._deltaYAcc) {
|
|
673
|
-
this._deltaYAcc = 0;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
if (this._wheelAnimationFrame) {
|
|
677
|
-
// Accumulate wheel delta while a frame is being processed
|
|
678
|
-
this._deltaYAcc += deltaY;
|
|
679
|
-
e.preventDefault();
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
deltaY += this._deltaYAcc;
|
|
684
|
-
this._deltaYAcc = 0;
|
|
685
|
-
|
|
686
|
-
this._wheelAnimationFrame = true;
|
|
687
|
-
this.__debouncerWheelAnimationFrame = Debouncer.debounce(
|
|
688
|
-
this.__debouncerWheelAnimationFrame,
|
|
689
|
-
animationFrame,
|
|
690
|
-
() => {
|
|
691
|
-
this._wheelAnimationFrame = false;
|
|
692
|
-
},
|
|
693
|
-
);
|
|
694
|
-
|
|
695
|
-
const momentum = Math.abs(e.deltaX) + Math.abs(deltaY);
|
|
696
|
-
|
|
697
|
-
if (this._canScroll(this.scrollTarget, e.deltaX, deltaY)) {
|
|
698
|
-
e.preventDefault();
|
|
699
|
-
this.scrollTarget.scrollTop += deltaY;
|
|
700
|
-
this.scrollTarget.scrollLeft += e.deltaX;
|
|
701
|
-
|
|
702
|
-
this._hasResidualMomentum = true;
|
|
703
|
-
|
|
704
|
-
this._ignoreNewWheel = true;
|
|
705
|
-
this._debouncerIgnoreNewWheel = Debouncer.debounce(
|
|
706
|
-
this._debouncerIgnoreNewWheel,
|
|
707
|
-
timeOut.after(this.timeouts.IGNORE_WHEEL),
|
|
708
|
-
() => {
|
|
709
|
-
this._ignoreNewWheel = false;
|
|
710
|
-
},
|
|
711
|
-
);
|
|
712
|
-
} else if ((this._hasResidualMomentum && momentum <= this._previousMomentum) || this._ignoreNewWheel) {
|
|
713
|
-
e.preventDefault();
|
|
714
|
-
} else if (momentum > this._previousMomentum) {
|
|
715
|
-
this._hasResidualMomentum = false;
|
|
716
|
-
}
|
|
717
|
-
this._previousMomentum = momentum;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* Determines if the element has an ancestor that handles the scroll delta prior to this
|
|
722
|
-
*
|
|
723
|
-
* @private
|
|
724
|
-
*/
|
|
725
|
-
_hasScrolledAncestor(el, deltaX, deltaY) {
|
|
726
|
-
if (el === this.scrollTarget || el === this.scrollTarget.getRootNode().host) {
|
|
727
|
-
return false;
|
|
728
|
-
} else if (
|
|
729
|
-
this._canScroll(el, deltaX, deltaY) &&
|
|
730
|
-
['auto', 'scroll'].indexOf(getComputedStyle(el).overflow) !== -1
|
|
731
|
-
) {
|
|
732
|
-
return true;
|
|
733
|
-
} else if (el !== this && el.parentElement) {
|
|
734
|
-
return this._hasScrolledAncestor(el.parentElement, deltaX, deltaY);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
_canScroll(el, deltaX, deltaY) {
|
|
739
|
-
return (
|
|
740
|
-
(deltaY > 0 && el.scrollTop < el.scrollHeight - el.offsetHeight) ||
|
|
741
|
-
(deltaY < 0 && el.scrollTop > 0) ||
|
|
742
|
-
(deltaX > 0 && el.scrollLeft < el.scrollWidth - el.offsetWidth) ||
|
|
743
|
-
(deltaX < 0 && el.scrollLeft > 0)
|
|
744
|
-
);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
682
|
/**
|
|
748
683
|
* Increases the pool size.
|
|
749
684
|
* @override
|