@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/component-base",
3
- "version": "25.0.0-alpha17",
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-alpha17",
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-alpha17",
42
- "@vaadin/test-runner-commands": "25.0.0-alpha17",
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": "8264c71309907be99368b09414f0f8d7f591e0b9"
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-alpha17') {
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({ createElements, updateElement, scrollTarget, scrollContainer, elementsContainer, reorderElements }) {
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
- IGNORE_WHEEL: 500,
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
- updatedElements.forEach((el) => {
275
- const elementHeight = el.offsetHeight;
276
- if (elementHeight === 0) {
277
- // If the elements have 0 height after update (for example due to lazy rendering),
278
- // it results in iron-list requesting to create an unlimited count of elements.
279
- // Assign a temporary placeholder sizing to elements that would otherwise end up having
280
- // no height.
281
- el.style.paddingTop = `${this.__placeholderHeight}px`;
282
- el.style.opacity = '0';
283
- el.__virtualizerPlaceholder = true;
284
-
285
- // Manually schedule the resize handler to make sure the placeholder padding is
286
- // cleared in case the resize observer never triggers.
287
- this.__placeholderClearDebouncer = Debouncer.debounce(this.__placeholderClearDebouncer, animationFrame, () =>
288
- this._resizeHandler(),
289
- );
290
- } else {
291
- // Add element height to the queue
292
- this.__elementHeightQueue.push(elementHeight);
293
- this.__elementHeightQueue.shift();
294
-
295
- // Calculate new placeholder height based on the average of the defined values in the
296
- // element height queue
297
- const filteredHeights = this.__elementHeightQueue.filter((h) => h !== undefined);
298
- this.__placeholderHeight = Math.round(filteredHeights.reduce((a, b) => a + b, 0) / filteredHeights.length);
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 - (this.__previousScrollTop || 0));
552
- const delta = this.scrollTarget.scrollTop - this._scrollPosition;
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._scrollTop === 0 && this.firstVisibleIndex !== 0 && Math.abs(delta) > 0) {
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