@thejlifex/ngx-scroll-spy
Version:
An Angular library that can spy the position of elements (inside a scrollable container) and emit the currently active (visible) element in the viewport.
68 lines • 8.69 kB
JavaScript
import { isPlatformServer } from '@angular/common';
import { Directive, Input, HostBinding, Inject, PLATFORM_ID } from '@angular/core';
import { filter, Subject, takeUntil } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "./scroll-spy.service";
/**
* Spies on the spyTarget that has the provided `spyTargetId`.
*/
export class SpyDirective {
constructor(scrollSpyService, platformId, changeDetectorRef) {
this.scrollSpyService = scrollSpyService;
this.platformId = platformId;
this.changeDetectorRef = changeDetectorRef;
/**
* Class name to add to this element when the spyTarget has transitioned into a state of intersection (is visisble).
*
* @default
* 'active'
*/
this.spyActiveClass = 'active';
this.directiveDestroyed$ = new Subject();
}
ngOnInit() {
if (isPlatformServer(this.platformId)) {
return;
}
if (!this.spyTargetId) {
throw new Error('SpyDirective: spyTargetId needs to be set.');
}
this.scrollSpyService.getSpyTargetIsIntersecting$(this.spyTargetContainerId)
.pipe(takeUntil(this.directiveDestroyed$), filter((event) => event.spyTarget.id === this.spyTargetId
&& event.spyTarget.containerId === this.spyTargetContainerId))
.subscribe((event) => {
this.activeClassInDOM = event.isIntersecting ? this.spyActiveClass : undefined;
/**
* Manually trigger change detection to update activeClass in the DOM
* (Needed for the case changeDetection OnPush is used).
*/
this.changeDetectorRef.detectChanges();
});
}
ngOnDestroy() {
this.directiveDestroyed$.next();
this.directiveDestroyed$.complete();
}
}
SpyDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.4", ngImport: i0, type: SpyDirective, deps: [{ token: i1.ScrollSpyService }, { token: PLATFORM_ID }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
SpyDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.4", type: SpyDirective, isStandalone: true, selector: "[spy]", inputs: { spyTargetId: "spyTargetId", spyTargetContainerId: "spyTargetContainerId", spyActiveClass: "spyActiveClass" }, host: { properties: { "class": "this.activeClassInDOM" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.4", ngImport: i0, type: SpyDirective, decorators: [{
type: Directive,
args: [{
selector: '[spy]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.ScrollSpyService }, { type: undefined, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { spyTargetId: [{
type: Input
}], spyTargetContainerId: [{
type: Input
}], spyActiveClass: [{
type: Input
}], activeClassInDOM: [{
type: HostBinding,
args: ['class']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3B5LmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zY3JvbGwtc3B5L3NyYy9saWIvc3B5LmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBcUIsV0FBVyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQXFCLE1BQU0sZUFBZSxDQUFDO0FBQ3pILE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7O0FBR2xEOztHQUVHO0FBS0gsTUFBTSxPQUFPLFlBQVk7SUEwQnZCLFlBQ1UsZ0JBQWtDLEVBQ2IsVUFBa0IsRUFDdkMsaUJBQW9DO1FBRnBDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDYixlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQ3ZDLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFmOUM7Ozs7O1dBS0c7UUFDTSxtQkFBYyxHQUFXLFFBQVEsQ0FBQztRQUluQyx3QkFBbUIsR0FBRyxJQUFJLE9BQU8sRUFBUSxDQUFDO0lBTTlDLENBQUM7SUFFTCxRQUFRO1FBQ04sSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDckMsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1NBQy9EO1FBQ0QsSUFBSSxDQUFDLGdCQUFnQixDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQzthQUN6RSxJQUFJLENBQ0gsU0FBUyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxFQUNuQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNmLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyxXQUFXO2VBQ3BDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxLQUFLLElBQUksQ0FBQyxvQkFBb0IsQ0FDN0QsQ0FDRjthQUNBLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDL0U7OztlQUdHO1lBQ0gsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3RDLENBQUM7O3lHQTVEVSxZQUFZLGtEQTRCYixXQUFXOzZGQTVCVixZQUFZOzJGQUFaLFlBQVk7a0JBSnhCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLE9BQU87b0JBQ2pCLFVBQVUsRUFBRSxJQUFJO2lCQUNqQjs7MEJBNkJJLE1BQU07MkJBQUMsV0FBVzs0RUF2QlosV0FBVztzQkFBbkIsS0FBSztnQkFPRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBUUcsY0FBYztzQkFBdEIsS0FBSztnQkFFZ0IsZ0JBQWdCO3NCQUFyQyxXQUFXO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1BsYXRmb3JtU2VydmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgRGlyZWN0aXZlLCBJbnB1dCwgT25Jbml0LCBPbkRlc3Ryb3ksIEhvc3RCaW5kaW5nLCBJbmplY3QsIFBMQVRGT1JNX0lELCBDaGFuZ2VEZXRlY3RvclJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBmaWx0ZXIsIFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBTY3JvbGxTcHlTZXJ2aWNlIH0gZnJvbSAnLi9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIFNwaWVzIG9uIHRoZSBzcHlUYXJnZXQgdGhhdCBoYXMgdGhlIHByb3ZpZGVkIGBzcHlUYXJnZXRJZGAuXHJcbiAqL1xyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tzcHldJyxcclxuICBzdGFuZGFsb25lOiB0cnVlXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBTcHlEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcblxyXG4gIC8qKlxyXG4gICAqIElEIG9mIHRoZSBzcHlUYXJnZXQgdG8gc3B5LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHNweVRhcmdldElkITogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBAb3B0aW9uYWxcclxuICAgKlxyXG4gICAqIElEIG9mIHRoZSBzcHlUYXJnZXRDb250YWluZXIgY29udGFpbmluZyB0aGUgc3B5VGFyZ2V0LlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHNweVRhcmdldENvbnRhaW5lcklkPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBDbGFzcyBuYW1lIHRvIGFkZCB0byB0aGlzIGVsZW1lbnQgd2hlbiB0aGUgc3B5VGFyZ2V0IGhhcyB0cmFuc2l0aW9uZWQgaW50byBhIHN0YXRlIG9mIGludGVyc2VjdGlvbiAoaXMgdmlzaXNibGUpLlxyXG4gICAqXHJcbiAgICogQGRlZmF1bHRcclxuICAgKiAnYWN0aXZlJ1xyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHNweUFjdGl2ZUNsYXNzOiBzdHJpbmcgPSAnYWN0aXZlJztcclxuXHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcycpIGFjdGl2ZUNsYXNzSW5ET00/OiBzdHJpbmc7XHJcblxyXG4gIHByaXZhdGUgZGlyZWN0aXZlRGVzdHJveWVkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBzY3JvbGxTcHlTZXJ2aWNlOiBTY3JvbGxTcHlTZXJ2aWNlLFxyXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBzdHJpbmcsXHJcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxyXG4gICkgeyB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgaWYgKGlzUGxhdGZvcm1TZXJ2ZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAoIXRoaXMuc3B5VGFyZ2V0SWQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTcHlEaXJlY3RpdmU6IHNweVRhcmdldElkIG5lZWRzIHRvIGJlIHNldC4nKTtcclxuICAgIH1cclxuICAgIHRoaXMuc2Nyb2xsU3B5U2VydmljZS5nZXRTcHlUYXJnZXRJc0ludGVyc2VjdGluZyQodGhpcy5zcHlUYXJnZXRDb250YWluZXJJZClcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGlyZWN0aXZlRGVzdHJveWVkJCksXHJcbiAgICAgICAgZmlsdGVyKChldmVudCkgPT5cclxuICAgICAgICAgIGV2ZW50LnNweVRhcmdldC5pZCA9PT0gdGhpcy5zcHlUYXJnZXRJZFxyXG4gICAgICAgICAgJiYgZXZlbnQuc3B5VGFyZ2V0LmNvbnRhaW5lcklkID09PSB0aGlzLnNweVRhcmdldENvbnRhaW5lcklkXHJcbiAgICAgICAgKVxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgdGhpcy5hY3RpdmVDbGFzc0luRE9NID0gZXZlbnQuaXNJbnRlcnNlY3RpbmcgPyB0aGlzLnNweUFjdGl2ZUNsYXNzIDogdW5kZWZpbmVkO1xyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIE1hbnVhbGx5IHRyaWdnZXIgY2hhbmdlIGRldGVjdGlvbiB0byB1cGRhdGUgYWN0aXZlQ2xhc3MgaW4gdGhlIERPTVxyXG4gICAgICAgICAqIChOZWVkZWQgZm9yIHRoZSBjYXNlIGNoYW5nZURldGVjdGlvbiBPblB1c2ggaXMgdXNlZCkuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmRpcmVjdGl2ZURlc3Ryb3llZCQubmV4dCgpO1xyXG4gICAgdGhpcy5kaXJlY3RpdmVEZXN0cm95ZWQkLmNvbXBsZXRlKCk7XHJcbiAgfVxyXG59XHJcbiJdfQ==