From 8b682346214121cc7bddfde839802dc0bf457d41 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Sat, 1 Mar 2025 17:09:39 -0800 Subject: [PATCH] feat: add `MultipleIntersectionObserver` --- README.md | 29 ++++ src/MultipleIntersectionObserver.svelte | 134 +++++++++++++++++++ src/MultipleIntersectionObserver.svelte.d.ts | 82 ++++++++++++ src/index.d.ts | 1 + src/index.js | 1 + 5 files changed, 247 insertions(+) create mode 100644 src/MultipleIntersectionObserver.svelte create mode 100644 src/MultipleIntersectionObserver.svelte.d.ts diff --git a/README.md b/README.md index 11a190a..36a83ea 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,35 @@ As an alternative to binding the `intersecting` prop, you can listen to the `int ``` +### Multiple elements + +For performance, use `MultipleIntersectionObserver` to observe multiple elements. + +This avoids instantiating a new observer for every element. + +```svelte + + +
+ + + {#each elements as element, index} + {@const visible = elementIntersections.get(element)} + +
+ Item {index + 1} +
+ {/each} +
+``` + ## API ### Props diff --git a/src/MultipleIntersectionObserver.svelte b/src/MultipleIntersectionObserver.svelte new file mode 100644 index 0000000..73c2b75 --- /dev/null +++ b/src/MultipleIntersectionObserver.svelte @@ -0,0 +1,134 @@ + + + diff --git a/src/MultipleIntersectionObserver.svelte.d.ts b/src/MultipleIntersectionObserver.svelte.d.ts new file mode 100644 index 0000000..568c40e --- /dev/null +++ b/src/MultipleIntersectionObserver.svelte.d.ts @@ -0,0 +1,82 @@ +import type { SvelteComponentTyped } from "svelte"; + +export default class extends SvelteComponentTyped< + { + /** + * Array of HTML Elements to observe. + * Use this for better performance when observing multiple elements. + * @default [] + */ + elements?: HTMLElement[]; + + /** + * Set to `true` to unobserve the element + * after it intersects the viewport. + * @default false + */ + once?: boolean; + + /** + * Specify the containing element. + * Defaults to the browser viewport. + * @default null + */ + root?: null | HTMLElement; + + /** + * Margin offset of the containing element. + * @default "0px" + */ + rootMargin?: string; + + /** + * Percentage of element visibility to trigger an event. + * Value must be a number between 0 and 1, or an array of numbers between 0 and 1. + * @default 0 + */ + threshold?: number | number[]; + + /** + * Map of element to its intersection state. + * @default new Map() + */ + elementIntersections?: Map; + + /** + * Map of element to its latest entry. + * @default new Map() + */ + elementEntries?: Map; + + /** + * `IntersectionObserver` instance. + * @default null + */ + observer?: null | IntersectionObserver; + }, + { + /** + * Dispatched when an element is first observed + * and also whenever an intersection event occurs. + */ + observe: CustomEvent<{ + entry: IntersectionObserverEntry; + target: HTMLElement; + }>; + + /** + * Dispatched only when an element is intersecting the viewport. + */ + intersect: CustomEvent<{ + entry: IntersectionObserverEntry & { isIntersecting: true }; + target: HTMLElement; + }>; + }, + { + default: { + observer: IntersectionObserver; + elementIntersections: Map; + elementEntries: Map; + }; + } +> {} diff --git a/src/index.d.ts b/src/index.d.ts index b012505..bad0c5a 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1 +1,2 @@ export { default } from "./IntersectionObserver.svelte"; +export { default as MultipleIntersectionObserver } from "./MultipleIntersectionObserver.svelte"; diff --git a/src/index.js b/src/index.js index b012505..bad0c5a 100644 --- a/src/index.js +++ b/src/index.js @@ -1 +1,2 @@ export { default } from "./IntersectionObserver.svelte"; +export { default as MultipleIntersectionObserver } from "./MultipleIntersectionObserver.svelte";