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 59 | 3x 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); }); } |