-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
intersect.js
55 lines (47 loc) · 1.59 KB
/
intersect.js
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
/**
* @copyright 2023 Chris Zuber <[email protected]>
*/
import { getDeferred } from './promises.js';
const protectedData = new WeakMap();
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const { resolve } = protectedData.get(entry.target);
protectedData.delete(entry.target);
resolve(entry);
observer.unobserve(entry.target);
}
});
}, {
rootMargin: `${Math.min(250, Math.floor(screen.height * 0.3))}px`,
});
export async function whenIntersecting(target, { signal, base = document } = {}) {
const { resolve, reject, promise } = getDeferred();
if (signal instanceof AbortSignal && signal.aborted) {
reject(signal.reason);
} else if (typeof target === 'string') {
whenIntersecting(base.querySelector(target), { signal }).then(resolve).catch(reject);
} else if (! (target instanceof Element)) {
reject(new TypeError('Non-elements can never intersect'));
} else if (protectedData.has(target)) {
protectedData.get(target).promise.then(resolve).catch(reject);
if (signal instanceof AbortSignal) {
signal.addEventListener('abort', ({ target: { reason }}) => {
reject(reason);
}, { once: true });
}
} else {
protectedData.set(target, { resolve, reject, promise });
observer.observe(target);
if (signal instanceof AbortSignal) {
signal.addEventListener('abort', ({ target: { reason }}) => {
observer.unobserve(target);
if (protectedData.has(target)) {
protectedData.get(target).reject(reason);
protectedData.delete(target);
}
}, { once: true });
}
}
return promise;
}