ng-virtual-list 20.7.13 → 20.7.14
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 +26 -7
- package/fesm2022/ng-virtual-list.mjs +102 -27
- package/fesm2022/ng-virtual-list.mjs.map +1 -1
- package/index.d.ts +188 -142
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -589,7 +589,7 @@ Selecting even elements:
|
|
|
589
589
|
|
|
590
590
|
## 📚 API
|
|
591
591
|
|
|
592
|
-
[NgVirtualListComponent](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts)
|
|
592
|
+
### [NgVirtualListComponent](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/ng-virtual-list.component.ts)
|
|
593
593
|
|
|
594
594
|
Inputs
|
|
595
595
|
|
|
@@ -640,6 +640,25 @@ Methods
|
|
|
640
640
|
| scrollTo | (id: [Id](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/id.ts), behavior: ScrollBehavior = 'auto') => number | The method scrolls the list to the element with the given id and returns the value of the scrolled area. Behavior accepts the values "auto", "instant" and "smooth". |
|
|
641
641
|
| scrollToEnd | (behavior?: ScrollBehavior) => void | Scrolls the scroll area to the desired element with the specified ID. |
|
|
642
642
|
| getItemBounds | (id: [Id](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/id.ts), behavior?: ScrollBehavior) => void | Returns the bounds of an element with a given id |
|
|
643
|
+
| focus | [Id](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/id.ts), align: [FocusAlignment](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/focus-alignment.ts) = [FocusAlignments.NONE](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/enums/focus-alignments.ts) | Focus an list item by a given id. |
|
|
644
|
+
|
|
645
|
+
<br/>
|
|
646
|
+
|
|
647
|
+
### Template API
|
|
648
|
+
|
|
649
|
+
```html
|
|
650
|
+
<ng-template #itemRenderer let-data="data" let-config="config" let-measures="measures">
|
|
651
|
+
<!-- content -->
|
|
652
|
+
</ng-template>
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Properties
|
|
656
|
+
|
|
657
|
+
| Property | Type | Description |
|
|
658
|
+
|--|--|--|
|
|
659
|
+
| data | {\[id: [Id](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/types/id.ts) \], [otherProps: string]: any;} | Collection item data. |
|
|
660
|
+
| config | [IDisplayObjectConfig](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/models/display-object-config.model.ts) | Display object configuration. A set of `select`, `collapse`, and `focus` methods are also provided. |
|
|
661
|
+
| measures | [IDisplayObjectMeasures](https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/models/display-object-measures.model.ts) \| undefined | Display object metrics. |
|
|
643
662
|
|
|
644
663
|
<br/>
|
|
645
664
|
|
|
@@ -647,12 +666,12 @@ Methods
|
|
|
647
666
|
|
|
648
667
|
| Angular version | ng-virtual-list version | git | npm |
|
|
649
668
|
|--|--|--|--|
|
|
650
|
-
| 19.x | 19.7.
|
|
651
|
-
| 18.x | 18.7.
|
|
652
|
-
| 17.x | 17.7.
|
|
653
|
-
| 16.x | 16.7.
|
|
654
|
-
| 15.x | 15.7.
|
|
655
|
-
| 14.x | 14.7.
|
|
669
|
+
| 19.x | 19.7.23 | [19.x](https://github.com/DjonnyX/ng-virtual-list/tree/19.x) | [19.7.23](https://www.npmjs.com/package/ng-virtual-list/v/19.7.23) |
|
|
670
|
+
| 18.x | 18.7.14 | [18.x](https://github.com/DjonnyX/ng-virtual-list/tree/18.x) | [18.7.14](https://www.npmjs.com/package/ng-virtual-list/v/18.7.14) |
|
|
671
|
+
| 17.x | 17.7.15 | [17.x](https://github.com/DjonnyX/ng-virtual-list/tree/17.x) | [17.7.15](https://www.npmjs.com/package/ng-virtual-list/v/17.7.15) |
|
|
672
|
+
| 16.x | 16.7.13 | [16.x](https://github.com/DjonnyX/ng-virtual-list/tree/16.x) | [16.7.13](https://www.npmjs.com/package/ng-virtual-list/v/16.7.13) |
|
|
673
|
+
| 15.x | 15.7.13 | [15.x](https://github.com/DjonnyX/ng-virtual-list/tree/15.x) | [15.7.13](https://www.npmjs.com/package/ng-virtual-list/v/15.7.13) |
|
|
674
|
+
| 14.x | 14.7.14 | [14.x](https://github.com/DjonnyX/ng-virtual-list/tree/14.x) | [14.7.14](https://www.npmjs.com/package/ng-virtual-list/v/14.7.14) |
|
|
656
675
|
|
|
657
676
|
<br/>
|
|
658
677
|
|
|
@@ -2,9 +2,9 @@ import * as i1 from '@angular/common';
|
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { Injectable, inject, signal, ElementRef, ChangeDetectionStrategy, Component, viewChild, output, input, ViewContainerRef, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
5
|
-
import { Subject, tap, fromEvent, combineLatest, map, filter, distinctUntilChanged, switchMap, of } from 'rxjs';
|
|
6
|
-
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
|
7
5
|
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
|
|
6
|
+
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
|
|
7
|
+
import { Subject, tap, fromEvent, combineLatest, map, filter, distinctUntilChanged, switchMap, of } from 'rxjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Action modes for collection elements.
|
|
@@ -82,6 +82,20 @@ var SnappingMethods;
|
|
|
82
82
|
SnappingMethods["ADVANCED"] = "advanced";
|
|
83
83
|
})(SnappingMethods || (SnappingMethods = {}));
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Focus Alignments.
|
|
87
|
+
* @link https://github.com/DjonnyX/ng-virtual-list/blob/20.x/projects/ng-virtual-list/src/lib/enums/focus-alignments.ts
|
|
88
|
+
* @author Evgenii Grebennikov
|
|
89
|
+
* @email djonnyx@gmail.com
|
|
90
|
+
*/
|
|
91
|
+
var FocusAlignments;
|
|
92
|
+
(function (FocusAlignments) {
|
|
93
|
+
FocusAlignments["NONE"] = "none";
|
|
94
|
+
FocusAlignments["START"] = "start";
|
|
95
|
+
FocusAlignments["CENTER"] = "center";
|
|
96
|
+
FocusAlignments["END"] = "end";
|
|
97
|
+
})(FocusAlignments || (FocusAlignments = {}));
|
|
98
|
+
|
|
85
99
|
const DEFAULT_ITEM_SIZE = 24;
|
|
86
100
|
const DEFAULT_BUFFER_SIZE = 2;
|
|
87
101
|
const DEFAULT_MAX_BUFFER_SIZE = 10;
|
|
@@ -327,11 +341,11 @@ class NgVirtualListService {
|
|
|
327
341
|
}
|
|
328
342
|
}
|
|
329
343
|
itemToFocus;
|
|
330
|
-
focus(element) {
|
|
344
|
+
focus(element, align = FocusAlignments.CENTER) {
|
|
331
345
|
element.focus({ preventScroll: true });
|
|
332
346
|
if (element.parentElement) {
|
|
333
347
|
const pos = parseFloat(element.parentElement?.getAttribute('position') ?? '0');
|
|
334
|
-
this.itemToFocus?.(element, pos);
|
|
348
|
+
this.itemToFocus?.(element, pos, align);
|
|
335
349
|
}
|
|
336
350
|
}
|
|
337
351
|
areaFocus(id) {
|
|
@@ -410,7 +424,7 @@ const validateFunction = (value, undefinable = false, nullable = false) => {
|
|
|
410
424
|
return (undefinable && isUndefinable(value)) || (nullable && isNullable(value)) || typeof value === 'function';
|
|
411
425
|
};
|
|
412
426
|
|
|
413
|
-
const ATTR_AREA_SELECTED = 'area-selected', TABINDEX = 'ng-vl-index', KEY_SPACE = " ", KEY_ARR_LEFT = "ArrowLeft", KEY_ARR_UP = "ArrowUp", KEY_ARR_RIGHT = "ArrowRight", KEY_ARR_DOWN = "ArrowDown", EVENT_FOCUS_IN = 'focusin', EVENT_FOCUS_OUT = 'focusout', EVENT_KEY_DOWN = 'keydown';
|
|
427
|
+
const ATTR_AREA_SELECTED = 'area-selected', TABINDEX = 'ng-vl-index', POSITION = 'position', POSITION_ZERO = '0', ID = 'item-id', KEY_SPACE = " ", KEY_ARR_LEFT = "ArrowLeft", KEY_ARR_UP = "ArrowUp", KEY_ARR_RIGHT = "ArrowRight", KEY_ARR_DOWN = "ArrowDown", EVENT_FOCUS_IN = 'focusin', EVENT_FOCUS_OUT = 'focusout', EVENT_KEY_DOWN = 'keydown';
|
|
414
428
|
const getElementByIndex = (index) => {
|
|
415
429
|
return `[${TABINDEX}="${index}"]`;
|
|
416
430
|
};
|
|
@@ -430,7 +444,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
430
444
|
_isCollapsed = false;
|
|
431
445
|
config = signal({});
|
|
432
446
|
measures = signal(undefined);
|
|
433
|
-
|
|
447
|
+
focused = signal(false);
|
|
434
448
|
part = signal(PART_DEFAULT_ITEM);
|
|
435
449
|
regular = false;
|
|
436
450
|
data = signal(undefined);
|
|
@@ -494,21 +508,28 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
494
508
|
}
|
|
495
509
|
this._service.collapse(data, collapsed);
|
|
496
510
|
};
|
|
511
|
+
_focusHandler = () =>
|
|
512
|
+
/**
|
|
513
|
+
* Focus a list item
|
|
514
|
+
*/
|
|
515
|
+
(align = FocusAlignments.CENTER) => {
|
|
516
|
+
this.focus(align);
|
|
517
|
+
};
|
|
497
518
|
constructor() {
|
|
498
519
|
super();
|
|
499
520
|
this._id = this._service.generateComponentId();
|
|
500
521
|
this._elementRef.nativeElement.setAttribute('id', String(this._id));
|
|
501
|
-
const $data = toObservable(this.data), $
|
|
502
|
-
$
|
|
522
|
+
const $data = toObservable(this.data), $focused = toObservable(this.focused);
|
|
523
|
+
$focused.pipe(takeUntilDestroyed(), tap(v => {
|
|
503
524
|
this._service.areaFocus(v ? this._id : this._service.focusedId === this._id ? null : this._service.focusedId);
|
|
504
525
|
})).subscribe();
|
|
505
526
|
fromEvent(this.element, EVENT_FOCUS_IN).pipe(takeUntilDestroyed(), tap(e => {
|
|
506
|
-
this.
|
|
527
|
+
this.focused.set(true);
|
|
507
528
|
this.updateConfig(this._data);
|
|
508
529
|
this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
|
|
509
530
|
})).subscribe(),
|
|
510
531
|
fromEvent(this.element, EVENT_FOCUS_OUT).pipe(takeUntilDestroyed(), tap(e => {
|
|
511
|
-
this.
|
|
532
|
+
this.focused.set(false);
|
|
512
533
|
this.updateConfig(this._data);
|
|
513
534
|
this.updatePartStr(this._data, this._isSelected, this._isCollapsed);
|
|
514
535
|
})).subscribe(),
|
|
@@ -611,23 +632,34 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
611
632
|
}
|
|
612
633
|
}
|
|
613
634
|
}
|
|
635
|
+
focus(align = FocusAlignments.CENTER) {
|
|
636
|
+
if (this._service.listElement) {
|
|
637
|
+
const tabIndex = this._data?.config?.tabIndex ?? 0;
|
|
638
|
+
let index = tabIndex;
|
|
639
|
+
const el = this._service.listElement.querySelector(getElementByIndex(index));
|
|
640
|
+
if (el) {
|
|
641
|
+
this._service.focus(el, align);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
614
645
|
updateMeasures(v) {
|
|
615
646
|
this.measures.set(v?.measures ? { ...v.measures } : undefined);
|
|
616
647
|
}
|
|
617
648
|
updateConfig(v) {
|
|
618
649
|
this.config.set({
|
|
619
|
-
...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed,
|
|
620
|
-
collapse: this._collapseHandler(v), select: this._selectHandler(v)
|
|
650
|
+
...v?.config || {}, selected: this._isSelected, collapsed: this._isCollapsed, focused: this.focused(),
|
|
651
|
+
collapse: this._collapseHandler(v), select: this._selectHandler(v), focus: this._focusHandler(),
|
|
621
652
|
});
|
|
622
653
|
}
|
|
623
654
|
update() {
|
|
624
655
|
const data = this._data, regular = this.regular, length = this._regularLength;
|
|
625
656
|
if (data) {
|
|
657
|
+
this._elementRef.nativeElement.setAttribute(ID, `${data.id}`);
|
|
626
658
|
const styles = this._elementRef.nativeElement.style;
|
|
627
659
|
styles.zIndex = data.config.zIndex;
|
|
628
660
|
if (data.config.snapped) {
|
|
629
|
-
this._elementRef.nativeElement.setAttribute(
|
|
630
|
-
styles.transform = data.config.sticky === 1 ? ZEROS_TRANSLATE_3D : `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX}
|
|
661
|
+
this._elementRef.nativeElement.setAttribute(POSITION, data.config.sticky === 1 ? POSITION_ZERO : `${data.config.isVertical ? data.measures.y : data.measures.x}`);
|
|
662
|
+
styles.transform = data.config.sticky === 1 ? ZEROS_TRANSLATE_3D : `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX}, ${POSITION_ZERO})`;
|
|
631
663
|
;
|
|
632
664
|
if (!data.config.isSnappingMethodAdvanced) {
|
|
633
665
|
styles.position = POSITION_STICKY;
|
|
@@ -636,17 +668,20 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
636
668
|
else {
|
|
637
669
|
styles.position = POSITION_ABSOLUTE;
|
|
638
670
|
if (regular) {
|
|
639
|
-
this._elementRef.nativeElement.setAttribute(
|
|
640
|
-
styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.delta}${PX}, ${data.config.isVertical ? data.measures.delta : 0}${PX}
|
|
671
|
+
this._elementRef.nativeElement.setAttribute(POSITION, POSITION_ZERO);
|
|
672
|
+
styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.delta}${PX}, ${data.config.isVertical ? data.measures.delta : 0}${PX}, ${POSITION_ZERO})`;
|
|
641
673
|
}
|
|
642
674
|
else {
|
|
643
|
-
this._elementRef.nativeElement.setAttribute(
|
|
644
|
-
styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX}
|
|
675
|
+
this._elementRef.nativeElement.setAttribute(POSITION, `${data.config.isVertical ? data.measures.y : data.measures.x}`);
|
|
676
|
+
styles.transform = `${TRANSLATE_3D}(${data.config.isVertical ? 0 : data.measures.x}${PX}, ${data.config.isVertical ? data.measures.y : 0}${PX}, ${POSITION_ZERO})`;
|
|
645
677
|
}
|
|
646
678
|
}
|
|
647
679
|
styles.height = data.config.isVertical ? data.config.dynamic ? SIZE_AUTO : `${data.measures.height}${PX}` : regular ? length : SIZE_100_PERSENT;
|
|
648
680
|
styles.width = data.config.isVertical ? regular ? length : SIZE_100_PERSENT : data.config.dynamic ? SIZE_AUTO : `${data.measures.width}${PX}`;
|
|
649
681
|
}
|
|
682
|
+
else {
|
|
683
|
+
this._elementRef.nativeElement.removeAttribute(ID);
|
|
684
|
+
}
|
|
650
685
|
}
|
|
651
686
|
updatePartStr(v, isSelected, isCollapsed) {
|
|
652
687
|
let odd = false;
|
|
@@ -667,7 +702,7 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
667
702
|
if (v ? v.config.new : false) {
|
|
668
703
|
part += PART_ITEM_NEW;
|
|
669
704
|
}
|
|
670
|
-
if (this.
|
|
705
|
+
if (this.focused()) {
|
|
671
706
|
part += PART_ITEM_FOCUSED;
|
|
672
707
|
}
|
|
673
708
|
this.part.set(part);
|
|
@@ -714,14 +749,14 @@ class NgVirtualListItemComponent extends BaseVirtualListItemComponent {
|
|
|
714
749
|
this._service.itemClick(this._data);
|
|
715
750
|
}
|
|
716
751
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgVirtualListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
717
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: NgVirtualListItemComponent, isStandalone: true, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let item = data();\r\n@let _config = config();\r\n@let _part = part();\r\n@let _measures = measures();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <div #listItem [part]=\"_part\" [attr.ng-vl-index]=\"_config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\"\r\n [ngClass]=\"{'snapped': item.config.snapped, 'snapped-out': item.config.snappedOut, 'focus':
|
|
752
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: NgVirtualListItemComponent, isStandalone: true, selector: "ng-virtual-list-item", host: { attributes: { "role": "listitem" }, classAttribute: "ngvl__item" }, usesInheritance: true, ngImport: i0, template: "@let item = data();\r\n@let _config = config();\r\n@let _part = part();\r\n@let _measures = measures();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <div #listItem [part]=\"_part\" [attr.ng-vl-index]=\"_config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\"\r\n [ngClass]=\"{'snapped': item.config.snapped, 'snapped-out': item.config.snappedOut, 'focus': focused()}\" (click)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data, measures: _measures, config: _config}\" />\r\n }\r\n </div>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
718
753
|
}
|
|
719
754
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: NgVirtualListItemComponent, decorators: [{
|
|
720
755
|
type: Component,
|
|
721
756
|
args: [{ selector: 'ng-virtual-list-item', imports: [CommonModule], host: {
|
|
722
757
|
'class': 'ngvl__item',
|
|
723
758
|
'role': 'listitem',
|
|
724
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let item = data();\r\n@let _config = config();\r\n@let _part = part();\r\n@let _measures = measures();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <div #listItem [part]=\"_part\" [attr.ng-vl-index]=\"_config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\"\r\n [ngClass]=\"{'snapped': item.config.snapped, 'snapped-out': item.config.snappedOut, 'focus':
|
|
759
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "@let item = data();\r\n@let _config = config();\r\n@let _part = part();\r\n@let _measures = measures();\r\n@let renderer = itemRenderer();\r\n\r\n@if (item) {\r\n <div #listItem [part]=\"_part\" [attr.ng-vl-index]=\"_config.tabIndex || -1\" tabindex=\"0\" class=\"ngvl-item__container\"\r\n [ngClass]=\"{'snapped': item.config.snapped, 'snapped-out': item.config.snappedOut, 'focus': focused()}\" (click)=\"onClickHandler()\">\r\n @if (renderer) {\r\n <ng-container [ngTemplateOutlet]=\"renderer\"\r\n [ngTemplateOutletContext]=\"{data: item.data, measures: _measures, config: _config}\" />\r\n }\r\n </div>\r\n}", styles: [":host{display:block;position:absolute;left:0;top:0;box-sizing:border-box;overflow:hidden}.ngvl-item__container{margin:0;padding:0;overflow:hidden;background-color:#fff;width:inherit;height:inherit;box-sizing:border-box}\n"] }]
|
|
725
760
|
}], ctorParameters: () => [] });
|
|
726
761
|
|
|
727
762
|
/**
|
|
@@ -2161,7 +2196,7 @@ const isCollectionMode = (src, expected) => {
|
|
|
2161
2196
|
return NORMAL_ALIASES.includes(src);
|
|
2162
2197
|
};
|
|
2163
2198
|
|
|
2164
|
-
const ROLE_LIST = 'list', ROLE_LIST_BOX = 'listbox';
|
|
2199
|
+
const ROLE_LIST = 'list', ROLE_LIST_BOX = 'listbox', ITEM_ID = 'item-id', ITEM_CONTAINER = 'ngvl-item__container';
|
|
2165
2200
|
const validateScrollIteration = (value) => {
|
|
2166
2201
|
return Number.isNaN(value) || (value < 0) ? 0 : value > MAX_SCROLL_TO_ITERATIONS ? MAX_SCROLL_TO_ITERATIONS : value;
|
|
2167
2202
|
}, validateId = (id) => {
|
|
@@ -2179,6 +2214,11 @@ const validateScrollIteration = (value) => {
|
|
|
2179
2214
|
if (!valid) {
|
|
2180
2215
|
throw Error('The "iteration" parameter must be of type `number`.');
|
|
2181
2216
|
}
|
|
2217
|
+
}, validateFocusAlignment = (align) => {
|
|
2218
|
+
const valid = validateString(align) && (align === 'none' || align === 'start' || align === 'center' || align === 'end');
|
|
2219
|
+
if (!valid) {
|
|
2220
|
+
throw Error('The "align" parameter must have the value `none`, `start`, `center` or `end`.');
|
|
2221
|
+
}
|
|
2182
2222
|
};
|
|
2183
2223
|
/**
|
|
2184
2224
|
* Virtual list component.
|
|
@@ -2643,12 +2683,33 @@ class NgVirtualListComponent {
|
|
|
2643
2683
|
this._scrollSize.set(actualScrollSize);
|
|
2644
2684
|
}
|
|
2645
2685
|
};
|
|
2646
|
-
itemToFocus = (element, position) => {
|
|
2686
|
+
itemToFocus = (element, position, align = FocusAlignments.CENTER) => {
|
|
2647
2687
|
const container = this._container()?.nativeElement;
|
|
2648
2688
|
if (container) {
|
|
2649
|
-
const { width, height } = this._bounds(), { width: elementWidth, height: elementHeight } = element.getBoundingClientRect(), isVertical = this._isVertical
|
|
2650
|
-
|
|
2651
|
-
|
|
2689
|
+
const { width, height } = this._bounds(), { width: elementWidth, height: elementHeight } = element.getBoundingClientRect(), isVertical = this._isVertical;
|
|
2690
|
+
let pos = Number.NaN;
|
|
2691
|
+
switch (align) {
|
|
2692
|
+
case FocusAlignments.START: {
|
|
2693
|
+
pos = isVertical ? position : position;
|
|
2694
|
+
break;
|
|
2695
|
+
}
|
|
2696
|
+
case FocusAlignments.CENTER: {
|
|
2697
|
+
pos = isVertical ? position - (height - elementHeight) * .5 : position - (width - elementWidth) * .5;
|
|
2698
|
+
break;
|
|
2699
|
+
}
|
|
2700
|
+
case FocusAlignments.END: {
|
|
2701
|
+
pos = isVertical ? position - (height - elementHeight) : position - (width - elementWidth);
|
|
2702
|
+
break;
|
|
2703
|
+
}
|
|
2704
|
+
case FocusAlignments.NONE:
|
|
2705
|
+
default: {
|
|
2706
|
+
break;
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
if (!Number.isNaN(pos)) {
|
|
2710
|
+
const params = { [this._isVertical ? TOP_PROP_NAME : LEFT_PROP_NAME]: pos, behavior: 'instant' };
|
|
2711
|
+
container.scrollTo(params);
|
|
2712
|
+
}
|
|
2652
2713
|
}
|
|
2653
2714
|
};
|
|
2654
2715
|
_elementRef = inject((ElementRef));
|
|
@@ -2974,6 +3035,20 @@ class NgVirtualListComponent {
|
|
|
2974
3035
|
validateId(id);
|
|
2975
3036
|
return this._trackBox.getItemBounds(id);
|
|
2976
3037
|
}
|
|
3038
|
+
/**
|
|
3039
|
+
* Focus an list item by a given id.
|
|
3040
|
+
*/
|
|
3041
|
+
focus(id, align = FocusAlignments.NONE) {
|
|
3042
|
+
validateId(id);
|
|
3043
|
+
validateFocusAlignment(align);
|
|
3044
|
+
const el = this._list()?.nativeElement.querySelector(`[${ITEM_ID}="${id}"]`);
|
|
3045
|
+
if (el) {
|
|
3046
|
+
const focusedEl = el.querySelector(`.${ITEM_CONTAINER}`);
|
|
3047
|
+
if (focusedEl) {
|
|
3048
|
+
this._service.focus(focusedEl, align);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
2977
3052
|
/**
|
|
2978
3053
|
* The method scrolls the list to the element with the given id and returns the value of the scrolled area.
|
|
2979
3054
|
* Behavior accepts the values "auto", "instant" and "smooth".
|
|
@@ -3158,5 +3233,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImpor
|
|
|
3158
3233
|
* Generated bundle index. Do not edit.
|
|
3159
3234
|
*/
|
|
3160
3235
|
|
|
3161
|
-
export { CollectionModes, Directions, MethodsForSelecting, NgVirtualListComponent, NgVirtualListItemComponent, ScrollEvent, SnappingMethods, debounce, toggleClassName };
|
|
3236
|
+
export { CollectionModes, Directions, FocusAlignments, MethodsForSelecting, NgVirtualListComponent, NgVirtualListItemComponent, ScrollEvent, SnappingMethods, debounce, toggleClassName };
|
|
3162
3237
|
//# sourceMappingURL=ng-virtual-list.mjs.map
|