-
Notifications
You must be signed in to change notification settings - Fork 142
/
Copy pathhooks.ts
56 lines (47 loc) · 1.9 KB
/
hooks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import { Observable, of, Subject } from 'rxjs';
import { filter } from 'rxjs/operators';
import { SharedHooks } from '../shared-hooks/hooks';
import { Attributes } from '../types';
export class IntersectionObserverHooks extends SharedHooks<{ isIntersecting: boolean }> {
private readonly observers = new WeakMap<Element | {}, IntersectionObserver>();
private readonly intersectionSubject = new Subject<IntersectionObserverEntry>();
private readonly uniqKey = {};
getObservable(attributes: Attributes<{ isIntersecting: boolean }>): Observable<{ isIntersecting: boolean }> {
if (this.skipLazyLoading(attributes)) {
return of({ isIntersecting: true });
}
if (attributes.customObservable) {
return attributes.customObservable;
}
const scrollContainerKey = attributes.scrollContainer || this.uniqKey;
const options: ObserverOptions = {
root: attributes.scrollContainer || null,
};
if (attributes.offset) {
options.rootMargin = `${attributes.offset}px`;
}
let observer = this.observers.get(scrollContainerKey);
if (!observer) {
observer = new IntersectionObserver((entrys) => this.loadingCallback(entrys), options);
this.observers.set(scrollContainerKey, observer);
}
observer.observe(attributes.element);
return Observable.create((obs: Subject<IntersectionObserverEntry>) => {
const subscription = this.intersectionSubject.pipe(filter((entry) => entry.target === attributes.element)).subscribe(obs);
return () => {
subscription.unsubscribe();
observer!.unobserve(attributes.element);
};
});
}
isVisible(event: { isIntersecting: boolean }): boolean {
return event.isIntersecting;
}
private loadingCallback(entrys: IntersectionObserverEntry[]) {
entrys.forEach((entry) => this.intersectionSubject.next(entry));
}
}
interface ObserverOptions {
root: Element | null;
rootMargin?: string;
}