UNPKG

@ynmstudio/utils

Version:
111 lines (106 loc) 4.74 kB
import { isPlatformBrowser } from '@angular/common'; import * as i0 from '@angular/core'; import { InjectionToken, inject, EventEmitter, DOCUMENT, PLATFORM_ID, HostBinding, Output, Input, Inject, Directive } from '@angular/core'; const INTERSECTION_OBSERVER_INIT = new InjectionToken('IntersectionObserverInit'); /** * A simple lightweight library for Angular with that detects when an * element is within the browsers viewport and adds a `in-viewport` or * `not-in-viewport` class to the element. * * @example * ```html * <p * class="foo" * snInViewport * (inViewportChange)="myEventHandler($event)"> * Amet tempor excepteur occaecat nulla. * </p> * ``` */ // @dynamic class InViewportDirective { get isInViewport() { return this.inViewport; } get isNotInViewport() { return !this.inViewport; } constructor(document, platformId, el) { this.document = document; this.platformId = platformId; this.el = el; this.inViewport = false; this.inViewportOptions = inject(INTERSECTION_OBSERVER_INIT, { optional: true }) ?? undefined; this.inViewportChange = new EventEmitter(); this.hasIntersectionObserver = this.intersectionObserverFeatureDetection(); } ngOnInit() { if (!this.hasIntersectionObserver || !isPlatformBrowser(this.platformId)) { this.inViewport = true; this.inViewportChange.emit(this.inViewport); } } ngAfterViewInit() { if (this.hasIntersectionObserver && isPlatformBrowser(this.platformId)) { // const IntersectionObserver = this.window['IntersectionObserver']; this.observer = new IntersectionObserver(this.intersectionObserverCallback.bind(this), this.inViewportOptions); this.observer?.observe(this.el.nativeElement); } } ngOnDestroy() { if (this.observer) { this.observer.unobserve(this.el.nativeElement); } } intersectionObserverCallback(entries) { entries.forEach((entry) => { if (this.inViewport === entry.isIntersecting) return; this.inViewport = entry.isIntersecting; this.inViewportChange.emit(this.inViewport); }); } intersectionObserverFeatureDetection() { const window = this.document.defaultView; const hasIntersectionObserver = !!window?.IntersectionObserver; const userAgent = window?.navigator.userAgent; const matches = userAgent?.match(/Edge\/(\d*)\./i); const isEdge = !!matches && matches.length > 1; const isEdgeVersion16OrBetter = isEdge && !!matches && parseInt(matches[1], 10) > 15; return hasIntersectionObserver && (!isEdge || isEdgeVersion16OrBetter); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: InViewportDirective, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: InViewportDirective, isStandalone: true, selector: "[snInViewport]", inputs: { inViewportOptions: "inViewportOptions" }, outputs: { inViewportChange: "inViewportChange" }, host: { properties: { "class.sn-viewport--in": "this.isInViewport", "class.sn-viewport--out": "this.isNotInViewport" } }, exportAs: ["snInViewport"], ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: InViewportDirective, decorators: [{ type: Directive, args: [{ selector: '[snInViewport]', exportAs: 'snInViewport', standalone: true, }] }], ctorParameters: () => [{ type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }, { type: i0.ElementRef }], propDecorators: { inViewportOptions: [{ type: Input }], inViewportChange: [{ type: Output }], isInViewport: [{ type: HostBinding, args: ['class.sn-viewport--in'] }], isNotInViewport: [{ type: HostBinding, args: ['class.sn-viewport--out'] }] } }); /* * Public API Surface of ngx-inviewport */ /** * Generated bundle index. Do not edit. */ export { INTERSECTION_OBSERVER_INIT, InViewportDirective }; //# sourceMappingURL=ynmstudio-utils-inviewport.mjs.map