import { useEffect, useRef, useState } from "react"; import { Memo } from "@/types/proto/api/v1/memo_service"; import { cn } from "@/utils"; interface Props { memoList: Memo[]; renderer: (memo: Memo) => JSX.Element; prefixElement?: JSX.Element; listMode?: boolean; } interface LocalState { columns: number; } const MINIMUM_MEMO_VIEWPORT_WIDTH = 512; const MasonryView = (props: Props) => { const [state, setState] = useState({ columns: 1, }); const containerRef = useRef(null); useEffect(() => { const handleResize = () => { if (!containerRef.current) { return; } if (props.listMode) { setState({ columns: 1, }); return; } const containerWidth = containerRef.current.offsetWidth; const scale = containerWidth / MINIMUM_MEMO_VIEWPORT_WIDTH; setState({ columns: scale >= 2 ? Math.round(scale) : 1, }); }; handleResize(); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, [props.listMode]); return (
{Array.from({ length: state.columns }).map((_, columnIndex) => (
{props.prefixElement && columnIndex === 0 &&
{props.prefixElement}
} {props.memoList.filter((_, index) => index % state.columns === columnIndex).map((memo) => props.renderer(memo))}
))}
); }; export default MasonryView;