All files / src/app/core/directives intersection-observer-util.ts

12.5% Statements 3/24
0% Branches 0/4
0% Functions 0/10
9.09% Lines 2/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 57 58 593x       3x                                                                                                            
import { Observable, Subject, debounceTime, filter } from 'rxjs';
 
export type IntersectionStatus = 'Visible' | 'Pending' | 'NotVisible';
 
export const fromIntersectionObserver = (
  element: HTMLElement,
  config: IntersectionObserverInit = {
    root: undefined,
    rootMargin: '0px',
    threshold: undefined,
  },
  debounce = 0
) =>
  new Observable<IntersectionStatus>(subscriber => {
    const subject$ = new Subject<{
      entry: IntersectionObserverEntry;
      observer: IntersectionObserver;
    }>();
 
    const intersectionObserver = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => subject$.next({ entry, observer }));
    }, config);
 
    subject$.subscribe(() => {
      subscriber.next('Pending');
    });
 
    subject$.pipe(debounceTime(debounce), filter(Boolean)).subscribe(async ({ entry }) => {
      const isEntryVisible = await isVisible(entry.target as HTMLElement);
 
      if (isEntryVisible) {
        subscriber.next('Visible');
      } else {
        subscriber.next('NotVisible');
      }
    });
 
    intersectionObserver.observe(element);
 
    return {
      unsubscribe() {
        intersectionObserver.disconnect();
        // eslint-disable-next-line ban/ban, rxjs/no-subject-unsubscribe
        subject$.unsubscribe();
      },
    };
  });
 
async function isVisible(element: HTMLElement) {
  return new Promise(resolve => {
    const observer = new IntersectionObserver(([entry]) => {
      resolve(entry.isIntersecting);
      observer.disconnect();
    });
 
    observer.observe(element);
  });
}