@ynmstudio/utils
Version:
YNM Utilities for Angular
111 lines (106 loc) • 4.74 kB
JavaScript
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