ng-virtual-list 21.9.3 → 21.9.5

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/README.md CHANGED
@@ -751,6 +751,10 @@ Methods
751
751
  | scrollToEnd | (cb?: () => void, options?: [IScrollOptions](https://github.com/DjonnyX/ng-virtual-list/blob/21.x/projects/ng-virtual-list/src/lib/models/scroll-options.model.ts)) | Scrolls the scroll area to the last item in the collection. |
752
752
  | getItemBounds | (id: [Id](https://github.com/DjonnyX/ng-virtual-list/blob/21.x/projects/ng-virtual-list/src/lib/types/id.ts), behavior?: ScrollBehavior) => void | Returns the bounds of an element with a given id |
753
753
  | focus | [Id](https://github.com/DjonnyX/ng-virtual-list/blob/21.x/projects/ng-virtual-list/src/lib/types/id.ts), align: [FocusAlignment](https://github.com/DjonnyX/ng-virtual-list/blob/21.x/projects/ng-virtual-list/src/lib/types/focus-alignment.ts) = [FocusAlignments.NONE](https://github.com/DjonnyX/ng-virtual-list/blob/21.x/projects/ng-virtual-list/src/lib/enums/focus-alignments.ts) | Focus an list item by a given id. |
754
+ | cacheClean | | Force clearing the cache. |
755
+ | stopSnappingScrollToEnd | | Stops the list from snapping to the bottom edge. |
756
+ | updateImmediately | | Instantly refreshes the list. |
757
+ | markForUpdate | | Marks the list for an update that will trigger on the next tick. |
754
758
 
755
759
  <br/>
756
760
 
@@ -776,13 +780,13 @@ Properties
776
780
 
777
781
  | Angular version | ng-virtual-list version | git | npm |
778
782
  |--|--|--|--|
779
- | 20.x | 20.9.2 | [20.x](https://github.com/DjonnyX/ng-virtual-list/tree/20.x) | [20.9.2](https://www.npmjs.com/package/ng-virtual-list/v/20.9.2) |
780
- | 19.x | 19.9.4 | [19.x](https://github.com/DjonnyX/ng-virtual-list/tree/19.x) | [19.9.4](https://www.npmjs.com/package/ng-virtual-list/v/19.9.4) |
781
- | 18.x | 18.9.2 | [18.x](https://github.com/DjonnyX/ng-virtual-list/tree/18.x) | [18.9.2](https://www.npmjs.com/package/ng-virtual-list/v/18.9.2) |
782
- | 17.x | 17.9.2 | [17.x](https://github.com/DjonnyX/ng-virtual-list/tree/17.x) | [17.9.2](https://www.npmjs.com/package/ng-virtual-list/v/17.9.2) |
783
- | 16.x | 16.9.3 | [16.x](https://github.com/DjonnyX/ng-virtual-list/tree/16.x) | [16.9.3](https://www.npmjs.com/package/ng-virtual-list/v/16.9.3) |
784
- | 15.x | 15.9.3 | [15.x](https://github.com/DjonnyX/ng-virtual-list/tree/15.x) | [15.9.3](https://www.npmjs.com/package/ng-virtual-list/v/15.9.3) |
785
- | 14.x | 14.9.3 | [14.x](https://github.com/DjonnyX/ng-virtual-list/tree/14.x) | [14.9.3](https://www.npmjs.com/package/ng-virtual-list/v/14.9.3) |
783
+ | 20.x | 20.9.6 | [20.x](https://github.com/DjonnyX/ng-virtual-list/tree/20.x) | [20.9.6](https://www.npmjs.com/package/ng-virtual-list/v/20.9.6) |
784
+ | 19.x | 19.9.6 | [19.x](https://github.com/DjonnyX/ng-virtual-list/tree/19.x) | [19.9.6](https://www.npmjs.com/package/ng-virtual-list/v/19.9.6) |
785
+ | 18.x | 18.9.4 | [18.x](https://github.com/DjonnyX/ng-virtual-list/tree/18.x) | [18.9.4](https://www.npmjs.com/package/ng-virtual-list/v/18.9.4) |
786
+ | 17.x | 17.9.4 | [17.x](https://github.com/DjonnyX/ng-virtual-list/tree/17.x) | [17.9.4](https://www.npmjs.com/package/ng-virtual-list/v/17.9.4) |
787
+ | 16.x | 16.9.6 | [16.x](https://github.com/DjonnyX/ng-virtual-list/tree/16.x) | [16.9.6](https://www.npmjs.com/package/ng-virtual-list/v/16.9.6) |
788
+ | 15.x | 15.9.6 | [15.x](https://github.com/DjonnyX/ng-virtual-list/tree/15.x) | [15.9.6](https://www.npmjs.com/package/ng-virtual-list/v/15.9.6) |
789
+ | 14.x | 14.9.6 | [14.x](https://github.com/DjonnyX/ng-virtual-list/tree/14.x) | [14.9.6](https://www.npmjs.com/package/ng-virtual-list/v/14.9.6) |
786
790
 
787
791
  <br/>
788
792
 
@@ -345,8 +345,8 @@ class NgVirtualListService {
345
345
  this.select(data);
346
346
  }
347
347
  }
348
- update() {
349
- this._trackBox?.changes();
348
+ update(immediately = false) {
349
+ this._trackBox?.changes(immediately);
350
350
  }
351
351
  /**
352
352
  * Selects a list item
@@ -599,7 +599,6 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
599
599
  config = signal({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
600
600
  measures = signal(undefined, ...(ngDevMode ? [{ debugName: "measures" }] : []));
601
601
  focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : []));
602
- reseted = signal(false, ...(ngDevMode ? [{ debugName: "reseted" }] : []));
603
602
  part = signal(PART_DEFAULT_ITEM, ...(ngDevMode ? [{ debugName: "part" }] : []));
604
603
  maxClickDistance = signal(DEFAULT_CLICK_DISTANCE, ...(ngDevMode ? [{ debugName: "maxClickDistance" }] : []));
605
604
  data = signal(undefined, ...(ngDevMode ? [{ debugName: "data" }] : []));
@@ -683,7 +682,10 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
683
682
  })).subscribe();
684
683
  this.classes = computed(() => {
685
684
  const data = this.data(), focused = this.focused();
686
- return { [CLASS_NAME_SNAPPED]: data?.config?.snapped ?? false, [CLASS_NAME_SNAPPED_OUT]: data?.config?.snappedOut ?? false, [CLASS_NAME_FOCUS]: focused };
685
+ return {
686
+ [CLASS_NAME_SNAPPED]: data?.config?.snapped ?? false, [CLASS_NAME_SNAPPED_OUT]: data?.config?.snappedOut ?? false,
687
+ [CLASS_NAME_FOCUS]: focused,
688
+ };
687
689
  }, ...(ngDevMode ? [{ debugName: "classes" }] : []));
688
690
  this.index = computed(() => {
689
691
  return this.config()?.tabIndex ?? -1;
@@ -692,7 +694,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
692
694
  const data = this.data(), measures = this.measures(), config = this.config();
693
695
  return {
694
696
  data: data?.data, prevData: data?.previouseData, nextData: data?.nextData, measures,
695
- config, reseted: this.reseted(), index: data?.index ?? -1
697
+ config, reseted: false, index: data?.index ?? -1
696
698
  };
697
699
  }, ...(ngDevMode ? [{ debugName: "templateContext" }] : []));
698
700
  const $data = toObservable(this.data), $focused = toObservable(this.focused);
@@ -874,7 +876,6 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
874
876
  return { width: width > 0 ? width : 1, height: height > 0 ? height : 1, };
875
877
  }
876
878
  show() {
877
- this.reseted.set(false);
878
879
  const el = this._elementRef.nativeElement, styles = el.style;
879
880
  styles.zIndex = this._data?.config?.zIndex ?? DEFAULT_ZINDEX;
880
881
  if (this.regular) {
@@ -891,7 +892,6 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
891
892
  }
892
893
  }
893
894
  hide() {
894
- this.reseted.set(true);
895
895
  const el = this._elementRef.nativeElement, styles = el.style;
896
896
  styles.position = POSITION_ABSOLUTE;
897
897
  styles.transform = `${TRANSLATE_3D$1}(${this._data?.config?.isVertical ? 0 : ZEROS_POSITION},${this._data?.config?.isVertical ? 0 : ZEROS_POSITION},0)`;
@@ -1202,14 +1202,14 @@ class CacheMap extends EventEmitter {
1202
1202
  }
1203
1203
  stopLifeCircle() {
1204
1204
  if (this._lifeCircleId !== undefined) {
1205
- cancelAnimationFrame(this._lifeCircleId);
1205
+ clearTimeout(this._lifeCircleId);
1206
1206
  }
1207
1207
  }
1208
1208
  nextTick(cb) {
1209
1209
  if (this._disposed) {
1210
1210
  return;
1211
1211
  }
1212
- this._lifeCircleId = requestAnimationFrame(() => {
1212
+ this._lifeCircleId = setTimeout(() => {
1213
1213
  cb();
1214
1214
  });
1215
1215
  return this._lifeCircleId;
@@ -1902,7 +1902,7 @@ class TrackBox extends CacheMap {
1902
1902
  * Calculates list metrics
1903
1903
  */
1904
1904
  recalculateMetrics(options) {
1905
- const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, reversed, bufferSize: minBufferSize, scrollSize, snap, itemConfigMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options, roundedScrollSize = Math.round(scrollSize);
1905
+ const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, bufferSize: minBufferSize, scrollSize, snap, itemConfigMap, enabledBufferOptimization, previousTotalSize, crudDetected, deletedItemsMap } = options, roundedScrollSize = Math.round(scrollSize);
1906
1906
  const trackBy = this._trackingPropertyName, bufferSize = Math.max(minBufferSize, this._bufferSize), { width, height } = bounds, sizeProperty = isVertical ? HEIGHT_PROP_NAME : WIDTH_PROP_NAME, size = isVertical ? height : width, totalLength = collection.length, typicalItemSize = itemSize, w = isVertical ? width : typicalItemSize, h = isVertical ? typicalItemSize : height, map = this._map, snapshot = this._snapshot, checkOverscrollItemsLimit = Math.ceil(typicalItemSize !== 0 ? size / typicalItemSize : 0), snippedPos = Math.floor(scrollSize) + this._scrollStartOffset, leftItemsWeights = [], isFromId = fromItemId !== undefined && (typeof fromItemId === 'number' && fromItemId > -1)
1907
1907
  || (typeof fromItemId === 'string' && fromItemId > '-1');
1908
1908
  let leftItemsOffset = 0, rightItemsOffset = 0;
@@ -2173,7 +2173,6 @@ class TrackBox extends CacheMap {
2173
2173
  totalSize,
2174
2174
  typicalItemSize,
2175
2175
  isFromItemIdFound,
2176
- reversed: options.reversed,
2177
2176
  isUpdating,
2178
2177
  };
2179
2178
  return metrics;
@@ -2187,11 +2186,18 @@ class TrackBox extends CacheMap {
2187
2186
  this.clearScrollDirectionCache();
2188
2187
  }
2189
2188
  }
2190
- changes() {
2189
+ changes(immediately = false) {
2190
+ if (this.changesDetected()) {
2191
+ return;
2192
+ }
2191
2193
  this.bumpVersion();
2194
+ if (immediately) {
2195
+ this._previousVersion = this._version;
2196
+ this.dispatch(CACHE_BOX_CHANGE_EVENT_NAME, this.version);
2197
+ }
2192
2198
  }
2193
2199
  generateDisplayCollection(items, itemConfigMap, metrics) {
2194
- const { offsetY, offsetX, width, height, normalizedItemWidth, normalizedItemHeight, dynamicSize, itemsOnDisplayLength, itemsFromStartToScrollEnd, isVertical, renderItems: renderItemsLength, scrollSize, sizeProperty, snap, snippedPos, startPosition, totalLength, startIndex, typicalItemSize, reversed, } = metrics, displayItems = [];
2200
+ const { offsetY, offsetX, width, height, normalizedItemWidth, normalizedItemHeight, dynamicSize, itemsOnDisplayLength, itemsFromStartToScrollEnd, isVertical, renderItems: renderItemsLength, scrollSize, sizeProperty, snap, snippedPos, startPosition, totalLength, startIndex, typicalItemSize, } = metrics, displayItems = [];
2195
2201
  if (items.length) {
2196
2202
  const trackBy = this._trackingPropertyName, actualSnippedPosition = snippedPos, isSnappingMethodAdvanced = this.isSnappingMethodAdvanced, boundsSize = isVertical ? height : width, actualEndSnippedPosition = scrollSize + boundsSize - this._scrollEndOffset, positionOffset = isVertical ? offsetY : offsetX;
2197
2203
  let pos = startPosition, renderItems = renderItemsLength, stickyItem, nextSticky, stickyItemIndex = -1, stickyItemSize = 0, endStickyItem, nextEndSticky, endStickyItemIndex = -1, endStickyItemSize = 0, count = 1;
@@ -2307,7 +2313,7 @@ class TrackBox extends CacheMap {
2307
2313
  if (iterations > totalLength || i >= totalLength) {
2308
2314
  break;
2309
2315
  }
2310
- const collectionItem = items[reversed ? (items.length - i + 1) : i];
2316
+ const collectionItem = items[i];
2311
2317
  if (!collectionItem) {
2312
2318
  continue;
2313
2319
  }
@@ -3663,11 +3669,11 @@ class NgScrollerComponent {
3663
3669
  }
3664
3670
  }
3665
3671
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgScrollerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3666
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.0", type: NgScrollerComponent, isStandalone: true, selector: "ng-scroller", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, focusedElement: { classPropertyName: "focusedElement", publicName: "focusedElement", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, startOffset: { classPropertyName: "startOffset", publicName: "startOffset", isSignal: true, isRequired: false, transformFunction: null }, endOffset: { classPropertyName: "endOffset", publicName: "endOffset", isSignal: true, isRequired: false, transformFunction: null }, scrollbarTheme: { classPropertyName: "scrollbarTheme", publicName: "scrollbarTheme", isSignal: true, isRequired: false, transformFunction: null }, scrollbarMinSize: { classPropertyName: "scrollbarMinSize", publicName: "scrollbarMinSize", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "scrollContent", first: true, predicate: ["scrollContent"], descendants: true, isSignal: true }, { propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, isSignal: true }, { propertyName: "cdkScrollable", first: true, predicate: ["scrollViewport"], descendants: true, read: CdkScrollable }, { propertyName: "scrollBar", first: true, predicate: ["scrollBar"], descendants: true, read: NgScrollBarComponent }], ngImport: i0, template: "<div localeSensitive [langTextDir]=\"langTextDir()\" [listDir]=\"direction()\" class=\"ngvl__container\" [ngClass]=\"containerClasses()\">\r\n <div #scrollViewport cdkScrollable part=\"scroller\" class=\"ngvl__scroller\">\r\n <div #scrollContent [attr.aria-orientation]=\"direction()\" [attr.aria-activedescendant]=\"focusedElement()\"\r\n tabindex=\"0\" part=\"list\" class=\"ngvl__list\" [ngClass]=\"actualClasses()\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n <ng-scroll-bar #scrollBar [isVertical]=\"isVertical()\" [size]=\"thumbSize()\" [theme]=\"scrollbarTheme()\" [position]=\"thumbPosition()\"\r\n [thumbGradientPositions]=\"thumbGradientPositions()\" [loading]=\"loading()\" [prepared]=\"preparedSignal()\" [show]=\"thumbShow()\"\r\n (onDrag)=\"onScrollBarDragHandler($event)\"></ng-scroll-bar>\r\n</div>", styles: [":host{position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.ngvl__container{position:relative;overflow:hidden;display:grid;width:100%;height:100%;cursor:grab}.ngvl__container.grabbing{cursor:grabbing}.ngvl__container.horizontal{grid-template-rows:1fr auto}.ngvl__container.horizontal .ngvl__list{display:inline-flex}.ngvl__container.horizontal .ngvl__scroller{overflow:hidden}.ngvl__container.vertical{grid-template-columns:1fr auto}.ngvl__container.vertical .ngvl__scroller{overflow:hidden}.ngvl__scroller{display:block;position:relative;overflow:hidden;width:100%;height:100%}.ngvl__list{position:absolute;list-style:none;padding:0;margin:0;width:100%;height:100%;opacity:0}.ngvl__list.prepared{opacity:1;overflow:hidden}.ngvl__list.prepared.wait-for-preparation{transition:opacity .15s ease-out .1s}.ngvl__list.ready-to-start{transition:height .15s ease-out}.ngvl__list.ready-to-start.wait-for-preparation{transition:height .15s ease-out,opacity .15s ease-out .1s}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: LocaleSensitiveDirective, selector: "[localeSensitive]", inputs: ["langTextDir", "listDir"] }, { kind: "component", type: NgScrollBarComponent, selector: "ng-scroll-bar", inputs: ["loading", "isVertical", "position", "thumbGradientPositions", "size", "theme", "prepared", "show"], outputs: ["onDrag"] }] });
3672
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.0", type: NgScrollerComponent, isStandalone: true, selector: "ng-scroller", inputs: { direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, focusedElement: { classPropertyName: "focusedElement", publicName: "focusedElement", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, classes: { classPropertyName: "classes", publicName: "classes", isSignal: true, isRequired: false, transformFunction: null }, startOffset: { classPropertyName: "startOffset", publicName: "startOffset", isSignal: true, isRequired: false, transformFunction: null }, endOffset: { classPropertyName: "endOffset", publicName: "endOffset", isSignal: true, isRequired: false, transformFunction: null }, scrollbarTheme: { classPropertyName: "scrollbarTheme", publicName: "scrollbarTheme", isSignal: true, isRequired: false, transformFunction: null }, scrollbarMinSize: { classPropertyName: "scrollbarMinSize", publicName: "scrollbarMinSize", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "scrollContent", first: true, predicate: ["scrollContent"], descendants: true, isSignal: true }, { propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, isSignal: true }, { propertyName: "cdkScrollable", first: true, predicate: ["scrollViewport"], descendants: true, read: CdkScrollable }, { propertyName: "scrollBar", first: true, predicate: ["scrollBar"], descendants: true, read: NgScrollBarComponent }], ngImport: i0, template: "<div localeSensitive [langTextDir]=\"langTextDir()\" [listDir]=\"direction()\" class=\"ngvl__container\" [ngClass]=\"containerClasses()\">\r\n <div #scrollViewport cdkScrollable part=\"scroller\" class=\"ngvl__scroller\">\r\n <div #scrollContent [attr.aria-orientation]=\"direction()\" [attr.aria-activedescendant]=\"focusedElement()\"\r\n tabindex=\"0\" part=\"list\" class=\"ngvl__list\" [ngClass]=\"actualClasses()\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n <ng-scroll-bar #scrollBar [isVertical]=\"isVertical()\" [size]=\"thumbSize()\" [theme]=\"scrollbarTheme()\" [position]=\"thumbPosition()\"\r\n [thumbGradientPositions]=\"thumbGradientPositions()\" [loading]=\"loading()\" [prepared]=\"preparedSignal()\" [show]=\"thumbShow()\"\r\n (onDrag)=\"onScrollBarDragHandler($event)\"></ng-scroll-bar>\r\n</div>", styles: [":host{position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.ngvl__container{position:relative;overflow:hidden;display:grid;width:100%;height:100%;cursor:grab}.ngvl__container.grabbing{cursor:grabbing}.ngvl__container.horizontal{grid-template-rows:1fr auto}.ngvl__container.horizontal .ngvl__list{display:inline-flex}.ngvl__container.horizontal .ngvl__scroller{overflow:hidden}.ngvl__container.vertical{grid-template-columns:1fr auto}.ngvl__container.vertical .ngvl__scroller{overflow:hidden}.ngvl__scroller{display:block;position:relative;overflow:hidden;width:100%;height:100%}.ngvl__list{position:absolute;list-style:none;padding:0;margin:0;width:100%;height:100%}.ngvl__list.prepared{overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "directive", type: LocaleSensitiveDirective, selector: "[localeSensitive]", inputs: ["langTextDir", "listDir"] }, { kind: "component", type: NgScrollBarComponent, selector: "ng-scroll-bar", inputs: ["loading", "isVertical", "position", "thumbGradientPositions", "size", "theme", "prepared", "show"], outputs: ["onDrag"] }] });
3667
3673
  }
3668
3674
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgScrollerComponent, decorators: [{
3669
3675
  type: Component,
3670
- args: [{ selector: 'ng-scroller', imports: [CommonModule, CdkScrollable, LocaleSensitiveDirective, NgScrollBarComponent], template: "<div localeSensitive [langTextDir]=\"langTextDir()\" [listDir]=\"direction()\" class=\"ngvl__container\" [ngClass]=\"containerClasses()\">\r\n <div #scrollViewport cdkScrollable part=\"scroller\" class=\"ngvl__scroller\">\r\n <div #scrollContent [attr.aria-orientation]=\"direction()\" [attr.aria-activedescendant]=\"focusedElement()\"\r\n tabindex=\"0\" part=\"list\" class=\"ngvl__list\" [ngClass]=\"actualClasses()\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n <ng-scroll-bar #scrollBar [isVertical]=\"isVertical()\" [size]=\"thumbSize()\" [theme]=\"scrollbarTheme()\" [position]=\"thumbPosition()\"\r\n [thumbGradientPositions]=\"thumbGradientPositions()\" [loading]=\"loading()\" [prepared]=\"preparedSignal()\" [show]=\"thumbShow()\"\r\n (onDrag)=\"onScrollBarDragHandler($event)\"></ng-scroll-bar>\r\n</div>", styles: [":host{position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.ngvl__container{position:relative;overflow:hidden;display:grid;width:100%;height:100%;cursor:grab}.ngvl__container.grabbing{cursor:grabbing}.ngvl__container.horizontal{grid-template-rows:1fr auto}.ngvl__container.horizontal .ngvl__list{display:inline-flex}.ngvl__container.horizontal .ngvl__scroller{overflow:hidden}.ngvl__container.vertical{grid-template-columns:1fr auto}.ngvl__container.vertical .ngvl__scroller{overflow:hidden}.ngvl__scroller{display:block;position:relative;overflow:hidden;width:100%;height:100%}.ngvl__list{position:absolute;list-style:none;padding:0;margin:0;width:100%;height:100%;opacity:0}.ngvl__list.prepared{opacity:1;overflow:hidden}.ngvl__list.prepared.wait-for-preparation{transition:opacity .15s ease-out .1s}.ngvl__list.ready-to-start{transition:height .15s ease-out}.ngvl__list.ready-to-start.wait-for-preparation{transition:height .15s ease-out,opacity .15s ease-out .1s}\n"] }]
3676
+ args: [{ selector: 'ng-scroller', imports: [CommonModule, CdkScrollable, LocaleSensitiveDirective, NgScrollBarComponent], template: "<div localeSensitive [langTextDir]=\"langTextDir()\" [listDir]=\"direction()\" class=\"ngvl__container\" [ngClass]=\"containerClasses()\">\r\n <div #scrollViewport cdkScrollable part=\"scroller\" class=\"ngvl__scroller\">\r\n <div #scrollContent [attr.aria-orientation]=\"direction()\" [attr.aria-activedescendant]=\"focusedElement()\"\r\n tabindex=\"0\" part=\"list\" class=\"ngvl__list\" [ngClass]=\"actualClasses()\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n <ng-scroll-bar #scrollBar [isVertical]=\"isVertical()\" [size]=\"thumbSize()\" [theme]=\"scrollbarTheme()\" [position]=\"thumbPosition()\"\r\n [thumbGradientPositions]=\"thumbGradientPositions()\" [loading]=\"loading()\" [prepared]=\"preparedSignal()\" [show]=\"thumbShow()\"\r\n (onDrag)=\"onScrollBarDragHandler($event)\"></ng-scroll-bar>\r\n</div>", styles: [":host{position:relative;overflow:hidden;-webkit-user-select:none;user-select:none}.ngvl__container{position:relative;overflow:hidden;display:grid;width:100%;height:100%;cursor:grab}.ngvl__container.grabbing{cursor:grabbing}.ngvl__container.horizontal{grid-template-rows:1fr auto}.ngvl__container.horizontal .ngvl__list{display:inline-flex}.ngvl__container.horizontal .ngvl__scroller{overflow:hidden}.ngvl__container.vertical{grid-template-columns:1fr auto}.ngvl__container.vertical .ngvl__scroller{overflow:hidden}.ngvl__scroller{display:block;position:relative;overflow:hidden;width:100%;height:100%}.ngvl__list{position:absolute;list-style:none;padding:0;margin:0;width:100%;height:100%}.ngvl__list.prepared{overflow:hidden}\n"] }]
3671
3677
  }], ctorParameters: () => [], propDecorators: { scrollContent: [{ type: i0.ViewChild, args: ['scrollContent', { isSignal: true }] }], cdkScrollable: [{
3672
3678
  type: ViewChild,
3673
3679
  args: ['scrollViewport', { read: CdkScrollable }]
@@ -4514,38 +4520,42 @@ class NgVirtualListComponent {
4514
4520
  });
4515
4521
  let prepared = false, readyToStart = false, isUserScrolling = false;
4516
4522
  this.$prepared.pipe(takeUntilDestroyed(), distinctUntilChanged(), tap(v => {
4517
- const waitForPreparation = this.waitForPreparation();
4518
- if (waitForPreparation) {
4519
- if (!v) {
4520
- prepared = readyToStart = v;
4523
+ if (!v) {
4524
+ this.cacheClean();
4525
+ readyToStart = isUserScrolling = false;
4526
+ prepared = readyToStart = v;
4527
+ const waitForPreparation = this.waitForPreparation();
4528
+ if (waitForPreparation) {
4521
4529
  const scrollerComponent = this._scrollerComponent();
4522
4530
  if (scrollerComponent) {
4523
4531
  scrollerComponent.prepared = v;
4524
4532
  }
4525
4533
  this.classes.set({ prepared: v, [WAIT_FOR_PREPARATION]: waitForPreparation });
4526
- this.cacheClean();
4527
4534
  }
4528
- }
4529
- else {
4530
- prepared = readyToStart = true;
4531
- const scrollerComponent = this._scrollerComponent();
4532
- if (scrollerComponent) {
4533
- scrollerComponent.prepared = true;
4535
+ else {
4536
+ const scrollerComponent = this._scrollerComponent();
4537
+ if (scrollerComponent) {
4538
+ scrollerComponent.prepared = true;
4539
+ }
4540
+ this.classes.set({ prepared: true, [READY_TO_START]: true, [WAIT_FOR_PREPARATION]: waitForPreparation });
4541
+ this.updateImmediately();
4534
4542
  }
4535
- this.classes.set({ prepared: true, [READY_TO_START]: true, [WAIT_FOR_PREPARATION]: waitForPreparation });
4536
4543
  }
4537
- }), filter$1(v => !!v), debounceTime(0), takeUntilDestroyed(this._destroyRef), tap(v => {
4544
+ }), filter$1(v => !!v), delay(0), takeUntilDestroyed(this._destroyRef), tap(v => {
4538
4545
  prepared = v;
4546
+ this.updateImmediately();
4539
4547
  }), delay(0), takeUntilDestroyed(this._destroyRef), tap(v => {
4540
4548
  const waitForPreparation = this.waitForPreparation(), scrollerComponent = this._scrollerComponent(), val = v || !waitForPreparation;
4541
4549
  if (scrollerComponent) {
4542
4550
  scrollerComponent.prepared = val;
4543
4551
  }
4544
4552
  this.classes.set({ prepared: val, [WAIT_FOR_PREPARATION]: waitForPreparation });
4553
+ this.updateImmediately();
4545
4554
  }), delay(1000), takeUntilDestroyed(this._destroyRef), tap(v => {
4546
4555
  const waitForPreparation = this.waitForPreparation();
4547
4556
  readyToStart = v;
4548
4557
  this.classes.set({ prepared: true, [READY_TO_START]: true, [WAIT_FOR_PREPARATION]: waitForPreparation });
4558
+ this.updateImmediately();
4549
4559
  })).subscribe();
4550
4560
  this._service.$focusedId.pipe(takeUntilDestroyed(), tap(v => {
4551
4561
  this.focusedElement.set(v ?? undefined);
@@ -4693,14 +4703,12 @@ class NgVirtualListComponent {
4693
4703
  const { width, height, x, y } = bounds, viewportSize = (isVertical ? height : width);
4694
4704
  let scrollLength = Math.round(this._totalSize()) ?? 0, actualScrollLength = Math.round(scrollLength === 0 ? 0 : scrollLength > viewportSize ? scrollLength - viewportSize : scrollLength), roundedMaxPosition = Math.round(actualScrollLength), scrollPosition = Math.round(actualScrollSize);
4695
4705
  const opts = {
4696
- bounds: { width, height, x, y }, dynamicSize, isVertical, itemSize, reversed: false,
4706
+ bounds: { width, height, x, y }, dynamicSize, isVertical, itemSize,
4697
4707
  bufferSize, maxBufferSize, scrollSize: actualScrollSize, snap, enabledBufferOptimization,
4698
4708
  };
4699
- if (snapScrollToBottom && scrollLength > viewportSize && !prepared) {
4700
- const { totalSize: calculatedTotalSize } = this._trackBox.getMetrics(items, itemConfigMap, { ...opts, reversed: true });
4701
- totalSize = calculatedTotalSize;
4709
+ if (snapScrollToBottom && !prepared) {
4702
4710
  actualScrollSize = (totalSize > viewportSize ? totalSize - viewportSize : 0);
4703
- const { displayItems: calculatedDisplayItems, totalSize: calculatedTotalSize1 } = this._trackBox.updateCollection(items, itemConfigMap, { ...opts, reversed: true, scrollSize: actualScrollSize });
4711
+ const { displayItems: calculatedDisplayItems, totalSize: calculatedTotalSize1 } = this._trackBox.updateCollection(items, itemConfigMap, { ...opts, scrollSize: actualScrollSize });
4704
4712
  displayItems = calculatedDisplayItems;
4705
4713
  totalSize = calculatedTotalSize1;
4706
4714
  scrollLength = Math.round(totalSize) ?? 0;
@@ -4905,13 +4913,12 @@ class NgVirtualListComponent {
4905
4913
  if (dynamicSize) {
4906
4914
  const { width, height, x, y } = this._bounds() || { x: 0, y: 0, width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, itemConfigMap = this.itemConfigMap(), items = this._actualItems(), isVertical = this._isVertical, currentScollSize = (isVertical ? scrollerComponent.scrollTop : scrollerComponent.scrollLeft), delta = this._trackBox.delta, opts = {
4907
4915
  bounds: { width, height, x, y }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize,
4908
- bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(), reversed: false,
4916
+ bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(),
4909
4917
  scrollSize: (isVertical ? scrollerComponent.scrollTop : scrollerComponent.scrollLeft) + delta,
4910
4918
  snap: this.snap(), fromItemId: id, enabledBufferOptimization: this.enabledBufferOptimization(),
4911
4919
  }, scrollSize = this._trackBox.getItemPosition(id, itemConfigMap, opts), params = {
4912
4920
  [isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, behavior: BEHAVIOR_INSTANT,
4913
- fireUpdate: false,
4914
- blending: true,
4921
+ fireUpdate: false, blending: false,
4915
4922
  };
4916
4923
  if (scrollSize === -1) {
4917
4924
  return of([true, { id, scroller: scrollerComponent, scrollCalled, cb }]);
@@ -4954,7 +4961,7 @@ class NgVirtualListComponent {
4954
4961
  _$scrollToEndDuringUpdateCanceller.next(1);
4955
4962
  const params = {
4956
4963
  [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize,
4957
- behavior: BEHAVIOR_INSTANT, blending: true,
4964
+ behavior: BEHAVIOR_INSTANT, blending: false,
4958
4965
  };
4959
4966
  scrollerComponent?.scrollTo?.(params);
4960
4967
  return of([true, { id, scroller: scrollerComponent, cb }]).pipe(delay(1));
@@ -5194,6 +5201,9 @@ class NgVirtualListComponent {
5194
5201
  this._trackBox.changes();
5195
5202
  }
5196
5203
  }
5204
+ /**
5205
+ * Force clearing the cache.
5206
+ */
5197
5207
  cacheClean() {
5198
5208
  this._trackBox.cacheClean();
5199
5209
  this._collapsedItemIds.set([]);
@@ -5205,7 +5215,11 @@ class NgVirtualListComponent {
5205
5215
  if (scrollerComponent) {
5206
5216
  scrollerComponent.reset();
5207
5217
  }
5218
+ this._$prepared.next(false);
5208
5219
  }
5220
+ /**
5221
+ * Stops the list from snapping to the bottom edge.
5222
+ */
5209
5223
  stopSnappingScrollToEnd() {
5210
5224
  const scroller = this._scrollerComponent();
5211
5225
  this._isScrollFinished.set(false);
@@ -5214,6 +5228,18 @@ class NgVirtualListComponent {
5214
5228
  scroller.stopScrolling();
5215
5229
  }
5216
5230
  }
5231
+ /**
5232
+ * Instantly refreshes the list.
5233
+ */
5234
+ updateImmediately() {
5235
+ this._service.update(true);
5236
+ }
5237
+ /**
5238
+ * Marks the list for an update that will trigger on the next tick.
5239
+ */
5240
+ markForUpdate() {
5241
+ this._service.update();
5242
+ }
5217
5243
  ngOnDestroy() {
5218
5244
  this.dispose();
5219
5245
  }