Skip to content

Commit 30eada0

Browse files
committed
feat(FileOrganizer): grid size based on first item, not hard-coded
1 parent 3d04a97 commit 30eada0

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

src/components/FileOrganizer/FileOrganizer.tsx

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,20 @@ export function FileOrganizer<F extends ObjectWithId>({
143143

144144
const [draggingId, setDraggingId] = useState<string>();
145145

146+
// Detect size of first item and use as size throughout.
147+
const [size, setSize] = useState({ width: THUMBNAIL_WIDTH, height: THUMBNAIL_WIDTH });
148+
const hasFiles = files.length > 0;
149+
useEffect(() => {
150+
if (!fileOrganizerRef.current) return;
151+
const firstItem = fileOrganizerRef.current.querySelector('div[draggable="true"]');
152+
if (!firstItem) return;
153+
const { width, height } = firstItem.getBoundingClientRect();
154+
setSize(prev => {
155+
if (prev.width === width && prev.height === height) return prev;
156+
return { width, height };
157+
});
158+
}, [hasFiles]);
159+
146160
const handleOnDragChange = useCallback(
147161
(id?: string) => {
148162
onDragChange?.(id);
@@ -151,18 +165,23 @@ export function FileOrganizer<F extends ObjectWithId>({
151165
[onDragChange],
152166
);
153167

154-
// Detect all shown items and set as array of IDs to notify onRenderThumbnail.
155-
// Set to null if all IDs are shown (no virtualization).
168+
// Whenever files changes, detect which items are in view and prevent
169+
// throttling. Set as array of IDs to notify onRenderThumbnail.
156170
const [initialShownIds, setInitialShownIds] = useState<string[]>([]);
157171
useEffect(() => {
158-
requestAnimationFrame(() => {
159-
if (!fileOrganizerRef.current) return;
160-
const itemsInView = fileOrganizerRef.current.querySelectorAll('div[draggable="true"]');
161-
const ids: string[] = [];
162-
itemsInView.forEach(draggableItem => ids.push(draggableItem.id));
163-
setInitialShownIds(ids);
164-
});
165-
}, []);
172+
if (files) {
173+
requestAnimationFrame(() => {
174+
if (!fileOrganizerRef.current) return;
175+
const itemsInView = fileOrganizerRef.current.querySelectorAll('div[draggable="true"]');
176+
const ids: string[] = [];
177+
itemsInView.forEach(draggableItem => {
178+
const dataFileId = draggableItem.getAttribute('data-file-id');
179+
if (dataFileId) ids.push(dataFileId);
180+
});
181+
setInitialShownIds(ids);
182+
});
183+
}
184+
}, [files]);
166185

167186
const handleItemKeyDown = useCallback(
168187
(event: KeyboardEvent<HTMLDivElement>, index: number, _file: F, draggableRef: RefObject<HTMLDivElement>) => {
@@ -202,8 +221,8 @@ export function FileOrganizer<F extends ObjectWithId>({
202221
const isInDragGroup = draggingIds?.includes(file.id) ?? false;
203222
return (
204223
<Draggable
224+
data-file-id={file.id}
205225
key={file.id}
206-
id={file.id}
207226
index={index}
208227
style={
209228
style && {
@@ -294,6 +313,7 @@ export function FileOrganizer<F extends ObjectWithId>({
294313
ref={gridRef}
295314
files={files}
296315
padding={pad}
316+
size={size}
297317
renderItem={renderItem}
298318
onColumnCountChange={setColumnCount}
299319
/>

src/components/FileOrganizer/MemoAutoSizer.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React, { forwardRef, memo, useCallback, useEffect, useMemo } from 'react';
22
import AutoSizer, { Size } from 'react-virtualized-auto-sizer';
33
import { FixedSizeGrid as Grid, GridChildComponentProps } from 'react-window';
4-
import { getItemIndex, ObjectWithId, THUMBNAIL_WIDTH } from '../../utils';
4+
import { getItemIndex, ObjectWithId } from '../../utils';
55

66
interface VirtualizedProps {
77
files: ObjectWithId[];
88
padding: number;
9+
size: { width: number; height: number };
910
onColumnCountChange: (newColumnCount: number) => void;
1011
renderItem: (file: any, index: number, style: React.CSSProperties | undefined) => JSX.Element; // eslint-disable-line @typescript-eslint/no-explicit-any
1112
}
@@ -19,15 +20,15 @@ const MemoGridItem = memo<GridChildComponentProps>(({ columnIndex, rowIndex, sty
1920

2021
const MemoGrid = memo(
2122
forwardRef<Grid, Size & VirtualizedProps>(
22-
({ width, height, files, padding, renderItem, onColumnCountChange }, ref) => {
23+
({ width, height, files, padding, renderItem, onColumnCountChange, size }, ref) => {
2324
const modifiedHeight = height - 2 * padding;
2425
const modifiedWidth = width - 2 * padding;
2526

2627
const data = useMemo(() => {
27-
let columnCount = Math.floor(modifiedWidth / THUMBNAIL_WIDTH);
28+
let columnCount = Math.floor(modifiedWidth / size.width);
2829
if (columnCount > files.length) columnCount = files.length;
2930
return { files, renderItem, columnCount };
30-
}, [files, renderItem, modifiedWidth]);
31+
}, [modifiedWidth, size.width, files, renderItem]);
3132

3233
useEffect(() => {
3334
onColumnCountChange(data.columnCount);
@@ -36,8 +37,8 @@ const MemoGrid = memo(
3637
return (
3738
<Grid
3839
ref={ref}
39-
columnWidth={THUMBNAIL_WIDTH}
40-
rowHeight={THUMBNAIL_WIDTH}
40+
columnWidth={size.width}
41+
rowHeight={size.height}
4142
height={modifiedHeight}
4243
width={modifiedWidth}
4344
style={{ padding, height, width }}
@@ -57,7 +58,7 @@ const MemoGrid = memo(
5758
);
5859

5960
export const MemoAutoSizer = memo(
60-
forwardRef<Grid, VirtualizedProps>(({ files, padding, renderItem, onColumnCountChange }, ref) => {
61+
forwardRef<Grid, VirtualizedProps>(({ files, padding, size, renderItem, onColumnCountChange }, ref) => {
6162
const onRenderGrid = useCallback(
6263
({ width, height }: Size) => (
6364
<MemoGrid
@@ -66,11 +67,12 @@ export const MemoAutoSizer = memo(
6667
width={width}
6768
height={height}
6869
files={files}
70+
size={size}
6971
renderItem={renderItem}
7072
onColumnCountChange={onColumnCountChange}
7173
/>
7274
),
73-
[files, padding, renderItem, ref, onColumnCountChange],
75+
[padding, ref, files, size, renderItem, onColumnCountChange],
7476
);
7577

7678
return <AutoSizer>{onRenderGrid}</AutoSizer>;

0 commit comments

Comments
 (0)