ng-virtual-list 20.12.0-beta-09 → 20.12.1
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 +4 -14
- package/fesm2022/ng-virtual-list.mjs +113 -91
- package/fesm2022/ng-virtual-list.mjs.map +1 -1
- package/index.d.ts +20 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
⚡A powerful API for implementing lists of varying functionality and complexity.
|
|
6
6
|
|
|
7
|
-
✨Flexible, and actively maintained Angular library that excels with high-performance, feature-rich virtualized lists—including grouping, sticky headers, snapping, animations, collapsing group elements, single and multiple selection of elements and both scroll directions, lists with scrolling bindings for elements, galleries of varying complexity, including 3D transformations of elements and effects such as MotionBlur, DOF (Depth Of Field) and Fog. Whether you're rendering millions of items or building interactive list components, it delivers scalability and customization. Angular (14–
|
|
7
|
+
✨Flexible, and actively maintained Angular library that excels with high-performance, feature-rich virtualized lists—including grouping, sticky headers, snapping, animations, collapsing group elements, single and multiple selection of elements and both scroll directions, lists with scrolling bindings for elements, galleries of varying complexity, including 3D transformations of elements and effects such as MotionBlur, DOF (Depth Of Field) and Fog. Whether you're rendering millions of items or building interactive list components, it delivers scalability and customization. Angular (14–22) compatibility.
|
|
8
8
|
|
|
9
9
|
🧬The main advantage of this solution is the elimination of the "empty spaces" effect during fast scrolling, which occurs in the classic implementation of virtualized lists. Visualization is as close as possible to native lists.
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|

|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
[Documentation](https://ng-virtual-list
|
|
23
|
+
[Documentation](https://ng-virtual-list.eugene-grebennikov.pro/)
|
|
24
24
|
|
|
25
25
|
<br/>
|
|
26
26
|
|
|
@@ -612,11 +612,7 @@ Inputs
|
|
|
612
612
|
| itemSize | number \| 'viewport' = 24 | If direction = 'vertical', then the height of a typical element. If direction = 'horizontal', then the width of a typical element. If the dynamicSize property is true, the items in the list can have different sizes, and you must specify the itemSize property to adjust the sizes of the items in the unallocated area. If the value is 'viewport', the sizes of elements are automatically resized to fit the viewport size. |
|
|
613
613
|
| itemTransform | [ItemTransform](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/item-transform.ts) \| null = null | Custom transformation of element's position, rotation, scale, opacity and zIndex. The default value is `null`. |
|
|
614
614
|
| itemRenderer | TemplateRef | Rendering element template. |
|
|
615
|
-
| itemConfigMap | [IVirtualListItemConfigMap?](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/models/item-config-map.model.ts) | Sets `sticky` position, `fullSize`, `collapsable` and `selectable` for the list item element. If `sticky` position is greater than `0`, then `sticky` position is applied.
|
|
616
|
-
If the `sticky` value is greater than `0`, then the `sticky` position mode is enabled for the element. `1` - position start, `2` - position end. Default value is `0`.
|
|
617
|
-
`selectable` determines whether an element can be selected or not. Default value is `true`.
|
|
618
|
-
`collapsable` determines whether an element with a `sticky` property greater than zero can collapse and collapse elements in front that do not have a `sticky` property.
|
|
619
|
-
`fullSize` determines the size of an element when rendering lists with cell divisions. If sticky is 1 or 2, fullSize automatically becomes true. The default value is false. |
|
|
615
|
+
| itemConfigMap | [IVirtualListItemConfigMap?](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/models/item-config-map.model.ts) | Sets `sticky` position, `fullSize`, `collapsable` and `selectable` for the list item element. If `sticky` position is greater than `0`, then `sticky` position is applied. If the `sticky` value is greater than `0`, then the `sticky` position mode is enabled for the element. `1` - position start, `2` - position end. Default value is `0`. `selectable` determines whether an element can be selected or not. Default value is `true`. `collapsable` determines whether an element with a `sticky` property greater than zero can collapse and collapse elements in front that do not have a `sticky` property. `fullSize` determines the size of an element when rendering lists with cell divisions. If sticky is 1 or 2, fullSize automatically becomes true. The default value is false. |
|
|
620
616
|
| langTextDir | [TextDirection? = 'ltr'](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/enums/text-direction.ts) | A string indicating the direction of text for the locale. Can be either "ltr" (left-to-right) or "rtl" (right-to-left). |
|
|
621
617
|
| loading | boolean? = false | If `true`, the scrollBar goes into loading state. The default value is `false`. |
|
|
622
618
|
| maxBufferSize | number? = 10 | Maximum number of elements outside the scope of visibility. Default value is 10. If maxBufferSize is set to be greater than bufferSize, then adaptive buffer mode is enabled. The greater the scroll size, the more elements are allocated for rendering. |
|
|
@@ -705,7 +701,7 @@ Properties
|
|
|
705
701
|
|
|
706
702
|
<br/>
|
|
707
703
|
|
|
708
|
-
### [VirtualClickModule](https://github.com/DjonnyX/ng-virtual-list/blob/
|
|
704
|
+
### [VirtualClickModule](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/directives/item-click/item-click.module.ts)
|
|
709
705
|
|
|
710
706
|
### Virtual click directive
|
|
711
707
|
|
|
@@ -730,12 +726,6 @@ import { NgVirtualListModule, VirtualClickModule } from 'ng-virtual-list';
|
|
|
730
726
|
</ng-template>
|
|
731
727
|
```
|
|
732
728
|
|
|
733
|
-
## 🤝 Contributing
|
|
734
|
-
|
|
735
|
-
PRs and feature requests are welcome!
|
|
736
|
-
Open an issue or start a discussion to shape the future of [ng-virtual-list](https://github.com/DjonnyX/ng-virtual-list/).
|
|
737
|
-
Try it out, star ⭐ the repo, and let us know what you’re building.
|
|
738
|
-
|
|
739
729
|
<br/>
|
|
740
730
|
|
|
741
731
|
## 📄 License
|
|
@@ -1399,7 +1399,7 @@ const DEFAULT_MAX_DISTANCE = 40;
|
|
|
1399
1399
|
* VirtualClickDirective
|
|
1400
1400
|
* Maximum performance for extremely large lists.
|
|
1401
1401
|
* It is based on algorithms for virtualization of screen objects.
|
|
1402
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/
|
|
1402
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/directives/item-click/item-click.directive.ts
|
|
1403
1403
|
* @author Evgenii Alexandrovich Grebennikov
|
|
1404
1404
|
* @email djonnyx@gmail.com
|
|
1405
1405
|
*/
|
|
@@ -1626,14 +1626,14 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
1626
1626
|
this._service.virtualClick(this._data);
|
|
1627
1627
|
}
|
|
1628
1628
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1629
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NgVirtualListItemComponent, isStandalone: false, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1629
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NgVirtualListItemComponent, isStandalone: false, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1630
1630
|
}
|
|
1631
1631
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
|
|
1632
1632
|
type: Component,
|
|
1633
1633
|
args: [{ selector: 'ng-virtual-list-item', host: {
|
|
1634
1634
|
'class': 'ngvl__item',
|
|
1635
1635
|
'role': 'listitem',
|
|
1636
|
-
}, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"] }]
|
|
1636
|
+
}, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n"] }]
|
|
1637
1637
|
}], ctorParameters: () => [] });
|
|
1638
1638
|
|
|
1639
1639
|
/**
|
|
@@ -1762,7 +1762,7 @@ class ScrollEvent {
|
|
|
1762
1762
|
|
|
1763
1763
|
/**
|
|
1764
1764
|
* Event emitter
|
|
1765
|
-
* @link https://github.com/DjonnyX/
|
|
1765
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/main/library/src/utils/event-emitter/event-emitter.ts
|
|
1766
1766
|
* @author Evgenii Alexandrovich Grebennikov
|
|
1767
1767
|
* @email djonnyx@gmail.com
|
|
1768
1768
|
*/
|
|
@@ -2065,7 +2065,7 @@ class Tracker {
|
|
|
2065
2065
|
}
|
|
2066
2066
|
const untrackedItems = [...components], newTrackItems = [], untrackedComponentsByTypeMap = {}, isDown = direction === 0 || direction === 1, snapped = !!snappedComponents ? [...snappedComponents] : [];
|
|
2067
2067
|
let isRegularSnapped = false;
|
|
2068
|
-
const serviceIdProp = getServiceIdProp(trackBy);
|
|
2068
|
+
const serviceIdProp = getServiceIdProp(trackBy), snappedItems = new Array();
|
|
2069
2069
|
for (let i = isDown ? 0 : items.length - 1, l = isDown ? items.length : 0; isDown ? i < l : i >= l; isDown ? i++ : i--) {
|
|
2070
2070
|
const item = items[i], isDummy = item?.data?.[SERVICE_PROP_DUMMY] && (item?.data?.[SERVICE_PROP_DUMMY] === SERVICE_PROP_DUMMY_ENABLED);
|
|
2071
2071
|
if (isDummy) {
|
|
@@ -2088,6 +2088,7 @@ class Tracker {
|
|
|
2088
2088
|
isRegularSnapped = true;
|
|
2089
2089
|
snappedComponent.instance.item = item;
|
|
2090
2090
|
snappedComponent.instance.show();
|
|
2091
|
+
snappedItems.push(snappedComponent);
|
|
2091
2092
|
}
|
|
2092
2093
|
}
|
|
2093
2094
|
}
|
|
@@ -2153,6 +2154,7 @@ class Tracker {
|
|
|
2153
2154
|
if (!!snappedComponent) {
|
|
2154
2155
|
snappedComponent.instance.item = item;
|
|
2155
2156
|
snappedComponent.instance.show();
|
|
2157
|
+
snappedItems.push(snappedComponent);
|
|
2156
2158
|
}
|
|
2157
2159
|
}
|
|
2158
2160
|
}
|
|
@@ -2183,13 +2185,14 @@ class Tracker {
|
|
|
2183
2185
|
comp.instance.hide();
|
|
2184
2186
|
}
|
|
2185
2187
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2188
|
+
for (let i = 0, l = snapped.length; i < l; i++) {
|
|
2189
|
+
const snappedComponent = snapped[i];
|
|
2190
|
+
if (snappedItems.indexOf(snappedComponent) > -1) {
|
|
2191
|
+
continue;
|
|
2192
|
+
}
|
|
2193
|
+
if (!!snappedComponent) {
|
|
2194
|
+
snappedComponent.instance.item = null;
|
|
2195
|
+
snappedComponent.instance.hide();
|
|
2193
2196
|
}
|
|
2194
2197
|
}
|
|
2195
2198
|
}
|
|
@@ -2669,7 +2672,7 @@ class TrackBox extends CacheMap {
|
|
|
2669
2672
|
* Calculates list metrics
|
|
2670
2673
|
*/
|
|
2671
2674
|
recalculateMetrics(options) {
|
|
2672
|
-
const { fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, minItemSize, maxItemSize, bufferSize: minBufferSize, scrollSize, stickyEnabled, itemConfigMap, enabledBufferOptimization, previousTotalSize, snapToItem, snapToItemAlign, deletedItemsMap, itemTransform } = options, roundedScrollSize = Math.round(scrollSize);
|
|
2675
|
+
const { alignment, fromItemId, bounds, collection, dynamicSize, isVertical, itemSize, minItemSize, maxItemSize, bufferSize: minBufferSize, scrollSize, stickyEnabled, itemConfigMap, enabledBufferOptimization, previousTotalSize, snapToItem, snapToItemAlign, deletedItemsMap, itemTransform } = options, roundedScrollSize = Math.round(scrollSize);
|
|
2673
2676
|
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, divides = this._divides, stickyPos = Math.floor(scrollSize) + this._scrollStartOffset, leftItemsOrRowsWeights = [], isFromId = fromItemId !== undefined && (typeof fromItemId === 'number' && fromItemId > -1)
|
|
2674
2677
|
|| (typeof fromItemId === 'string' && fromItemId > '-1');
|
|
2675
2678
|
let leftItemsOffset = 0, rightItemsOffset = 0;
|
|
@@ -2809,15 +2812,17 @@ class TrackBox extends CacheMap {
|
|
|
2809
2812
|
}
|
|
2810
2813
|
if (id == fromItemId) {
|
|
2811
2814
|
isFromItemIdFound = true;
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2815
|
+
if (alignment !== Alignments.CENTER) {
|
|
2816
|
+
const { num, offset } = this.getElementNumToEnd(i, collection, map, typicalItemSize, size, isVertical), leftViewportSize = size - offset;
|
|
2817
|
+
if (leftViewportSize > 0) {
|
|
2818
|
+
const { num: num1, offset: offset1 } = this.getElementNumToEnd(i + num, collection, map, typicalItemSize, size, isVertical, 0, true), deltaNum = (num1 - num), deltaOffset = (offset1 - offset);
|
|
2819
|
+
totalItemsToDisplayEndWeight += offset;
|
|
2820
|
+
itemsFromStartToScrollEnd -= deltaNum;
|
|
2821
|
+
rightItemsWeight = rightItemLength = 0;
|
|
2822
|
+
leftHiddenItemsWeight -= deltaOffset;
|
|
2823
|
+
leftItemsOrRowsWeights.splice(leftItemsOrRowsWeights.length - deltaNum, deltaNum);
|
|
2824
|
+
y -= deltaOffset;
|
|
2825
|
+
}
|
|
2821
2826
|
}
|
|
2822
2827
|
itemById = collectionItem;
|
|
2823
2828
|
itemByIdPos = y;
|
|
@@ -3004,7 +3009,7 @@ class TrackBox extends CacheMap {
|
|
|
3004
3009
|
rightItemsWeight = Math.floor(rightItemLength * dividedTypicalItemSize / typicalItemSize) * typicalItemSize;
|
|
3005
3010
|
leftHiddenItemsWeight = Math.floor(itemsFromStartToScrollEnd * dividedTypicalItemSize / typicalItemSize) * typicalItemSize;
|
|
3006
3011
|
totalItemsToDisplayEndWeight = Math.floor(itemsFromStartToDisplayEnd * dividedTypicalItemSize / typicalItemSize) * typicalItemSize;
|
|
3007
|
-
totalSize = (totalLength * dividedTypicalItemSize) + this._scrollStartOffset + this._scrollEndOffset;
|
|
3012
|
+
totalSize = (Math.ceil(totalLength / divides) * divides * dividedTypicalItemSize) + this._scrollStartOffset + this._scrollEndOffset;
|
|
3008
3013
|
const k = totalSize !== 0 ? previousTotalSize / totalSize : 0;
|
|
3009
3014
|
if (isFromId) {
|
|
3010
3015
|
const index = collection.findIndex(item => item[trackBy] == fromItemId);
|
|
@@ -3380,7 +3385,7 @@ class TrackBox extends CacheMap {
|
|
|
3380
3385
|
}
|
|
3381
3386
|
if (!isDummy) {
|
|
3382
3387
|
if ((isSnappingMethodAdvanced || id !== stickyItem?.id) && id !== endStickyItem?.id) {
|
|
3383
|
-
const isOdd = (items.length - layoutIndexOffset + i) % 2 != 0, sticky = itemConfigMap[id]?.sticky ?? 0, fullSize = itemConfigMap[id]?.fullSize ?? false, selectable = itemConfigMap[id]?.selectable ?? true, collapsable = itemConfigMap[id]?.collapsable ?? false, snapped = stickyEnabled && (sticky === 1 && (pos <= scrollSize + this._scrollStartOffset) || sticky === 2 && (pos >= scrollSize + boundsSize - size)), absoluteStartPosition = pos - scrollSize, ratio = size !== 0 ? boundsSize / size : 0, absoluteStartPositionPercent = -(boundsSize !== 0 ? absoluteStartPosition / boundsSize : 0) * ratio, absoluteEndPosition = boundsSize - (absoluteStartPositionPercent + size), absoluteEndPositionPercent = (absoluteStartPositionPercent + (boundsSize !== 0 ? (absoluteEndPosition + size) / boundsSize : 0) * ratio), x = isVertical ? divSize * ((sticky || fullSize) ? 0 : ci) : pos, y = isVertical ? pos : divSize * ((sticky || fullSize) ? 0 : ci), measures = {
|
|
3388
|
+
const isOdd = (items.length - layoutIndexOffset + i) % 2 != 0, sticky = itemConfigMap[id]?.sticky ?? 0, fullSize = itemConfigMap[id]?.fullSize ?? false, selectable = itemConfigMap[id]?.selectable ?? true, collapsable = itemConfigMap[id]?.collapsable ?? false, snapped = stickyEnabled && ((sticky === 1 && (pos <= scrollSize + this._scrollStartOffset)) || (sticky === 2 && (pos >= scrollSize + boundsSize - size))), absoluteStartPosition = pos - scrollSize, ratio = size !== 0 ? boundsSize / size : 0, absoluteStartPositionPercent = -(boundsSize !== 0 ? absoluteStartPosition / boundsSize : 0) * ratio, absoluteEndPosition = boundsSize - (absoluteStartPositionPercent + size), absoluteEndPositionPercent = (absoluteStartPositionPercent + (boundsSize !== 0 ? (absoluteEndPosition + size) / boundsSize : 0) * ratio), x = isVertical ? divSize * ((sticky || fullSize) ? 0 : ci) : pos, y = isVertical ? pos : divSize * ((sticky || fullSize) ? 0 : ci), measures = {
|
|
3384
3389
|
x,
|
|
3385
3390
|
y,
|
|
3386
3391
|
transformedX: x,
|
|
@@ -3408,7 +3413,7 @@ class TrackBox extends CacheMap {
|
|
|
3408
3413
|
maxWidth: maxItemSize,
|
|
3409
3414
|
maxHeight: maxItemSize,
|
|
3410
3415
|
scrollDirection,
|
|
3411
|
-
delta: sticky === 1 ? actualSnippedPosition : sticky === 2 ? actualEndSnippedPosition - deltaOffet - size : 0,
|
|
3416
|
+
delta: sticky === 1 ? actualSnippedPosition : (sticky === 2 ? (actualEndSnippedPosition - deltaOffet - size) : 0),
|
|
3412
3417
|
}, config = {
|
|
3413
3418
|
isFirst: i === layoutIndexOffset,
|
|
3414
3419
|
isLast: i === li,
|
|
@@ -3418,7 +3423,7 @@ class TrackBox extends CacheMap {
|
|
|
3418
3423
|
isVertical,
|
|
3419
3424
|
collapsable,
|
|
3420
3425
|
selectable,
|
|
3421
|
-
sticky
|
|
3426
|
+
sticky,
|
|
3422
3427
|
snap: stickyEnabled,
|
|
3423
3428
|
snapped: false,
|
|
3424
3429
|
snappedOut: false,
|
|
@@ -3471,9 +3476,9 @@ class TrackBox extends CacheMap {
|
|
|
3471
3476
|
i++;
|
|
3472
3477
|
}
|
|
3473
3478
|
const axis = isVertical ? Y_PROP_NAME : X_PROP_NAME;
|
|
3474
|
-
if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition +
|
|
3475
|
-
if (nextSticky.measures[axis] >
|
|
3476
|
-
stickyItem.measures[axis] = nextSticky.measures[axis] -
|
|
3479
|
+
if (!!nextSticky && !!stickyItem && nextSticky.measures[axis] <= actualSnippedPosition + stickyItem.measures[sizeProperty]) {
|
|
3480
|
+
if (nextSticky.measures[axis] > actualSnippedPosition) {
|
|
3481
|
+
stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
|
|
3477
3482
|
stickyItem.config.snapped = nextSticky.config.snapped = false;
|
|
3478
3483
|
stickyItem.config.snappedOut = true;
|
|
3479
3484
|
stickyItem.config.sticky = 1;
|
|
@@ -3482,7 +3487,8 @@ class TrackBox extends CacheMap {
|
|
|
3482
3487
|
else {
|
|
3483
3488
|
nextSticky.config.snapped = true;
|
|
3484
3489
|
nextSticky.measures.delta = (isVertical ? nextSticky.measures.y : nextSticky.measures.x) - scrollSize;
|
|
3485
|
-
stickyItem.measures[axis] =
|
|
3490
|
+
stickyItem.measures[axis] = nextSticky.measures[axis] - stickyItem.measures[sizeProperty];
|
|
3491
|
+
stickyItem.measures.delta = (isVertical ? stickyItem.measures.y : stickyItem.measures.x) - scrollSize;
|
|
3486
3492
|
}
|
|
3487
3493
|
}
|
|
3488
3494
|
if (!!nextEndSticky && !!endStickyItem &&
|
|
@@ -3499,6 +3505,7 @@ class TrackBox extends CacheMap {
|
|
|
3499
3505
|
nextEndSticky.measures[axis] = actualEndSnippedPosition - nextEndSticky.measures[sizeProperty];
|
|
3500
3506
|
nextEndSticky.measures.delta = (isVertical ? nextEndSticky.measures.y : nextEndSticky.measures.x) - scrollSize;
|
|
3501
3507
|
endStickyItem.measures[axis] = nextEndSticky.measures[axis] + nextEndSticky.measures[sizeProperty];
|
|
3508
|
+
endStickyItem.measures.delta = (isVertical ? endStickyItem.measures.y : endStickyItem.measures.x) - scrollSize;
|
|
3502
3509
|
}
|
|
3503
3510
|
}
|
|
3504
3511
|
if (itemTransform !== null) {
|
|
@@ -3556,10 +3563,10 @@ class TrackBox extends CacheMap {
|
|
|
3556
3563
|
if (!!components) {
|
|
3557
3564
|
for (const comp of components) {
|
|
3558
3565
|
const id = comp.instance.itemId ?? null, isVertical = comp.instance.item?.config?.isVertical, x = comp.instance.item?.measures?.x ?? 0, y = comp.instance.item?.measures?.y ?? 0, isFirst = comp.instance.item?.config?.isFirst ?? false, isLast = comp.instance.item?.config?.isLast ?? false, { width, height } = comp.instance.getBounds(), pos = position;
|
|
3559
|
-
if (isVertical &&
|
|
3566
|
+
if (isVertical && (pos >= y && pos < y + height)) {
|
|
3560
3567
|
return { id, x, y, width, height, isFirst, isLast };
|
|
3561
3568
|
}
|
|
3562
|
-
else if (!isVertical &&
|
|
3569
|
+
else if (!isVertical && (pos >= x && pos < x + width)) {
|
|
3563
3570
|
return { id, x, y, width, height, isFirst, isLast };
|
|
3564
3571
|
}
|
|
3565
3572
|
if (isFirst) {
|
|
@@ -3954,7 +3961,7 @@ const easeLinear = (t) => {
|
|
|
3954
3961
|
|
|
3955
3962
|
/**
|
|
3956
3963
|
* Animator
|
|
3957
|
-
* @link https://github.com/DjonnyX/
|
|
3964
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/main/library/src/utils/animator/animator.ts
|
|
3958
3965
|
* @author Evgenii Alexandrovich Grebennikov
|
|
3959
3966
|
* @email djonnyx@gmail.com
|
|
3960
3967
|
*/
|
|
@@ -4826,7 +4833,7 @@ class NgScrollView extends BaseScrollView {
|
|
|
4826
4833
|
}
|
|
4827
4834
|
animate(startValue, endValue, duration = ANIMATION_DURATION, easingFunction = easeOutQuad, userAction = false, alignmentAtComplete = true, skipOverridedCoordinates = false) {
|
|
4828
4835
|
const isVertical = this.isVertical();
|
|
4829
|
-
let
|
|
4836
|
+
let position = startValue;
|
|
4830
4837
|
this._isAlignmentAnimation = !alignmentAtComplete;
|
|
4831
4838
|
this._animator.animate({
|
|
4832
4839
|
withDelta: this._service.dynamic && !this.isInfinity(),
|
|
@@ -4843,17 +4850,16 @@ class NgScrollView extends BaseScrollView {
|
|
|
4843
4850
|
this.animate(currentCoordinate, currentCoordinate + delta, duration - elapsed, easingFunction, userAction, alignmentAtComplete);
|
|
4844
4851
|
return;
|
|
4845
4852
|
}
|
|
4846
|
-
const v0 = calculateVelocity(position, value, timestamp) ?? this.averageVelocity;
|
|
4853
|
+
const v0 = calculateVelocity(position, value - this._delta, timestamp) ?? this.averageVelocity;
|
|
4847
4854
|
position = value;
|
|
4848
4855
|
if (alignmentAtComplete && !this._isAlignmentAnimation && !skipOverridedCoordinates) {
|
|
4849
|
-
if (
|
|
4856
|
+
if (!this.snapIfNecessary(v0)) {
|
|
4850
4857
|
this.move(isVertical, value, false, userAction);
|
|
4851
4858
|
}
|
|
4852
4859
|
}
|
|
4853
4860
|
else {
|
|
4854
4861
|
this.move(isVertical, value, false, userAction);
|
|
4855
4862
|
}
|
|
4856
|
-
iteration++;
|
|
4857
4863
|
this._service.update(true);
|
|
4858
4864
|
}, onComplete: ({ value, timestamp }) => {
|
|
4859
4865
|
this._isAlignmentAnimation = false;
|
|
@@ -4905,10 +4911,9 @@ class NgScrollView extends BaseScrollView {
|
|
|
4905
4911
|
return size;
|
|
4906
4912
|
}
|
|
4907
4913
|
alignPosition(animated = true, force = false) {
|
|
4908
|
-
if (!this.snapToItem() || this._isAlignmentAnimation) {
|
|
4914
|
+
if (!this.snapToItem() || (this._isAlignmentAnimation && !force)) {
|
|
4909
4915
|
return false;
|
|
4910
4916
|
}
|
|
4911
|
-
this.stopScrolling(true);
|
|
4912
4917
|
const scrollDirection = this._scrollDirection.get() || (force ? 1 : 0);
|
|
4913
4918
|
if (scrollDirection === 0) {
|
|
4914
4919
|
return false;
|
|
@@ -5323,7 +5328,7 @@ const RIGHT = 'right', DIR = 'dir';
|
|
|
5323
5328
|
* LocaleSensitiveDirective
|
|
5324
5329
|
* Maximum performance for extremely large lists.
|
|
5325
5330
|
* It is based on algorithms for virtualization of screen objects.
|
|
5326
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/
|
|
5331
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/directives/locale-sensitive/locale-sensitive.directive.ts
|
|
5327
5332
|
* @author Evgenii Alexandrovich Grebennikov
|
|
5328
5333
|
* @email djonnyx@gmail.com
|
|
5329
5334
|
*/
|
|
@@ -5919,10 +5924,10 @@ class PrerenderTrackBox extends EventEmitter {
|
|
|
5919
5924
|
}
|
|
5920
5925
|
|
|
5921
5926
|
/**
|
|
5922
|
-
*
|
|
5927
|
+
* NgPrerenderVirtualListItemComponent
|
|
5923
5928
|
* Maximum performance for extremely large lists.
|
|
5924
5929
|
* It is based on algorithms for virtualization of screen objects.
|
|
5925
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/ng-prerender-container/components/ng-prerender-list-item.component.ts
|
|
5930
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/ng-prerender-container/components/ng-prerender-list-item/ng-prerender-list-item.component.ts
|
|
5926
5931
|
* @author Evgenii Alexandrovich Grebennikov
|
|
5927
5932
|
* @email djonnyx@gmail.com
|
|
5928
5933
|
*/
|
|
@@ -5997,21 +6002,21 @@ class NgPrerenderVirtualListItemComponent extends NgVirtualListItemComponent {
|
|
|
5997
6002
|
}
|
|
5998
6003
|
}
|
|
5999
6004
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NgPrerenderVirtualListItemComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
6000
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NgPrerenderVirtualListItemComponent, isStandalone: false, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6005
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.19", type: NgPrerenderVirtualListItemComponent, isStandalone: false, selector: "ng-prerender-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: VirtualClickDirective, selector: "[virtualClick]", inputs: ["maxClickDistance"], outputs: ["onVirtualClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6001
6006
|
}
|
|
6002
6007
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NgPrerenderVirtualListItemComponent, decorators: [{
|
|
6003
6008
|
type: Component,
|
|
6004
6009
|
args: [{ selector: 'ng-prerender-virtual-list-item', host: {
|
|
6005
6010
|
'class': 'ngvl__item',
|
|
6006
6011
|
'role': 'listitem',
|
|
6007
|
-
}, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"] }]
|
|
6012
|
+
}, standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let renderer = itemRenderer();\r\n@let class = classes();\r\n<div #item class=\"ngvl-item\" [ngClass]=\"class\" [part]=\"part()\" [attr.ngvl-index]=\"index()\" [attr.ngvl-visibility]=\"visibility\" tabindex=\"-1\">\r\n @if (_blendColor) {\r\n <div class=\"ngvl-item__blend-color\" [style.--blend-color]=\"_blendColor\"></div>\r\n }\r\n <div #container virtualClick [part]=\"fxPart()\" [maxClickDistance]=\"maxClickDistance()\" class=\"ngvl-item__container\"\r\n [ngClass]=\"class\" (onVirtualClick)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\" [ngTemplateOutletContext]=\"templateContext()\" />\r\n }\r\n </div>\r\n</div>", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;text-rendering:optimizeSpeed;image-rendering:auto}.ngvl-item{position:relative;margin:0;padding:0;overflow:hidden;outline:none;width:inherit;height:inherit;box-sizing:border-box}.ngvl-item__blend-color{position:absolute;left:0;top:0;width:100%;height:100%;background-color:var(--blend-color);z-index:-1}.ngvl-item__container{margin:0;padding:0;width:100%;height:100%;box-sizing:border-box}\n", ":host{display:block;position:absolute!important;left:0;top:0;box-sizing:border-box;overflow:hidden;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-moz-user-drag:none;pointer-events:none;-webkit-user-select:none;user-select:none;text-rendering:optimizeSpeed;image-rendering:pixelated}\n"] }]
|
|
6008
6013
|
}] });
|
|
6009
6014
|
|
|
6010
6015
|
/**
|
|
6011
|
-
*
|
|
6016
|
+
* NgPrerenderScrollerComponent
|
|
6012
6017
|
* Maximum performance for extremely large lists.
|
|
6013
6018
|
* It is based on algorithms for virtualization of screen objects.
|
|
6014
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/prerender-container/prerender-scroller/prerender-scroller.component.ts
|
|
6019
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/ng-prerender-container/components/ng-prerender-scroller/ng-prerender-scroller.component.ts
|
|
6015
6020
|
* @author Evgenii Alexandrovich Grebennikov
|
|
6016
6021
|
* @email djonnyx@gmail.com
|
|
6017
6022
|
*/
|
|
@@ -6115,10 +6120,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
6115
6120
|
}], scrollbarEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarEnabled", required: false }] }], classes: [{ type: i0.Input, args: [{ isSignal: true, alias: "classes", required: false }] }] } });
|
|
6116
6121
|
|
|
6117
6122
|
/**
|
|
6118
|
-
*
|
|
6123
|
+
* NgPrerenderList
|
|
6119
6124
|
* Maximum performance for extremely large lists.
|
|
6120
6125
|
* It is based on algorithms for virtualization of screen objects.
|
|
6121
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/prerender-container/components/prerender-list/prerender-list.component.ts
|
|
6126
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/ng-prerender-container/components/ng-prerender-list/ng-prerender-list.component.ts
|
|
6122
6127
|
* @author Evgenii Alexandrovich Grebennikov
|
|
6123
6128
|
* @email djonnyx@gmail.com
|
|
6124
6129
|
*/
|
|
@@ -6261,10 +6266,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
|
|
|
6261
6266
|
}], enabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "enabled", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], isVertical: [{ type: i0.Input, args: [{ isSignal: true, alias: "isVertical", required: false }] }], scrollbarEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollbarEnabled", required: false }] }], startOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "startOffset", required: false }] }], endOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "endOffset", required: false }] }], bounds: [{ type: i0.Input, args: [{ isSignal: true, alias: "bounds", required: true }] }], dynamic: [{ type: i0.Input, args: [{ isSignal: true, alias: "dynamic", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], divides: [{ type: i0.Input, args: [{ isSignal: true, alias: "divides", required: false }] }], itemRenderer: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemRenderer", required: false }] }], itemComponentClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemComponentClass", required: false }] }] } });
|
|
6262
6267
|
|
|
6263
6268
|
/**
|
|
6264
|
-
*
|
|
6269
|
+
* NgPrerenderContainer
|
|
6265
6270
|
* Maximum performance for extremely large lists.
|
|
6266
6271
|
* It is based on algorithms for virtualization of screen objects.
|
|
6267
|
-
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/ng-prerender-container/ng-prerender-container.component.ts
|
|
6272
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/components/ng-prerender-container/ng-prerender-container.component.ts
|
|
6268
6273
|
* @author Evgenii Alexandrovich Grebennikov
|
|
6269
6274
|
* @email djonnyx@gmail.com
|
|
6270
6275
|
*/
|
|
@@ -7519,7 +7524,10 @@ class NgVirtualListComponent {
|
|
|
7519
7524
|
this._$initialized.next(true);
|
|
7520
7525
|
})).subscribe();
|
|
7521
7526
|
this._service.initialize(this._id, this._trackBox);
|
|
7522
|
-
|
|
7527
|
+
const $animationParams = toObservable(this.animationParams);
|
|
7528
|
+
$animationParams.pipe(takeUntilDestroyed(), tap(v => {
|
|
7529
|
+
this._service.animationParams = v;
|
|
7530
|
+
})).subscribe();
|
|
7523
7531
|
this._isInfinity = computed(() => {
|
|
7524
7532
|
const mode = this.spreadingMode();
|
|
7525
7533
|
return isSpreadingMode(mode, SpreadingModes.INFINITY);
|
|
@@ -8089,7 +8097,7 @@ class NgVirtualListComponent {
|
|
|
8089
8097
|
this._isLoading = false;
|
|
8090
8098
|
})).subscribe();
|
|
8091
8099
|
const update = (params) => {
|
|
8092
|
-
const { alignment,
|
|
8100
|
+
const { alignment, snapScrollToStart, snapScrollToEnd, bounds, items, itemConfigMap, scrollSize, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize, stickyEnabled, isVertical, dynamicSize, enabledBufferOptimization, snapToItem, snapToItemAlign, userAction, collapsedIds, itemTransform, } = params;
|
|
8093
8101
|
const scroller = this._scrollerComponent();
|
|
8094
8102
|
let totalSize = 0;
|
|
8095
8103
|
if (!!scroller) {
|
|
@@ -8099,7 +8107,7 @@ class NgVirtualListComponent {
|
|
|
8099
8107
|
let actualScrollSize = !this._readyForShow && snapScrollToEnd ? (isVertical ? scroller.scrollHeight : scroller.scrollWidth) :
|
|
8100
8108
|
(isVertical ? scroller.scrollTop : scroller.scrollLeft), leftLayoutOffset = 0, displayItems;
|
|
8101
8109
|
const { width, height } = bounds, viewportSize = (isVertical ? height : width), opts = {
|
|
8102
|
-
bounds: { width, height }, dynamicSize, isVertical, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize,
|
|
8110
|
+
alignment, bounds: { width, height }, dynamicSize, isVertical, itemSize, minItemSize, maxItemSize, bufferSize, maxBufferSize,
|
|
8103
8111
|
scrollSize: actualScrollSize, stickyEnabled, enabledBufferOptimization, snapToItem, snapToItemAlign, itemTransform,
|
|
8104
8112
|
};
|
|
8105
8113
|
if (snapScrollToEnd && !this._readyForShow) {
|
|
@@ -8107,12 +8115,24 @@ class NgVirtualListComponent {
|
|
|
8107
8115
|
displayItems = calculatedDisplayItems;
|
|
8108
8116
|
totalSize = calculatedTotalSize1;
|
|
8109
8117
|
leftLayoutOffset = leftLayoutOffset1;
|
|
8118
|
+
if (!!itemTransform && dynamicSize && this._trackBox.delta !== 0) {
|
|
8119
|
+
const { displayItems: calculatedDisplayItems, totalSize: calculatedTotalSize1, leftLayoutOffset: leftLayoutOffset1 } = this._trackBox.updateCollection(items, itemConfigMap, { ...opts, scrollSize: actualScrollSize + this._trackBox.delta });
|
|
8120
|
+
displayItems = calculatedDisplayItems;
|
|
8121
|
+
totalSize = calculatedTotalSize1;
|
|
8122
|
+
leftLayoutOffset = leftLayoutOffset1;
|
|
8123
|
+
}
|
|
8110
8124
|
}
|
|
8111
8125
|
else {
|
|
8112
8126
|
const { displayItems: calculatedDisplayItems, totalSize: calculatedTotalSize, leftLayoutOffset: leftLayoutOffset1 } = this._trackBox.updateCollection(items, itemConfigMap, opts);
|
|
8113
8127
|
displayItems = calculatedDisplayItems;
|
|
8114
8128
|
totalSize = calculatedTotalSize;
|
|
8115
8129
|
leftLayoutOffset = leftLayoutOffset1;
|
|
8130
|
+
if (!!itemTransform && dynamicSize && this._trackBox.delta !== 0) {
|
|
8131
|
+
const { displayItems: calculatedDisplayItems, totalSize: calculatedTotalSize, leftLayoutOffset: leftLayoutOffset1 } = this._trackBox.updateCollection(items, itemConfigMap, { ...opts, scrollSize: actualScrollSize + this._trackBox.delta });
|
|
8132
|
+
displayItems = calculatedDisplayItems;
|
|
8133
|
+
totalSize = calculatedTotalSize;
|
|
8134
|
+
leftLayoutOffset = leftLayoutOffset1;
|
|
8135
|
+
}
|
|
8116
8136
|
}
|
|
8117
8137
|
scroller.totalSize = totalSize;
|
|
8118
8138
|
scroller.startLayoutOffset = leftLayoutOffset;
|
|
@@ -8129,23 +8149,7 @@ class NgVirtualListComponent {
|
|
|
8129
8149
|
if (this._isSnappingMethodAdvanced) {
|
|
8130
8150
|
this.updateRegularRenderer();
|
|
8131
8151
|
}
|
|
8132
|
-
|
|
8133
|
-
case Alignments.NONE: {
|
|
8134
|
-
this._actualScrollStartOffset.set(precalculatedScrollStartOffset);
|
|
8135
|
-
this._actualScrollEndOffset.set(precalculatedScrollEndOffset);
|
|
8136
|
-
break;
|
|
8137
|
-
}
|
|
8138
|
-
case Alignments.CENTER: {
|
|
8139
|
-
const firstItemId = items.length > 0 ? (items[0]?.[trackBy] ?? null) : null, endItemId = items.length > 0 ? (items?.[items.length - 1]?.[trackBy] ?? null) : null, alignmentStartOffset = viewportSize * .5 - (firstItemId !== null ? (isVertical ? (this._service.getItemBounds(firstItemId)?.height ?? 0) :
|
|
8140
|
-
(this._service.getItemBounds(firstItemId)?.width ?? 0)) : 0) * (isInfinity ? 0 : .5), alignmentEndOffset = viewportSize * .5 - (endItemId !== null ? (isVertical ? (this._service.getItemBounds(endItemId)?.height ?? 0) :
|
|
8141
|
-
(this._service.getItemBounds(endItemId)?.width ?? 0)) : 0) * (isInfinity ? 0 : .5);
|
|
8142
|
-
this._alignmentScrollStartOffset.set(alignmentStartOffset);
|
|
8143
|
-
this._alignmentScrollEndOffset.set(alignmentEndOffset);
|
|
8144
|
-
this._actualScrollStartOffset.set(precalculatedScrollStartOffset + alignmentStartOffset);
|
|
8145
|
-
this._actualScrollEndOffset.set(precalculatedScrollEndOffset + alignmentEndOffset);
|
|
8146
|
-
break;
|
|
8147
|
-
}
|
|
8148
|
-
}
|
|
8152
|
+
this.updateOffsetsByAllignment();
|
|
8149
8153
|
scroller.delta = delta;
|
|
8150
8154
|
if ((snapScrollToStart && this._trackBox.isSnappedToStart && scroller.scrollable) ||
|
|
8151
8155
|
(snapScrollToStart && currentScrollSize <= MIN_PIXELS_FOR_PREVENT_SNAPPING)) {
|
|
@@ -8324,6 +8328,7 @@ class NgVirtualListComponent {
|
|
|
8324
8328
|
const dynamicSize = this.dynamicSize(), itemSize = this._actualItemSize(), minItemSize = this._actualMinItemSize(), maxItemSize = this._actualMaxItemSize(), snapScrollToEnd = this.snapScrollToEnd();
|
|
8325
8329
|
if (dynamicSize) {
|
|
8326
8330
|
const { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, itemConfigMap = this.itemConfigMap(), isVertical = this._isVertical, currentScrollSize = isVertical ? scrollerComponent.scrollTop : scrollerComponent.scrollLeft, opts = {
|
|
8331
|
+
alignment: this.actualAlignment(),
|
|
8327
8332
|
bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize, minItemSize, maxItemSize,
|
|
8328
8333
|
bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(), itemTransform: this.itemTransform(),
|
|
8329
8334
|
scrollSize: (isVertical ? scrollerComponent.scrollTop : scrollerComponent.scrollLeft),
|
|
@@ -8349,21 +8354,8 @@ class NgVirtualListComponent {
|
|
|
8349
8354
|
this.createDisplayComponentsIfNeed(displayItems);
|
|
8350
8355
|
this.tracking();
|
|
8351
8356
|
this.snappingHandler();
|
|
8357
|
+
this.updateOffsetsByAllignment();
|
|
8352
8358
|
scrollSize = this._trackBox.getItemPosition(id, itemConfigMap, { ...opts, scrollSize: actualScrollSize, fromItemId: id });
|
|
8353
|
-
if (this._isInfinity()) {
|
|
8354
|
-
if (this.snapToItem()) {
|
|
8355
|
-
const itemBounds = this._trackBox.getItemBounds(id);
|
|
8356
|
-
if (!!itemBounds) {
|
|
8357
|
-
const itemSize = isVertical ? itemBounds.height : itemBounds.width;
|
|
8358
|
-
switch (this.snapToItemAlign()) {
|
|
8359
|
-
case SnapToItemAligns.CENTER: {
|
|
8360
|
-
scrollSize += itemSize * .5;
|
|
8361
|
-
break;
|
|
8362
|
-
}
|
|
8363
|
-
}
|
|
8364
|
-
}
|
|
8365
|
-
}
|
|
8366
|
-
}
|
|
8367
8359
|
if (scrollSize === -1) {
|
|
8368
8360
|
return of([finished, { id, blending, iteration: nextIteration, cb }]).pipe(delay(0));
|
|
8369
8361
|
}
|
|
@@ -8388,11 +8380,11 @@ class NgVirtualListComponent {
|
|
|
8388
8380
|
else {
|
|
8389
8381
|
const index = items.findIndex(item => item[trackBy] === id);
|
|
8390
8382
|
if (index > -1) {
|
|
8391
|
-
const isVertical = this._isVertical, itemSize = this._actualItemSize();
|
|
8383
|
+
const isVertical = this._isVertical, itemSize = this._actualItemSize(), isInfinity = this._isInfinity(), snapToItem = this.snapToItem(), snapToItemAlign = this.snapToItemAlign();
|
|
8392
8384
|
let scrollSize = index * itemSize;
|
|
8393
|
-
if (
|
|
8394
|
-
if (
|
|
8395
|
-
switch (
|
|
8385
|
+
if (isInfinity) {
|
|
8386
|
+
if (snapToItem) {
|
|
8387
|
+
switch (snapToItemAlign) {
|
|
8396
8388
|
case SnapToItemAligns.CENTER: {
|
|
8397
8389
|
scrollSize += itemSize * .5;
|
|
8398
8390
|
break;
|
|
@@ -8401,11 +8393,12 @@ class NgVirtualListComponent {
|
|
|
8401
8393
|
}
|
|
8402
8394
|
}
|
|
8403
8395
|
const { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, itemConfigMap = this.itemConfigMap(), items = this._actualItems(), opts = {
|
|
8396
|
+
alignment: this._actualAlignment(),
|
|
8404
8397
|
bounds: { width, height }, collection: items, dynamicSize, isVertical: this._isVertical, itemSize, minItemSize, maxItemSize,
|
|
8405
8398
|
bufferSize: this.bufferSize(), maxBufferSize: this.maxBufferSize(), itemTransform: this.itemTransform(),
|
|
8406
8399
|
scrollSize: (isVertical ? scrollerComponent.scrollTop : scrollerComponent.scrollLeft),
|
|
8407
|
-
snapToItem: this.
|
|
8408
|
-
|
|
8400
|
+
snapToItem, snapToItemAlign, stickyEnabled: this.stickyEnabled(), fromItemId: id,
|
|
8401
|
+
enabledBufferOptimization: this.enabledBufferOptimization(),
|
|
8409
8402
|
};
|
|
8410
8403
|
this._trackBox.clearDelta();
|
|
8411
8404
|
const viewportSize = (isVertical ? height : width), { displayItems, totalSize, leftLayoutOffset } = this._trackBox.updateCollection(items, itemConfigMap, {
|
|
@@ -8420,6 +8413,7 @@ class NgVirtualListComponent {
|
|
|
8420
8413
|
this.createDisplayComponentsIfNeed(displayItems);
|
|
8421
8414
|
this.tracking();
|
|
8422
8415
|
this.snappingHandler();
|
|
8416
|
+
this.updateOffsetsByAllignment();
|
|
8423
8417
|
this._$preventScrollSnapping.next(true);
|
|
8424
8418
|
const params = {
|
|
8425
8419
|
[this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: scrollSize, fireUpdate: false,
|
|
@@ -8446,7 +8440,7 @@ class NgVirtualListComponent {
|
|
|
8446
8440
|
this.emitScrollEvent(true, false, true);
|
|
8447
8441
|
const scrollParams = params;
|
|
8448
8442
|
scrollParams?.cb?.();
|
|
8449
|
-
}), delay(
|
|
8443
|
+
}), delay(0), tap(([finished]) => {
|
|
8450
8444
|
if (finished) {
|
|
8451
8445
|
this._scrollerComponent()?.snapIfNeed();
|
|
8452
8446
|
}
|
|
@@ -8487,6 +8481,14 @@ class NgVirtualListComponent {
|
|
|
8487
8481
|
}
|
|
8488
8482
|
}));
|
|
8489
8483
|
})).subscribe();
|
|
8484
|
+
combineLatest([$itemConfigMap, $dynamicSize, $divides]).pipe(takeUntilDestroyed(), filter$1(([itemConfigMap, dynamicSize, divides]) => !!itemConfigMap && !dynamicSize && divides > 1), tap(([itemConfigMap]) => {
|
|
8485
|
+
for (const id in itemConfigMap) {
|
|
8486
|
+
const metaData = itemConfigMap[id];
|
|
8487
|
+
if (metaData?.fullSize || metaData?.sticky === 1 || metaData?.sticky === 2) {
|
|
8488
|
+
throw Error('The accelerated rendering algorithm `[dynamicSize]="false"` cannot correctly handle non-uniform lists (the itemConfigMap specifies full-size elements). For correct rendering, specify `[dynamicSize]="true"`.');
|
|
8489
|
+
}
|
|
8490
|
+
}
|
|
8491
|
+
})).subscribe();
|
|
8490
8492
|
combineLatest([$collapsingMode, $items, $itemConfigMap, $trackBy]).pipe(takeUntilDestroyed(), tap(([collapsingMode, items, itemConfigMap, trackBy]) => {
|
|
8491
8493
|
const isAccordion = isCollapseMode(collapsingMode, CollapsingModes.ACCORDION);
|
|
8492
8494
|
if (isAccordion) {
|
|
@@ -8690,6 +8692,26 @@ class NgVirtualListComponent {
|
|
|
8690
8692
|
this._trackBox.setDisplayObjectIndexMapById(doMap);
|
|
8691
8693
|
}
|
|
8692
8694
|
}
|
|
8695
|
+
updateOffsetsByAllignment() {
|
|
8696
|
+
const alignment = this._actualAlignment(), items = this._actualItems(), trackBy = this.trackBy(), isInfinity = this._isInfinity(), isVertical = this._isVertical, { width, height } = this._bounds() || { width: DEFAULT_LIST_SIZE, height: DEFAULT_LIST_SIZE }, viewportSize = isVertical ? height : width, precalculatedScrollStartOffset = this._precalculatedScrollStartOffset(), precalculatedScrollEndOffset = this._precalculatedScrollEndOffset();
|
|
8697
|
+
switch (alignment) {
|
|
8698
|
+
case Alignments.NONE: {
|
|
8699
|
+
this._actualScrollStartOffset.set(precalculatedScrollStartOffset);
|
|
8700
|
+
this._actualScrollEndOffset.set(precalculatedScrollEndOffset);
|
|
8701
|
+
break;
|
|
8702
|
+
}
|
|
8703
|
+
case Alignments.CENTER: {
|
|
8704
|
+
const firstItemId = items.length > 0 ? (items[0]?.[trackBy] ?? null) : null, endItemId = items.length > 0 ? (items?.[items.length - 1]?.[trackBy] ?? null) : null, alignmentStartOffset = viewportSize * .5 - (firstItemId !== null ? (isVertical ? (this._service.getItemBounds(firstItemId)?.height ?? 0) :
|
|
8705
|
+
(this._service.getItemBounds(firstItemId)?.width ?? 0)) : 0) * (isInfinity ? 0 : .5), alignmentEndOffset = viewportSize * .5 - (endItemId !== null ? (isVertical ? (this._service.getItemBounds(endItemId)?.height ?? 0) :
|
|
8706
|
+
(this._service.getItemBounds(endItemId)?.width ?? 0)) : 0) * (isInfinity ? 0 : .5);
|
|
8707
|
+
this._alignmentScrollStartOffset.set(alignmentStartOffset);
|
|
8708
|
+
this._alignmentScrollEndOffset.set(alignmentEndOffset);
|
|
8709
|
+
this._actualScrollStartOffset.set(precalculatedScrollStartOffset + alignmentStartOffset);
|
|
8710
|
+
this._actualScrollEndOffset.set(precalculatedScrollEndOffset + alignmentEndOffset);
|
|
8711
|
+
break;
|
|
8712
|
+
}
|
|
8713
|
+
}
|
|
8714
|
+
}
|
|
8693
8715
|
updateRegularRenderer() {
|
|
8694
8716
|
this._resizeSnappedComponentHandler();
|
|
8695
8717
|
}
|