mirror of
https://github.com/bitwarden/browser
synced 2025-12-19 01:33:33 +00:00
[CL-834] Use intersection observer to determine if content scrolls (#16099)
* use intersection observer to fix dynamic content load issue * set up mock intersection observer * Create reusable hasScrollable content util * return null from resize to fix type error * remove Observer mock * return observable * refactor util and remove resize * use async pipe for observable in template * remove comment left in error
This commit is contained in:
17
libs/components/src/utils/dom-observables.ts
Normal file
17
libs/components/src/utils/dom-observables.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
/** IntersectionObserver Observable */
|
||||
export const intersectionObserver$ = (
|
||||
target: Element,
|
||||
init: IntersectionObserverInit,
|
||||
): Observable<IntersectionObserverEntry> => {
|
||||
return new Observable((sub) => {
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
for (const e of entries) {
|
||||
sub.next(e);
|
||||
}
|
||||
}, init);
|
||||
io.observe(target);
|
||||
return () => io.disconnect();
|
||||
});
|
||||
};
|
||||
26
libs/components/src/utils/has-scrollable-content.ts
Normal file
26
libs/components/src/utils/has-scrollable-content.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Observable, animationFrameScheduler } from "rxjs";
|
||||
import { auditTime, map, startWith, observeOn, distinctUntilChanged } from "rxjs/operators";
|
||||
|
||||
import { intersectionObserver$ } from "./dom-observables";
|
||||
/**
|
||||
* Utility to determine if an element has scrollable content.
|
||||
* Returns an Observable that emits whenever scroll/resize/layout might change visibility
|
||||
*/
|
||||
export const hasScrollableContent$ = (
|
||||
root: HTMLElement,
|
||||
target: HTMLElement,
|
||||
threshold: number = 1,
|
||||
): Observable<boolean> => {
|
||||
return intersectionObserver$(target, { root, threshold }).pipe(
|
||||
startWith(null as IntersectionObserverEntry | null),
|
||||
auditTime(0, animationFrameScheduler),
|
||||
observeOn(animationFrameScheduler),
|
||||
map((entry: IntersectionObserverEntry | null) => {
|
||||
if (!entry) {
|
||||
return root.scrollHeight > root.clientHeight;
|
||||
}
|
||||
return !entry.isIntersecting;
|
||||
}),
|
||||
distinctUntilChanged(),
|
||||
);
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./aria-disable-element";
|
||||
export * from "./function-to-observable";
|
||||
export * from "./has-scrollable-content";
|
||||
export * from "./i18n-mock.service";
|
||||
|
||||
Reference in New Issue
Block a user