import { useMemo } from 'react'; export type LayoutItem = { item: T; x: number; y: number; width: number; height: number; }; export type MasonryLayout = { items: LayoutItem[]; totalHeight: number; }; export function useMasonryLayout( data: T[], numColumns: number, containerWidth: number, getItemHeight: (item: T, width: number) => number | undefined, gap: number, estimatedHeight: number ): MasonryLayout { return useMemo(() => { if (containerWidth <= 0 || data.length === 0) { return { items: [], totalHeight: 0 }; } const columnHeights = Array(numColumns).fill(0); const columnWidth = (containerWidth - gap * (numColumns - 1)) / numColumns; const layoutItems = data.map((item) => { const shortestColumnIndex = columnHeights.indexOf(Math.min(...columnHeights)); const x = shortestColumnIndex * (columnWidth + gap); const y = columnHeights[shortestColumnIndex]; const height = getItemHeight(item, columnWidth) ?? estimatedHeight; columnHeights[shortestColumnIndex] = y + height + gap; return { item, x, y, width: columnWidth, height }; }); const totalHeight = Math.max(...columnHeights) - gap; return { items: layoutItems, totalHeight: Math.max(0, totalHeight) }; }, [data, numColumns, containerWidth, getItemHeight, gap, estimatedHeight]); }