feat: add `MultipleIntersectionObserver`
A common scenario is to have multiple elements for observing. Currently, the library only allows one element to be observed at a time. For large number of items, this is less performant than using a single observer for multiple elements.
This introduces MultipleIntersectionObserver, which allows multiple elements to be observed by a single instance. The ergonomics of using it is a bit different, in that an array is provided and a Map returned.
The most basic, proposed usage is as follows:
<script>
import { MultipleIntersectionObserver } from "svelte-intersection-observer";
let ref1;
let ref2;
$: elements = [ref1, ref2];
</script>
<header />
<MultipleIntersectionObserver {elements} let:elementIntersections>
{#each elements as element, index}
{@const visible = elementIntersections.get(element)}
<div bind:this={element} class:visible>
Item {index + 1}
</div>
{/each}
</MultipleIntersectionObserver>
Another example is binding to the map directly to re-use state elsewhere in the component:
<script>
import { MultipleIntersectionObserver } from "svelte-intersection-observer";
let ref1;
let ref2;
let elementIntersections = new Map();
$: elements = [ref1, ref2];
$: anyItemVisible = Array.from(elementIntersections).some(
(visible) => visible,
);
</script>
<header class:intersecting={anyItemVisible}>
{#each elements as element, index}
{@const visible = elementIntersections.get(element)}
{#if visible}
Item {index + 1} visible
{/if}
{/each}
</header>
<MultipleIntersectionObserver
{elements}
bind:elementIntersections
let:elementIntersections
>
{#each elements as element, index}
{@const visible = elementIntersections.get(element)}
<div bind:this={element} class:visible>
Item {index + 1} ({visible})
</div>
{/each}
</MultipleIntersectionObserver>
However, it's simpler to wrap the sibling element with the MultipleIntersectionObserver instance, and use the destructed let:elementIntersections directly instead of binding to it.
<script>
import { MultipleIntersectionObserver } from "svelte-intersection-observer";
let ref1;
let ref2;
$: elements = [ref1, ref2];
</script>
<MultipleIntersectionObserver {elements} let:elementIntersections>
{@const anyItemVisible = Array.from(elementIntersections).some(
(visible) => visible,
)}
<header class:intersecting={anyItemVisible}>
{#each elements as element, index}
{@const visible = elementIntersections.get(element)}
{#if visible}
Item {index + 1} visible
{/if}
{/each}
</header>
{#each elements as element, index}
{@const visible = elementIntersections.get(element)}
<div bind:this={element} class:visible>
Item {index + 1} ({visible})
</div>
{/each}
</MultipleIntersectionObserver>