@solid-primitives/intersection-observer
Version:
Primitives to support using the intersection observer API.
172 lines (171 loc) • 8.22 kB
TypeScript
import type { JSX, Accessor } from "solid-js";
import { type FalsyValue, type MaybeAccessor } from "@solid-primitives/utils";
export type AddIntersectionObserverEntry = (el: Element) => void;
export type RemoveIntersectionObserverEntry = (el: Element) => void;
export type EntryCallback = (entry: IntersectionObserverEntry, instance: IntersectionObserver) => void;
export type AddViewportObserverEntry = (el: Element, callback: MaybeAccessor<EntryCallback>) => void;
export type RemoveViewportObserverEntry = (el: Element) => void;
export type CreateViewportObserverReturnValue = [
AddViewportObserverEntry,
{
remove: RemoveViewportObserverEntry;
start: () => void;
stop: () => void;
instance: IntersectionObserver;
}
];
declare module "solid-js" {
namespace JSX {
interface Directives {
intersectionObserver: true | EntryCallback;
}
}
}
export type E = JSX.Element;
/**
* @deprecated Please use native {@link IntersectionObserver}, or {@link createIntersectionObserver} instead.
*/
export declare function makeIntersectionObserver(elements: Element[], onChange: IntersectionObserverCallback, options?: IntersectionObserverInit): {
add: AddIntersectionObserverEntry;
remove: RemoveIntersectionObserverEntry;
start: VoidFunction;
reset: VoidFunction;
stop: VoidFunction;
instance: IntersectionObserver;
};
/**
* Creates a reactive Intersection Observer primitive.
*
* @param elements - A list of elements to watch
* @param onChange - An event handler that returns an array of observer entires
* @param options - IntersectionObserver constructor options:
* - `root` — The Element or Document whose bounds are used as the bounding box when testing for intersection.
* - `rootMargin` — A string which specifies a set of offsets to add to the root's bounding_box when calculating intersections, effectively shrinking or growing the root for calculation purposes.
* - `threshold` — Either a single number or an array of numbers between 0.0 and 1.0, specifying a ratio of intersection area to total bounding box area for the observed target.
*
* @example
* ```tsx
* const createIntersectionObserver(els, entries =>
* console.log(entries)
* );
* ```
*/
export declare function createIntersectionObserver(elements: Accessor<Element[]>, onChange: IntersectionObserverCallback, options?: IntersectionObserverInit): void;
/**
* Creates a more advanced viewport observer for complex tracking with multiple objects in a single IntersectionObserver instance.
*
* @param elements - A list of elements to watch
* @param callback - Element intersection change event handler
* @param options - IntersectionObserver constructor options:
* - `root` — The Element or Document whose bounds are used as the bounding box when testing for intersection.
* - `rootMargin` — A string which specifies a set of offsets to add to the root's bounding_box when calculating intersections, effectively shrinking or growing the root for calculation purposes.
* - `threshold` — Either a single number or an array of numbers between 0.0 and 1.0, specifying a ratio of intersection area to total bounding box area for the observed target.
*
* @example
* ```tsx
* const [add, { remove, start, stop, instance }] = createViewportObserver(els, (e) => {...});
* add(el, e => console.log(e.isIntersecting))
*
* // directive usage:
* const [intersectionObserver] = createViewportObserver()
* <div use:intersectionObserver={(e) => console.log(e.isIntersecting)}></div>
* ```
*/
export declare function createViewportObserver(elements: MaybeAccessor<Element[]>, callback: EntryCallback, options?: IntersectionObserverInit): CreateViewportObserverReturnValue;
export declare function createViewportObserver(initial: MaybeAccessor<[Element, EntryCallback][]>, options?: IntersectionObserverInit): CreateViewportObserverReturnValue;
export declare function createViewportObserver(options?: IntersectionObserverInit): CreateViewportObserverReturnValue;
export type VisibilitySetter<Ctx extends {} = {}> = (entry: IntersectionObserverEntry, context: Ctx & {
visible: boolean;
}) => boolean;
/**
* Creates reactive signal that changes when a single element's visibility changes.
*
* @param options - A Primitive and IntersectionObserver constructor options:
* - `root` — The Element or Document whose bounds are used as the bounding box when testing for intersection.
* - `rootMargin` — A string which specifies a set of offsets to add to the root's bounding_box when calculating intersections, effectively shrinking or growing the root for calculation purposes.
* - `threshold` — Either a single number or an array of numbers between 0.0 and 1.0, specifying a ratio of intersection area to total bounding box area for the observed target.
* - `initialValue` — Initial value of the signal *(default: false)*
*
* @returns A configured *"use"* function for creating a visibility signal for a single element. The passed element can be a **reactive signal** or a DOM element. Returning a falsy value will remove the element from the observer.
* ```ts
* (element: Accessor<Element | FalsyValue> | Element) => Accessor<boolean>
* ```
*
* @example
* ```tsx
* let el: HTMLDivElement | undefined
* const useVisibilityObserver = createVisibilityObserver({ threshold: 0.8 })
* const visible = useVisibilityObserver(() => el)
* <div ref={el}>{ visible() ? "Visible" : "Hidden" }</div>
* ```
*/
export declare function createVisibilityObserver(options?: IntersectionObserverInit & {
initialValue?: boolean;
}, setter?: MaybeAccessor<VisibilitySetter>): (element: Accessor<Element | FalsyValue> | Element) => Accessor<boolean>;
export declare enum Occurrence {
Entering = "Entering",
Leaving = "Leaving",
Inside = "Inside",
Outside = "Outside"
}
/**
* Calculates the occurrence of an element in the viewport.
*/
export declare function getOccurrence(isIntersecting: boolean, prevIsIntersecting: boolean | undefined): Occurrence;
/**
* A visibility setter factory function. It provides information about element occurrence in the viewport — `"Entering"`, `"Leaving"`, `"Inside"` or `"Outside"`.
* @param setter - A function that sets the occurrence of an element in the viewport.
* @returns A visibility setter function.
* @example
* ```ts
* const useVisibilityObserver = createVisibilityObserver(
* { threshold: 0.8 },
* withOccurrence((entry, { occurrence }) => {
* console.log(occurrence);
* return entry.isIntersecting;
* })
* );
* ```
*/
export declare function withOccurrence<Ctx extends {}>(setter: MaybeAccessor<VisibilitySetter<Ctx & {
occurrence: Occurrence;
}>>): () => VisibilitySetter<Ctx>;
export declare enum DirectionX {
Left = "Left",
Right = "Right",
None = "None"
}
export declare enum DirectionY {
Top = "Top",
Bottom = "Bottom",
None = "None"
}
/**
* Calculates the direction of an element in the viewport. The direction is calculated based on the element's rect, it's previous rect and the `isIntersecting` flag.
* @returns A direction string: `"Left"`, `"Right"`, `"Top"`, `"Bottom"` or `"None"`.
*/
export declare function getDirection(rect: DOMRectReadOnly, prevRect: DOMRectReadOnly | undefined, intersecting: boolean): {
directionX: DirectionX;
directionY: DirectionY;
};
/**
* A visibility setter factory function. It provides information about element direction on the screen — `"Left"`, `"Right"`, `"Top"`, `"Bottom"` or `"None"`.
* @param setter - A function that sets the occurrence of an element in the viewport.
* @returns A visibility setter function.
* @example
* ```ts
* const useVisibilityObserver = createVisibilityObserver(
* { threshold: 0.8 },
* withDirection((entry, { directionY, directionX, visible }) => {
* if (!entry.isIntersecting && directionY === "Top" && visible) {
* return true;
* }
* return entry.isIntersecting;
* })
* );
* ```
*/
export declare function withDirection<Ctx extends {}>(callback: MaybeAccessor<VisibilitySetter<Ctx & {
directionX: DirectionX;
directionY: DirectionY;
}>>): () => VisibilitySetter<Ctx>;