UNPKG

@ariakit/react-core

Version:

Ariakit React core

141 lines (138 loc) 4.25 kB
"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 };