import React, { useRef, useEffect } from 'react'; import { Box } from '@mantine/core'; import { useVirtualizer } from '@tanstack/react-virtual'; import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; import styles from './PageEditor.module.css'; interface DragDropItem { id: string; splitBefore?: boolean; } interface DragDropGridProps { items: T[]; selectedItems: number[]; selectionMode: boolean; isAnimating: boolean; onReorderPages: (sourcePageNumber: number, targetIndex: number, selectedPages?: number[]) => void; renderItem: (item: T, index: number, refs: React.MutableRefObject>) => React.ReactNode; renderSplitMarker?: (item: T, index: number) => React.ReactNode; } const DragDropGrid = ({ items, selectedItems, selectionMode, isAnimating, onReorderPages, renderItem, renderSplitMarker, }: DragDropGridProps) => { const itemRefs = useRef>(new Map()); const containerRef = useRef(null); // Grid configuration const ITEMS_PER_ROW = 4; const ITEM_HEIGHT = 340; // 20rem + gap const OVERSCAN = items.length > 1000 ? 8 : 4; // More overscan for large documents // Virtualization with react-virtual library const rowVirtualizer = useVirtualizer({ count: Math.ceil(items.length / ITEMS_PER_ROW), getScrollElement: () => containerRef.current?.closest('[data-scrolling-container]') as Element, estimateSize: () => ITEM_HEIGHT, overscan: OVERSCAN, }); return (
{rowVirtualizer.getVirtualItems().map((virtualRow) => { const startIndex = virtualRow.index * ITEMS_PER_ROW; const endIndex = Math.min(startIndex + ITEMS_PER_ROW, items.length); const rowItems = items.slice(startIndex, endIndex); return (
{rowItems.map((item, itemIndex) => { const actualIndex = startIndex + itemIndex; return ( {/* Split marker */} {renderSplitMarker && item.splitBefore && actualIndex > 0 && renderSplitMarker(item, actualIndex)} {/* Item */} {renderItem(item, actualIndex, itemRefs)} ); })}
); })}
); }; export default DragDropGrid;