UNPKG

virtua-restoration

Version:

<img src="./virtua-restoration.png" alt="Virtua Restoration" style="max-width: 1000px; width: 100%; display: block; margin: 0 auto 20px auto;">

82 lines (78 loc) 2.88 kB
// src/components/VirtualizedList.tsx import { useLayoutEffect, useMemo, useRef } from "react"; import { VList } from "virtua"; // src/components/getCacheProvider.tsx function getCacheProvider(cacheKey, cacheSource = "sessionStorage", customProvider) { if (cacheSource === "custom" && customProvider) return customProvider; const storage = cacheSource === "localStorage" ? window.localStorage : window.sessionStorage; return { get: () => { const serialized = storage.getItem(cacheKey); if (!serialized) return void 0; try { return JSON.parse(serialized); } catch (e) { console.error("Error parsing storage cache:", e); return void 0; } }, set: (data) => { storage.setItem(cacheKey, JSON.stringify(data)); } }; } // src/components/VirtualizedList.tsx import { jsx } from "react/jsx-runtime"; var VirtualizedList = ({ cacheKey, children, cacheSourceType = "sessionStorage", customProvider, className, style }) => { const ref = useRef(null); const provider = useMemo(() => getCacheProvider(cacheKey, cacheSourceType, customProvider), [cacheKey, cacheSourceType, customProvider]); const [offset, cache] = useMemo(() => { return provider?.get() ?? []; }, [provider]); useLayoutEffect(() => { if (!ref.current) return; const handle = ref.current; if (offset) { handle.scrollTo(offset); } return () => { if (provider) { provider.set([handle.scrollOffset, handle.cache]); } }; }, [offset, provider]); return /* @__PURE__ */ jsx(VList, { ref, cache, className, style: style ?? { height: "100vh", overflow: "auto" }, children }); }; // src/components/WindowVirtualized.tsx import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo2, useRef as useRef2 } from "react"; import { WindowVirtualizer } from "virtua"; import { jsx as jsx2 } from "react/jsx-runtime"; var WindowVirtualizedList = ({ cacheKey, children, cacheSourceType = "sessionStorage", customProvider }) => { const ref = useRef2(null); const provider = useMemo2(() => getCacheProvider(cacheKey, cacheSourceType, customProvider), [cacheKey, cacheSourceType, customProvider]); const [offset, cache] = useMemo2(() => { return provider?.get() ?? []; }, [provider]); useLayoutEffect2(() => { if (!ref.current) return; const handle = ref.current; window.scrollTo(0, offset ?? 0); let scrollY = 0; const onScroll = () => { scrollY = window.scrollY; }; window.addEventListener("scroll", onScroll); onScroll(); return () => { window.removeEventListener("scroll", onScroll); if (provider) { provider.set([scrollY, handle.cache]); } }; }, [offset, provider]); return /* @__PURE__ */ jsx2(WindowVirtualizer, { ref, cache, children }); }; export { VirtualizedList, WindowVirtualizedList };