(options: IntersectionObserverInit)
| 58 | } |
| 59 | |
| 60 | function createObserver(options: IntersectionObserverInit) { |
| 61 | // Create a unique ID for this observer instance, based on the root, root margin and threshold. |
| 62 | const id = optionsToId(options); |
| 63 | let instance = observerMap.get(id); |
| 64 | |
| 65 | if (!instance) { |
| 66 | // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view. |
| 67 | const elements = new Map<Element, Array<ObserverInstanceCallback>>(); |
| 68 | let thresholds: number[] | readonly number[]; |
| 69 | |
| 70 | const observer = new IntersectionObserver((entries) => { |
| 71 | entries.forEach((entry) => { |
| 72 | // While it would be nice if you could just look at isIntersecting to determine if the component is inside the viewport, browsers can't agree on how to use it. |
| 73 | // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0 |
| 74 | const inView = |
| 75 | entry.isIntersecting && |
| 76 | thresholds.some((threshold) => entry.intersectionRatio >= threshold); |
| 77 | |
| 78 | // @ts-expect-error support IntersectionObserver v2 |
| 79 | if (options.trackVisibility && typeof entry.isVisible === "undefined") { |
| 80 | // The browser doesn't support Intersection Observer v2, falling back to v1 behavior. |
| 81 | // @ts-expect-error |
| 82 | entry.isVisible = inView; |
| 83 | } |
| 84 | |
| 85 | // Copy the callbacks array before iterating to prevent issues when callbacks are removed during iteration (e.g., when using triggerOnce) |
| 86 | [...(elements.get(entry.target) ?? [])].forEach((callback) => { |
| 87 | callback(inView, entry); |
| 88 | }); |
| 89 | }); |
| 90 | }, options); |
| 91 | |
| 92 | // Ensure we have a valid thresholds array. If not, use the threshold from the options |
| 93 | thresholds = |
| 94 | observer.thresholds || |
| 95 | (Array.isArray(options.threshold) |
| 96 | ? options.threshold |
| 97 | : [options.threshold || 0]); |
| 98 | |
| 99 | instance = { |
| 100 | id, |
| 101 | observer, |
| 102 | elements, |
| 103 | }; |
| 104 | |
| 105 | observerMap.set(id, instance); |
| 106 | } |
| 107 | |
| 108 | return instance; |
| 109 | } |
| 110 | |
| 111 | /** |
| 112 | * @param element - DOM Element to observe |
no test coverage detected
searching dependent graphs…