refactor item grid to resolve overlayscrollbars

This commit is contained in:
jeffvli
2025-11-10 21:33:30 -08:00
parent 6541a6d583
commit 4360906883
@@ -50,6 +50,7 @@ interface VirtualizedGridListProps {
enableExpansion: boolean; enableExpansion: boolean;
enableSelection: boolean; enableSelection: boolean;
gap: 'lg' | 'md' | 'sm' | 'xl' | 'xs'; gap: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
height: number;
initialTop?: ItemGridListProps['initialTop']; initialTop?: ItemGridListProps['initialTop'];
internalState: ItemListStateActions; internalState: ItemListStateActions;
itemType: LibraryItem; itemType: LibraryItem;
@@ -63,6 +64,7 @@ interface VirtualizedGridListProps {
itemHeight: number; itemHeight: number;
rowCount: number; rowCount: number;
}; };
width: number;
} }
const VirtualizedGridList = React.memo( const VirtualizedGridList = React.memo(
@@ -73,6 +75,7 @@ const VirtualizedGridList = React.memo(
enableExpansion, enableExpansion,
enableSelection, enableSelection,
gap, gap,
height,
initialTop, initialTop,
internalState, internalState,
itemType, itemType,
@@ -82,6 +85,7 @@ const VirtualizedGridList = React.memo(
outerRef, outerRef,
ref, ref,
tableMeta, tableMeta,
width,
}: VirtualizedGridListProps) => { }: VirtualizedGridListProps) => {
const itemData: GridItemProps = useMemo(() => { const itemData: GridItemProps = useMemo(() => {
return { return {
@@ -146,28 +150,20 @@ const VirtualizedGridList = React.memo(
} }
return ( return (
<div className={styles.autoSizerContainer}> <FixedSizeList
<AutoSizer> height={height}
{({ height, width }) => { initialScrollOffset={initialTop || 0}
return ( itemCount={itemData.tableMeta?.rowCount || 0}
<FixedSizeList itemData={itemData}
height={height} itemSize={itemData.tableMeta?.itemHeight || 0}
initialScrollOffset={initialTop || 0} onItemsRendered={debouncedOnItemsRendered}
itemCount={itemData.tableMeta?.rowCount || 0} onScroll={handleOnScroll}
itemData={itemData} outerRef={outerRef}
itemSize={itemData.tableMeta?.itemHeight || 0} ref={ref}
onItemsRendered={debouncedOnItemsRendered} width={width}
onScroll={handleOnScroll} >
outerRef={outerRef} {ListComponent}
ref={ref} </FixedSizeList>
width={width}
>
{ListComponent}
</FixedSizeList>
);
}}
</AutoSizer>
</div>
); );
}, },
); );
@@ -311,6 +307,14 @@ export const ItemGridList = ({
}, },
}); });
const hasExpanded = internalState.hasExpanded();
const [tableMeta, setTableMeta] = useState<null | {
columnCount: number;
itemHeight: number;
rowCount: number;
}>(null);
useEffect(() => { useEffect(() => {
const { current: root } = rootRef; const { current: root } = rootRef;
const { current: outer } = outerRef; const { current: outer } = outerRef;
@@ -323,15 +327,7 @@ export const ItemGridList = ({
target: root, target: root,
}); });
} }
}, [initialize]); }, [initialize, tableMeta]);
const hasExpanded = internalState.hasExpanded();
const [tableMeta, setTableMeta] = useState<null | {
columnCount: number;
itemHeight: number;
rowCount: number;
}>(null);
const throttledSetTableMeta = useMemo(() => { const throttledSetTableMeta = useMemo(() => {
return createThrottledSetTableMeta(itemsPerRow); return createThrottledSetTableMeta(itemsPerRow);
@@ -377,7 +373,11 @@ export const ItemGridList = ({
if (selected.length > 0) { if (selected.length > 0) {
const lastSelected = selected[selected.length - 1]; const lastSelected = selected[selected.length - 1];
currentIndex = data.findIndex( currentIndex = data.findIndex(
(d: any) => d && typeof d === 'object' && 'id' in d && d.id === lastSelected.id, (d: any) =>
d &&
typeof d === 'object' &&
'id' in d &&
d.id === (lastSelected as any).id,
); );
} }
@@ -476,7 +476,10 @@ export const ItemGridList = ({
// Find the indices of the last selected item and new item // Find the indices of the last selected item and new item
const lastIndex = data.findIndex( const lastIndex = data.findIndex(
(d: any) => (d: any) =>
d && typeof d === 'object' && 'id' in d && d.id === lastSelectedItem.id, d &&
typeof d === 'object' &&
'id' in d &&
d.id === (lastSelectedItem as any).id,
); );
if (lastIndex !== -1 && newIndex !== -1) { if (lastIndex !== -1 && newIndex !== -1) {
@@ -505,7 +508,9 @@ export const ItemGridList = ({
const currentSelected = internalState.getSelected(); const currentSelected = internalState.getSelected();
const newSelected = [...currentSelected]; const newSelected = [...currentSelected];
rangeItems.forEach((rangeItem) => { rangeItems.forEach((rangeItem) => {
if (!newSelected.some((selected) => selected.id === rangeItem.id)) { if (
!newSelected.some((selected: any) => selected.id === rangeItem.id)
) {
newSelected.push(rangeItem); newSelected.push(rangeItem);
} }
}); });
@@ -518,11 +523,11 @@ export const ItemGridList = ({
}; };
// Remove the new item from its current position if it exists // Remove the new item from its current position if it exists
const filteredSelected = newSelected.filter( const filteredSelected = newSelected.filter(
(item) => item.id !== newItemListItem.id, (item: any) => item.id !== newItemListItem.id,
); );
// Add it at the end so it becomes the last selected item // Add it at the end so it becomes the last selected item
filteredSelected.push(newItemListItem); filteredSelected.push(newItemListItem);
internalState.setSelected(filteredSelected); internalState.setSelected(filteredSelected as any);
} }
} else { } else {
// No previous selection, just select the new item // No previous selection, just select the new item
@@ -586,23 +591,29 @@ export const ItemGridList = ({
ref={mergedContainerRef} ref={mergedContainerRef}
tabIndex={0} tabIndex={0}
> >
<VirtualizedGridList <AutoSizer>
controls={controls} {({ height, width }) => (
data={data} <VirtualizedGridList
enableDrag={enableDrag} controls={controls}
enableExpansion={enableExpansion} data={data}
enableSelection={enableSelection} enableDrag={enableDrag}
gap={gap} enableExpansion={enableExpansion}
initialTop={initialTop} enableSelection={enableSelection}
internalState={internalState} gap={gap}
itemType={itemType} height={height}
onRangeChanged={onRangeChanged} initialTop={initialTop}
onScroll={onScroll ?? (() => {})} internalState={internalState}
onScrollEnd={onScrollEnd ?? (() => {})} itemType={itemType}
outerRef={outerRef} onRangeChanged={onRangeChanged}
ref={listRef} onScroll={onScroll ?? (() => {})}
tableMeta={tableMeta} onScrollEnd={onScrollEnd ?? (() => {})}
/> outerRef={outerRef}
ref={listRef}
tableMeta={tableMeta}
width={width}
/>
)}
</AutoSizer>
<AnimatePresence> <AnimatePresence>
{hasExpanded && ( {hasExpanded && (
<ExpandedListContainer> <ExpandedListContainer>