drab
Version:
Interactivity for You
65 lines (64 loc) • 2.23 kB
JavaScript
import { Base } from "../base/index.js";
/**
* Uses the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to add a `data-intersect` attribute to `content` when the `trigger` is intersecting.
*
* Use `onIntersect` and `onExit` to customize further with JavaScript.
*
* `threshold`
*
* Specify a `threshold` between `0` and `1` to determine how much of the `trigger` should be visible for the intersection to occur.
*/
export class Intersect extends Base {
/** Functions to run when the `trigger` intersects. */
#intersectCallbacks = [];
/** Functions to run when the `trigger` exits. */
#exitCallbacks = [];
constructor() {
super();
}
/**
* How much of the `trigger` should be visible for the intersection to occur. For example, given a threshold of `.5`, the intersection would occur when the `trigger` is 50% visible.
*
* @default 0
*/
get #threshold() {
return Number(this.getAttribute("threshold") ?? 0);
}
/**
* @param callback Runs when `trigger` intersects.
*/
onIntersect(callback) {
this.#intersectCallbacks.push(callback);
}
/**
* @param callback Runs when `trigger` exits.
*/
onExit(callback) {
this.#exitCallbacks.push(callback);
}
mount() {
const observer = new IntersectionObserver((entries) => {
/** Attribute to add or remove from `content`. */
const attr = "data-intersect";
for (const entry of entries) {
if (entry.isIntersecting) {
this.getContent().setAttribute(attr, "");
for (const callback of this.#intersectCallbacks) {
callback();
}
}
else {
this.getContent().removeAttribute(attr);
for (const callback of this.#exitCallbacks) {
callback();
}
}
}
}, {
threshold: this.#threshold,
});
for (const trigger of this.getTrigger()) {
observer.observe(trigger);
}
}
}