@vaadin/component-base 24.3.9 → 24.3.11

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": "24.3.9",
3
+ "version": "24.3.11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -42,5 +42,5 @@
42
42
  "@vaadin/testing-helpers": "^0.6.0",
43
43
  "sinon": "^13.0.2"
44
44
  },
45
- "gitHead": "89f71cc95b22840de910070c145f9cbf9714f4f4"
45
+ "gitHead": "890abeb0937416074456782aa90ed92c1bfe9cac"
46
46
  }
package/src/define.js CHANGED
@@ -9,7 +9,7 @@ export function defineCustomElement(CustomElement) {
9
9
  if (!defined) {
10
10
  Object.defineProperty(CustomElement, 'version', {
11
11
  get() {
12
- return '24.3.9';
12
+ return '24.3.11';
13
13
  },
14
14
  });
15
15
 
@@ -82,6 +82,10 @@ export class IronListAdapter {
82
82
  return this.lastVisibleIndex + this._vidxOffset;
83
83
  }
84
84
 
85
+ get _maxVirtualIndexOffset() {
86
+ return this.size - this._virtualCount;
87
+ }
88
+
85
89
  __hasPlaceholders() {
86
90
  return this.__getVisibleElements().some((el) => el.__virtualizerPlaceholder);
87
91
  }
@@ -106,7 +110,7 @@ export class IronListAdapter {
106
110
  let targetVirtualIndex = Math.floor((index / this.size) * this._virtualCount);
107
111
  if (this._virtualCount - targetVirtualIndex < visibleElementCount) {
108
112
  targetVirtualIndex = this._virtualCount - (this.size - index);
109
- this._vidxOffset = this.size - this._virtualCount;
113
+ this._vidxOffset = this._maxVirtualIndexOffset;
110
114
  } else if (targetVirtualIndex < visibleElementCount) {
111
115
  if (index < OFFSET_ADJUST_MIN_THRESHOLD) {
112
116
  targetVirtualIndex = index;
@@ -297,24 +301,41 @@ export class IronListAdapter {
297
301
  this._debouncers._increasePoolIfNeeded.cancel();
298
302
  }
299
303
 
304
+ // Prevent element update while the scroll position is being restored
305
+ this.__preventElementUpdates = true;
306
+
307
+ // Record the scroll position before changing the size
308
+ let fvi; // First visible index
309
+ let fviOffsetBefore; // Scroll offset of the first visible index
310
+ if (size > 0) {
311
+ fvi = this.adjustedFirstVisibleIndex;
312
+ fviOffsetBefore = this.__getIndexScrollOffset(fvi);
313
+ }
314
+
300
315
  // Change the size
301
316
  this.__size = size;
302
317
 
303
- if (!this._physicalItems) {
304
- // Not initialized yet
305
- this._itemsChanged({
306
- path: 'items',
307
- });
308
- this.__preventElementUpdates = true;
309
- flush();
310
- this.__preventElementUpdates = false;
311
- } else {
312
- // Already initialized, just update _virtualCount
313
- this._updateScrollerSize();
314
- this._virtualCount = this.items.length;
315
- this._render();
318
+ this._itemsChanged({
319
+ path: 'items',
320
+ });
321
+ flush();
322
+
323
+ // Try to restore the scroll position if the new size is larger than 0
324
+ if (size > 0) {
325
+ fvi = Math.min(fvi, size - 1);
326
+ // Note, calling scrollToIndex also updates the virtual index offset,
327
+ // causing the virtualizer to add more items when size is increased,
328
+ // and remove exceeding items when size is decreased.
329
+ this.scrollToIndex(fvi);
330
+
331
+ const fviOffsetAfter = this.__getIndexScrollOffset(fvi);
332
+ if (fviOffsetBefore !== undefined && fviOffsetAfter !== undefined) {
333
+ this._scrollTop += fviOffsetBefore - fviOffsetAfter;
334
+ }
316
335
  }
317
336
 
337
+ this.__preventElementUpdates = false;
338
+
318
339
  // When reducing size while invisible, iron-list does not update items, so
319
340
  // their hidden state is not updated and their __lastUpdatedIndex is not
320
341
  // reset. In that case force an update here.
@@ -326,8 +347,7 @@ export class IronListAdapter {
326
347
  requestAnimationFrame(() => this._resizeHandler());
327
348
  }
328
349
 
329
- // Schedule and flush a resize handler. This will cause a
330
- // re-render for the elements.
350
+ // Schedule and flush a resize handler
331
351
  this._resizeHandler();
332
352
  flush();
333
353
  }
@@ -703,15 +723,16 @@ export class IronListAdapter {
703
723
 
704
724
  /** @private */
705
725
  _adjustVirtualIndexOffset(delta) {
726
+ const maxOffset = this._maxVirtualIndexOffset;
727
+
706
728
  if (this._virtualCount >= this.size) {
707
729
  this._vidxOffset = 0;
708
730
  } else if (this.__skipNextVirtualIndexAdjust) {
709
731
  this.__skipNextVirtualIndexAdjust = false;
710
732
  } else if (Math.abs(delta) > 10000) {
711
733
  // Process a large scroll position change
712
- const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.offsetHeight);
713
- const offset = scale * this.size;
714
- this._vidxOffset = Math.round(offset - scale * this._virtualCount);
734
+ const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.clientHeight);
735
+ this._vidxOffset = Math.round(scale * maxOffset);
715
736
  } else {
716
737
  // Make sure user can always swipe/wheel scroll to the start and end
717
738
  const oldOffset = this._vidxOffset;
@@ -730,7 +751,6 @@ export class IronListAdapter {
730
751
  }
731
752
 
732
753
  // Near end
733
- const maxOffset = this.size - this._virtualCount;
734
754
  if (this._scrollTop >= this._maxScrollTop && this._maxScrollTop > 0) {
735
755
  this._vidxOffset = maxOffset;
736
756
  if (oldOffset !== this._vidxOffset) {