@opuu/inview
Version:
Lightweight JavaScript library for viewport detection with debounced callbacks - intersection observer, lazy loading, scroll animations, infinite scroll, element visibility tracking with TypeScript support. Zero dependencies, ~1KB gzipped.
172 lines (171 loc) • 5.14 kB
JavaScript
class h {
/**
* Constructor
*
* Create a new InView instance
*
* @param {InViewConfig | string} config - Configuration object or CSS selector
*
* @example
* new InView(".selector");
*
* @example
* new InView({
* selector: ".selector",
* delay: 1000,
* precision: "low",
* single: true
* });
*/
constructor(e) {
this.items = null, this.paused = !1, this.delay = 0, this.threshold = [], this.single = !1, this.observers = [], this.debounceTimers = /* @__PURE__ */ new WeakMap();
let s = 0.01;
typeof e == "string" ? (this.items = document.querySelectorAll(e), this.delay = 0) : typeof e == "object" && (e.delay && (this.delay = e.delay), e.single && (this.single = e.single), e.precision === "low" ? s = 0.1 : e.precision === "medium" ? s = 0.01 : e.precision === "high" && (s = 1e-3), this.single ? this.items = document.querySelector(e.selector) : this.items = document.querySelectorAll(e.selector));
for (let i = 0; i <= 1; i += s)
this.threshold.push(i);
}
/**
* Debounce function to delay callback execution
*
* @param {Element} element - The element triggering the event
* @param {CallableFunction} callback - The callback to execute
* @param {InViewEvent} event - The event object to pass to callback
*/
debounceCallback(e, s, i) {
const r = this.debounceTimers.get(e);
if (r && clearTimeout(r), this.delay > 0) {
const t = window.setTimeout(() => {
this.debounceTimers.delete(e), s(i);
}, this.delay);
this.debounceTimers.set(e, t);
} else
s(i);
}
/**
* Pause the observer
*
* @returns {InView} - Returns the InView instance
*
* @example
* const inview = new InView(".selector");
* inview.on("enter", (e) => {});
* // pause on specific needs
* inview.pause();
*/
pause() {
return this.paused = !0, this;
}
/**
* Resume the observer
*
* @returns {InView} - Returns the InView instance
*
* @example
* const inview = new InView(".selector");
* inview.on("enter", (e) => {});
* // pause the observer
* inview.pause();
* // resume the observer again
* inview.resume();
*/
resume() {
return this.paused = !1, this;
}
/**
* Set the debounce delay
*
* @param {number} delay - Debounce delay in ms
*
* @returns {InView} - Returns the InView instance
*
* @example
* const inview = new InView(".selector");
* inview.on("enter", (e) => {});
* // set debounce delay to 1000ms
* inview.setDelay(1000);
*/
setDelay(e) {
return this.delay = e, this;
}
/**
* Destroy the observer and clean up all resources
*
* @returns {InView} - Returns the InView instance
*
* @example
* const inview = new InView(".selector");
* inview.on("enter", (e) => {});
* // Clean up when done
* inview.destroy();
*/
destroy() {
if (this.items instanceof Element) {
const e = this.debounceTimers.get(this.items);
e && clearTimeout(e);
} else this.items instanceof NodeList && this.items.forEach((e) => {
const s = this.debounceTimers.get(e);
s && clearTimeout(s);
});
return this.debounceTimers = /* @__PURE__ */ new WeakMap(), this.observers.forEach((e) => {
e.disconnect();
}), this.observers = [], this.paused = !1, this.items = null, this;
}
/**
* Listen for enter or exit events
*
* @param {"enter" | "exit"} event - Event type
* @param {CallableFunction} callback - Callback function
*
* @returns {InView} - Returns the InView instance
*
* @example
* const inview = new InView({...});
* inview.on("enter", (e: InViewEvent) => {
* console.log(e.percentage);
* });
*
* inview.on("exit", (e: InViewEvent) => {
* console.log("exit");
* });
*
* @example
* new InView(".selector").on("enter", (e: InViewEvent) => {
* console.log(e.percentage);
* }).on("exit", (e: InViewEvent) => {
* console.log("exit");
* });
*/
on(e, s) {
if ("IntersectionObserver" in window) {
const i = new IntersectionObserver(
(r) => {
r.forEach((t) => {
if (e === "enter" && t.intersectionRatio > 0 || e === "exit" && t.intersectionRatio === 0) {
const o = {
percentage: t.intersectionRatio * 100,
rootBounds: t.rootBounds,
boundingClientRect: t.boundingClientRect,
intersectionRect: t.intersectionRect,
target: t.target,
time: t.time,
event: e
};
this.paused || this.debounceCallback(t.target, s, o);
}
});
},
{
threshold: this.threshold
}
);
this.items instanceof Element ? i.observe(this.items) : this.items instanceof NodeList ? this.items.forEach((r) => {
i.observe(r);
}) : console.error("InView: No items found."), this.observers.push(i);
} else
console.error("InView: IntersectionObserver not supported.");
return this;
}
}
export {
h as default
};