import { useEffect, useRef, useState } from 'react' import type { BackendArt } from '../../functions/BackendTypes' import { useScrollRoot } from '../../functions/Context' import { routeIntercept } from '../../functions/Route' import { CDN_BASE } from '../../functions/Backend' import './styles/LayoutBrowser.css' interface PropsForLayoutBrowser { items: BackendArt[] position: number onEndReached?: () => void } export interface RecoverForLayoutBrowser { position: number items: BackendArt[] } export default function LayoutBrowser({ items, position, onEndReached }: PropsForLayoutBrowser) { const [columnCount, setColumnCount] = useState(3) const containerRef = useRef(null) const scrollRoot = useScrollRoot() const didRestore = useRef(false) // Endless Scrolling useEffect(() => { if (!onEndReached || !scrollRoot) return const onScroll = () => { const { scrollTop, scrollHeight, clientHeight } = scrollRoot if (scrollTop + clientHeight >= scrollHeight - 100) { onEndReached() } } scrollRoot.addEventListener('scroll', onScroll) return () => scrollRoot.removeEventListener('scroll', onScroll) }, [onEndReached, scrollRoot]) // Restore Scrolling useEffect(() => { if (!scrollRoot || didRestore.current) return // avoid race conditions const raf = requestAnimationFrame(() => { scrollRoot.scrollTo({ top: position }) didRestore.current = true }) return () => { cancelAnimationFrame(raf) } }, [scrollRoot, position, items]) // Calculate Column Count useEffect(() => { const el = containerRef.current if (!el) return const ro = new ResizeObserver(([entry]) => { setColumnCount(Math.max(1, Math.floor(entry.contentRect.width / 160))) }) ro.observe(el) return () => ro.disconnect() }, []) const columns: BackendArt[][] = Array.from({ length: columnCount }, () => []) items.forEach((item, i) => columns[i % columnCount].push(item)) return (
{columns.map((column, columnIdx) => (
{column.map((item, itemIdx) => { const animationOrder = Math.min(columnIdx + itemIdx * columnCount, 25) const animationDelay = `calc(${animationOrder} * var(--animation-step-delay))` return ( routeIntercept(e, item, { position: scrollRoot?.scrollTop ?? 0, items: items, } as RecoverForLayoutBrowser) }>
{item.title}
) })}
))}
) }