@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
90 lines (87 loc) • 2.69 kB
JavaScript
import { useLatest } from '@liveblocks/react/_private';
import { useEffect, useState } from 'react';
let optionlessIntersectionObserver;
const optionlessIntersectionCallbacks = /* @__PURE__ */ new WeakMap();
const individualIntersectionObservers = /* @__PURE__ */ new WeakMap();
function observe(element, callback, options) {
if (!options) {
if (!optionlessIntersectionObserver) {
optionlessIntersectionObserver = new IntersectionObserver((entries) => {
for (const entry of entries) {
const callback2 = optionlessIntersectionCallbacks.get(entry.target);
callback2?.(entry);
}
});
}
optionlessIntersectionCallbacks.set(element, callback);
optionlessIntersectionObserver.observe(element);
} else {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
callback?.(entry);
}
},
{
root: options.root?.current,
rootMargin: typeof options.rootMargin === "number" ? `${options.rootMargin}px` : options.rootMargin,
threshold: options.threshold
}
);
individualIntersectionObservers.set(element, observer);
observer.observe(element);
}
}
function unobserve(element, options) {
if (!options) {
optionlessIntersectionCallbacks.delete(element);
optionlessIntersectionObserver?.unobserve(element);
} else {
const observer = individualIntersectionObservers.get(element);
observer?.unobserve(element);
individualIntersectionObservers.delete(element);
}
}
function useIntersectionCallback(ref, callback, options) {
const enabled = options?.enabled ?? true;
const latestCallback = useLatest(callback);
const { root, rootMargin, threshold } = options ?? {};
useEffect(() => {
const element = ref.current;
if (!element) {
return;
}
const observeOptions = {
root,
rootMargin,
threshold
};
if (enabled) {
observe(
element,
(entry) => {
latestCallback.current(entry.isIntersecting, entry);
},
observeOptions
);
} else {
unobserve(element, observeOptions);
}
return () => {
unobserve(element, observeOptions);
};
}, [ref, enabled, latestCallback, root, rootMargin, threshold]);
}
function useVisible(ref, options) {
const [isVisible, setVisible] = useState(
options?.initialValue !== void 0 ? options.initialValue : false
);
useIntersectionCallback(
ref,
(isIntersecting) => setVisible(isIntersecting),
options
);
return isVisible;
}
export { useIntersectionCallback, useVisible };
//# sourceMappingURL=use-visible.js.map