@ariakit/react-core
Version:
Ariakit React core
141 lines (138 loc) • 4.25 kB
JavaScript
"use client";
import {
Role
} from "./QJ4LGO2N.js";
import {
CollectionItem
} from "./Y62RTBST.js";
import {
forwardRef
} from "./VOQWLFSQ.js";
import {
useForceUpdate,
useId,
useMergeRefs
} from "./5GGHRIN3.js";
import {
__objRest,
__spreadProps,
__spreadValues
} from "./3YLGPPWQ.js";
// src/collection/collection-item-offscreen.tsx
import { invariant } from "@ariakit/core/utils/misc";
import { useCallback, useRef, useState } from "react";
import { jsx } from "react/jsx-runtime";
var TagName = "div";
function requestIdleCallback(callback) {
if (typeof window.requestIdleCallback === "function") {
return window.requestIdleCallback(callback);
}
callback();
return 0;
}
function cancelIdleCallback(id) {
if (typeof window.cancelIdleCallback === "function") {
window.cancelIdleCallback(id);
}
}
function useCollectionItemOffscreen(_a) {
var _b = _a, { offscreenBehavior = "active", offscreenRoot } = _b, props = __objRest(_b, ["offscreenBehavior", "offscreenRoot"]);
const id = useId(props.id);
const [updated, forceUpdate] = useForceUpdate();
const forcedUpdatesCountRef = useRef(0);
const [_active, setActive] = useState(offscreenBehavior === "active");
const active = _active || offscreenBehavior === "active";
const observerRef = useRef(null);
const idleCallbackIdRef = useRef(0);
const ref = useCallback(
(element) => {
var _a2;
if (!element || offscreenBehavior === "active") {
cancelIdleCallback(idleCallbackIdRef.current);
(_a2 = observerRef.current) == null ? void 0 : _a2.disconnect();
return;
}
invariant(
offscreenRoot !== void 0,
process.env.NODE_ENV !== "production" && "The offscreenRoot prop must provided."
);
const getOffscreenRoot = () => {
if (!offscreenRoot) return null;
if (typeof offscreenRoot === "function") {
return offscreenRoot(element);
}
if ("current" in offscreenRoot) {
return offscreenRoot.current;
}
return offscreenRoot;
};
const root = getOffscreenRoot();
if (!root) {
forcedUpdatesCountRef.current++;
if (forcedUpdatesCountRef.current > 3) {
throw new Error(
"The offscreenRoot is not available. Please make sure the root element is mounted."
);
}
forceUpdate();
return;
}
if (!observerRef.current || observerRef.current.root !== root) {
observerRef.current = new IntersectionObserver(
([entry]) => {
cancelIdleCallback(idleCallbackIdRef.current);
const isIntersecting = !!(entry == null ? void 0 : entry.isIntersecting);
idleCallbackIdRef.current = requestIdleCallback(() => {
if (!isIntersecting && offscreenBehavior === "lazy") return;
setActive(isIntersecting);
});
},
{ root, rootMargin: "40%" }
);
}
observerRef.current.observe(element);
},
[updated, offscreenBehavior, offscreenRoot]
);
return {
id,
active,
ref,
"data-offscreen": !active || void 0
};
}
var CollectionItem2 = forwardRef(function CollectionItem3(_a) {
var _b = _a, {
offscreenBehavior,
offscreenRoot
} = _b, props = __objRest(_b, [
"offscreenBehavior",
"offscreenRoot"
]);
const _a2 = useCollectionItemOffscreen(__spreadValues({
offscreenBehavior,
offscreenRoot
}, props)), { active, ref } = _a2, rest = __objRest(_a2, ["active", "ref"]);
const allProps = __spreadProps(__spreadValues(__spreadValues({}, rest), props), { ref: useMergeRefs(ref, props.ref) });
if (active) {
return /* @__PURE__ */ jsx(CollectionItem, __spreadValues({}, allProps));
}
const _b2 = allProps, {
store,
shouldRegisterItem,
getItem,
element: element
} = _b2, htmlProps = __objRest(_b2, [
"store",
"shouldRegisterItem",
"getItem",
// @ts-expect-error This prop may come from a collection renderer.
"element"
]);
const Component = Role[TagName];
return /* @__PURE__ */ jsx(Component, __spreadValues({}, htmlProps));
});
export {
useCollectionItemOffscreen,
CollectionItem2 as CollectionItem
};