Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

114 lines
3.4 KiB
TypeScript
Raw Normal View History

2025-08-18 23:19:44 +01:00
import React, { useRef, useEffect } from 'react';
import { Box } from '@mantine/core';
2025-08-18 23:19:44 +01:00
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<T extends DragDropItem> {
items: T[];
Stirling 2.0 (#3928) # Description of Changes <!-- File context for managing files between tools and views Optimisation for large files Updated Split to work with new file system and match Matts stepped design closer --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-07-16 17:53:50 +01:00
selectedItems: number[];
selectionMode: boolean;
isAnimating: boolean;
2025-08-18 23:19:44 +01:00
onReorderPages: (sourcePageNumber: number, targetIndex: number, selectedPages?: number[]) => void;
renderItem: (item: T, index: number, refs: React.MutableRefObject<Map<string, HTMLDivElement>>) => React.ReactNode;
renderSplitMarker?: (item: T, index: number) => React.ReactNode;
}
const DragDropGrid = <T extends DragDropItem>({
items,
selectedItems,
selectionMode,
isAnimating,
2025-08-18 23:19:44 +01:00
onReorderPages,
renderItem,
renderSplitMarker,
}: DragDropGridProps<T>) => {
const itemRefs = useRef<Map<string, HTMLDivElement>>(new Map());
2025-08-18 13:19:20 +01:00
const containerRef = useRef<HTMLDivElement>(null);
2025-08-18 23:19:44 +01:00
// 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
2025-08-18 13:19:20 +01:00
2025-08-18 23:19:44 +01:00
// 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 (
2025-08-18 13:19:20 +01:00
<Box
ref={containerRef}
style={{
2025-08-18 23:19:44 +01:00
// Basic container styles
width: '100%',
height: '100%',
2025-08-18 13:19:20 +01:00
}}
>
<div
style={{
2025-08-18 23:19:44 +01:00
height: `${rowVirtualizer.getTotalSize()}px`,
width: '100%',
2025-08-18 13:19:20 +01:00
position: 'relative',
}}
>
2025-08-18 23:19:44 +01:00
{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);
2025-08-18 13:19:20 +01:00
2025-08-18 23:19:44 +01:00
return (
2025-08-18 13:19:20 +01:00
<div
2025-08-18 23:19:44 +01:00
key={virtualRow.index}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualRow.size}px`,
transform: `translateY(${virtualRow.start}px)`,
}}
2025-08-18 13:19:20 +01:00
>
2025-08-18 23:19:44 +01:00
<div
style={{
display: 'flex',
gap: '1.5rem',
justifyContent: 'flex-start',
height: '100%',
alignItems: 'center',
}}
>
{rowItems.map((item, itemIndex) => {
const actualIndex = startIndex + itemIndex;
return (
<React.Fragment key={item.id}>
{/* Split marker */}
{renderSplitMarker && item.splitBefore && actualIndex > 0 && renderSplitMarker(item, actualIndex)}
{/* Item */}
{renderItem(item, actualIndex, itemRefs)}
</React.Fragment>
);
})}
2025-08-18 13:19:20 +01:00
</div>
</div>
2025-08-18 23:19:44 +01:00
);
})}
</div>
</Box>
);
};
export default DragDropGrid;