add grid item card size presets

This commit is contained in:
jeffvli
2025-12-23 21:59:52 -08:00
parent cf06d69822
commit 51587fbb6b
23 changed files with 167 additions and 5 deletions
@@ -135,6 +135,7 @@ export interface ItemCardDerivativeProps extends Omit<ItemCardProps, 'type'> {
const CompactItemCard = ({
controls,
data,
enableDrag,
enableExpansion,
enableNavigation,
internalState,
@@ -150,6 +151,53 @@ const CompactItemCard = ({
: undefined;
const isSelected = useItemSelectionState(internalState, itemRowId || undefined);
const { isDragging: isDraggingLocal, ref } = useDragDrop<HTMLDivElement>({
drag: {
getId: () => {
if (!data) {
return [];
}
const draggedItems = getDraggedItems(data, internalState);
return draggedItems.map((item) => item.id);
},
getItem: () => {
if (!data) {
return [];
}
const draggedItems = getDraggedItems(data, internalState);
return draggedItems;
},
itemType,
onDragStart: () => {
if (!data) {
return;
}
const draggedItems = getDraggedItems(data, internalState);
if (internalState) {
internalState.setDragging(draggedItems);
}
},
onDrop: () => {
if (internalState) {
internalState.setDragging([]);
}
},
operation:
itemType === LibraryItem.QUEUE_SONG
? [DragOperation.REORDER, DragOperation.ADD]
: [DragOperation.ADD],
target: DragTarget.ALBUM,
},
isEnabled: !!enableDrag && !!data,
});
const itemId = data && internalState ? data.id : undefined;
const isDraggingState = useItemDraggingState(internalState, itemId);
const isDragging = isDraggingState || isDraggingLocal;
const handleClick = useDoubleClick({
onDoubleClick: (e: React.MouseEvent<HTMLDivElement>) => {
if (!data || !controls || !internalState) {
@@ -289,8 +337,10 @@ const CompactItemCard = ({
return (
<div
className={clsx(styles.container, styles.compact, {
[styles.dragging]: isDragging,
[styles.selected]: isSelected,
})}
ref={ref}
>
{enableNavigation && navigationPath && !internalState ? (
<Link
@@ -68,6 +68,7 @@ interface VirtualizedGridListProps {
outerRef: RefObject<any>;
ref: RefObject<FixedSizeList<GridItemProps> | null>;
rows?: ItemCardProps['rows'];
size?: 'compact' | 'default' | 'large';
tableMetaRef: RefObject<null | {
columnCount: number;
itemHeight: number;
@@ -95,6 +96,7 @@ const VirtualizedGridList = React.memo(
outerRef,
ref,
rows,
size,
tableMetaRef,
width,
}: VirtualizedGridListProps) => {
@@ -113,6 +115,7 @@ const VirtualizedGridList = React.memo(
internalState,
itemType,
rows,
size,
tableMeta,
};
}, [
@@ -126,6 +129,7 @@ const VirtualizedGridList = React.memo(
gap,
internalState,
itemType,
size,
]);
const handleOnScroll = useCallback(
@@ -215,7 +219,11 @@ const VirtualizedGridList = React.memo(
VirtualizedGridList.displayName = 'VirtualizedGridList';
const createThrottledSetTableMeta = (itemsPerRow?: number, rowsCount?: number) => {
const createThrottledSetTableMeta = (
itemsPerRow?: number,
rowsCount?: number,
size?: 'compact' | 'default' | 'large',
) => {
return throttle((width: number, dataLength: number, setTableMeta: (meta: any) => void) => {
const isSm = width >= 600;
const isMd = width >= 768;
@@ -245,10 +253,22 @@ const createThrottledSetTableMeta = (itemsPerRow?: number, rowsCount?: number) =
dynamicItemsPerRow = 2;
}
if (size === 'large') {
dynamicItemsPerRow = Math.round(dynamicItemsPerRow * 0.75);
if (dynamicItemsPerRow < 1) {
dynamicItemsPerRow = 1;
}
}
const setItemsPerRow = itemsPerRow || dynamicItemsPerRow;
const widthPerItem = Number(width) / setItemsPerRow;
const itemHeight = widthPerItem + (rowsCount || getDataRowsCount()) * 26;
// For compact size, don't include text lines in height calculation
// CompactItemCard has a different layout that doesn't need the extra space
const itemHeight =
size === 'compact'
? widthPerItem
: widthPerItem + (rowsCount || getDataRowsCount()) * 26;
if (widthPerItem === 0) {
return;
@@ -273,6 +293,7 @@ export interface GridItemProps {
internalState: ItemListStateActions;
itemType: LibraryItem;
rows?: ItemCardProps['rows'];
size?: 'compact' | 'default' | 'large';
tableMeta: null | {
columnCount: number;
itemHeight: number;
@@ -301,6 +322,7 @@ export interface ItemGridListProps {
overrideControls?: Partial<ItemControls>;
ref?: Ref<ItemListHandle>;
rows?: ItemCardProps['rows'];
size?: 'compact' | 'default' | 'large';
}
const BaseItemGridList = ({
@@ -320,6 +342,7 @@ const BaseItemGridList = ({
overrideControls,
ref,
rows,
size = 'default',
}: ItemGridListProps) => {
const rootRef = useRef(null);
const outerRef = useRef(null);
@@ -410,8 +433,8 @@ const BaseItemGridList = ({
}, [osInstance]);
const throttledSetTableMeta = useMemo(() => {
return createThrottledSetTableMeta(itemsPerRow, rows?.length);
}, [itemsPerRow, rows?.length]);
return createThrottledSetTableMeta(itemsPerRow, rows?.length, size);
}, [itemsPerRow, rows?.length, size]);
useLayoutEffect(() => {
const { current: container } = containerRef;
@@ -738,6 +761,7 @@ const BaseItemGridList = ({
outerRef={outerRef}
ref={listRef}
rows={rows}
size={size}
tableMetaRef={tableMetaRef}
width={width}
/>
@@ -753,7 +777,7 @@ const BaseItemGridList = ({
const ListComponent = memo((props: ListChildComponentProps<GridItemProps>) => {
const { index, style } = props;
const { columns, controls, data, enableDrag, gap, itemType, rows } = props.data;
const { columns, controls, data, enableDrag, gap, itemType, rows, size } = props.data;
const items: ReactNode[] = [];
const itemCount = data.length;
@@ -784,6 +808,7 @@ const ListComponent = memo((props: ListChildComponentProps<GridItemProps>) => {
internalState={props.data.internalState}
itemType={itemType}
rows={rows}
type={size === 'compact' ? 'compact' : 'poster'}
withControls
/>
</div>,
@@ -66,6 +66,7 @@ export interface ItemListComponentProps<TQuery> {
export interface ItemListGridComponentProps<TQuery> extends ItemListComponentProps<TQuery> {
gap?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';
itemsPerRow?: number;
size?: 'compact' | 'default' | 'large';
}
export interface ItemListHandle {