import { memo, useMemo } from 'react'; import { View, StyleSheet, type ViewStyle } from 'react-native'; type WaterfallItem = { w: number; h: number; data: any; }; type WaterfallProps = { items: WaterfallItem[]; column?: number; itemPadding?: number; renderItem: (item: T, width: number, height: number) => React.ReactNode; containerWidth: number; }; function WaterfallComponent({ items, column = 2, itemPadding = 8, renderItem, containerWidth, }: WaterfallProps) { const layout = useMemo(() => { const columns: { h: number; items: Array }[] = Array.from({ length: column }, () => ({ h: 0, items: [] })); const itemWidth = (containerWidth - itemPadding * (column - 1)) / column; items.forEach((item) => { const minColumn = columns.reduce((min, col, idx) => col.h < columns[min].h ? idx : min, 0); const col = columns[minColumn]; const layoutItem = { ...item, x: minColumn * (itemWidth + itemPadding), y: col.h > 0 ? col.h + itemPadding : 0, w: itemWidth, }; col.h = layoutItem.y + item.h + 40; col.items.push(layoutItem); }); const maxHeight = Math.max(...columns.map(col => col.h)); const allItems = columns.flatMap(col => col.items); return { items: allItems, height: maxHeight }; }, [items, column, itemPadding, containerWidth]); return ( {layout.items.map((item, index) => ( {renderItem(item.data, item.w, item.h)} ))} ); } const styles = StyleSheet.create({ container: { position: 'relative', width: '100%', }, item: { overflow: 'hidden', }, }); export const Waterfall = memo(WaterfallComponent) as typeof WaterfallComponent;