refactor(doclist): centralize icons grid layout logic into reusable utility
Move grid style and template calculation for icon views into a shared iconsGrid.ts utility. Replace inline grid logic in IconsView and DocumentListSkeleton with calls to the new iconsGridStyle function for consistency and maintainability.
This commit is contained in:
parent
e4b0c8358e
commit
eea143abbf
3 changed files with 35 additions and 37 deletions
|
|
@ -1,24 +1,20 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { IconSize, ViewMode } from '@/types/documents';
|
import type { IconSize, ViewMode } from '@/types/documents';
|
||||||
|
import { iconsGridStyle } from '@/components/doclist/views/iconsGrid';
|
||||||
|
|
||||||
interface DocumentListSkeletonProps {
|
interface DocumentListSkeletonProps {
|
||||||
viewMode?: ViewMode;
|
viewMode?: ViewMode;
|
||||||
iconSize?: IconSize;
|
iconSize?: IconSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ICON_COLS: Record<IconSize, string> = {
|
const ICON_SKELETON_ITEM_COUNT = 12;
|
||||||
sm: 'grid-cols-3 sm:grid-cols-5 md:grid-cols-7 lg:grid-cols-8',
|
|
||||||
md: 'grid-cols-2 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6',
|
|
||||||
lg: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5',
|
|
||||||
xl: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4',
|
|
||||||
};
|
|
||||||
|
|
||||||
function IconsSkeleton({ iconSize }: { iconSize: IconSize }) {
|
function IconsSkeleton({ iconSize }: { iconSize: IconSize }) {
|
||||||
return (
|
return (
|
||||||
<div className="h-full min-h-0 overflow-y-auto p-3">
|
<div className="h-full min-h-0 overflow-y-auto p-3">
|
||||||
<div className={`grid gap-2 sm:gap-3 ${ICON_COLS[iconSize]}`}>
|
<div className="grid" style={iconsGridStyle(iconSize, ICON_SKELETON_ITEM_COUNT)}>
|
||||||
{Array.from({ length: 12 }).map((_, index) => (
|
{Array.from({ length: ICON_SKELETON_ITEM_COUNT }).map((_, index) => (
|
||||||
<div key={index} className="overflow-hidden rounded-md border border-offbase bg-base">
|
<div key={index} className="overflow-hidden rounded-md border border-offbase bg-base">
|
||||||
<div className="aspect-[3/4] w-full bg-offbase" />
|
<div className="aspect-[3/4] w-full bg-offbase" />
|
||||||
<div className="flex items-center gap-2 px-2 py-2">
|
<div className="flex items-center gap-2 px-2 py-2">
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, type CSSProperties } from 'react';
|
import { useEffect } from 'react';
|
||||||
import type { DocumentListDocument, IconSize } from '@/types/documents';
|
import type { DocumentListDocument, IconSize } from '@/types/documents';
|
||||||
import { DocumentTile } from './DocumentTile';
|
import { DocumentTile } from './DocumentTile';
|
||||||
import { useDocumentSelection } from '../dnd/DocumentSelectionContext';
|
import { useDocumentSelection } from '../dnd/DocumentSelectionContext';
|
||||||
|
import { iconsGridStyle } from './iconsGrid';
|
||||||
|
|
||||||
interface IconsViewProps {
|
interface IconsViewProps {
|
||||||
documents: DocumentListDocument[];
|
documents: DocumentListDocument[];
|
||||||
|
|
@ -12,33 +13,6 @@ interface IconsViewProps {
|
||||||
onMergeIntoFolder: (sources: DocumentListDocument[], target: DocumentListDocument) => void;
|
onMergeIntoFolder: (sources: DocumentListDocument[], target: DocumentListDocument) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TILE_WIDTH_PX: Record<IconSize, number> = {
|
|
||||||
sm: 112,
|
|
||||||
md: 136,
|
|
||||||
lg: 162,
|
|
||||||
xl: 192,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SMALL_GRID_ITEM_COUNT = 3;
|
|
||||||
|
|
||||||
function responsiveGridTemplate(iconSize: IconSize, itemCount: number): string {
|
|
||||||
const width = TILE_WIDTH_PX[iconSize];
|
|
||||||
if (itemCount <= SMALL_GRID_ITEM_COUNT) {
|
|
||||||
return `repeat(auto-fill, minmax(${width}px, ${width}px))`;
|
|
||||||
}
|
|
||||||
return `repeat(auto-fit, minmax(${width}px, 1fr))`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gridGap = '12px';
|
|
||||||
|
|
||||||
function gridStyle(iconSize: IconSize, itemCount: number): CSSProperties {
|
|
||||||
return {
|
|
||||||
gridTemplateColumns: responsiveGridTemplate(iconSize, itemCount),
|
|
||||||
gap: gridGap,
|
|
||||||
justifyContent: itemCount <= SMALL_GRID_ITEM_COUNT ? 'start' : undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function IconsView({
|
export function IconsView({
|
||||||
documents,
|
documents,
|
||||||
iconSize,
|
iconSize,
|
||||||
|
|
@ -61,7 +35,7 @@ export function IconsView({
|
||||||
onClick={handleBackgroundClick}
|
onClick={handleBackgroundClick}
|
||||||
className="flex-1 min-h-0 overflow-y-auto p-3"
|
className="flex-1 min-h-0 overflow-y-auto p-3"
|
||||||
>
|
>
|
||||||
<div className="grid" style={gridStyle(iconSize, documents.length)}>
|
<div className="grid" style={iconsGridStyle(iconSize, documents.length)}>
|
||||||
{documents.map((doc) => (
|
{documents.map((doc) => (
|
||||||
<DocumentTile
|
<DocumentTile
|
||||||
key={`${doc.type}-${doc.id}`}
|
key={`${doc.type}-${doc.id}`}
|
||||||
|
|
|
||||||
28
src/components/doclist/views/iconsGrid.ts
Normal file
28
src/components/doclist/views/iconsGrid.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import type { CSSProperties } from 'react';
|
||||||
|
import type { IconSize } from '@/types/documents';
|
||||||
|
|
||||||
|
const TILE_WIDTH_PX: Record<IconSize, number> = {
|
||||||
|
sm: 112,
|
||||||
|
md: 136,
|
||||||
|
lg: 162,
|
||||||
|
xl: 192,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SMALL_GRID_ITEM_COUNT = 3;
|
||||||
|
const GRID_GAP_PX = 12;
|
||||||
|
|
||||||
|
function responsiveGridTemplate(iconSize: IconSize, itemCount: number): string {
|
||||||
|
const width = TILE_WIDTH_PX[iconSize];
|
||||||
|
if (itemCount <= SMALL_GRID_ITEM_COUNT) {
|
||||||
|
return `repeat(auto-fill, minmax(${width}px, ${width}px))`;
|
||||||
|
}
|
||||||
|
return `repeat(auto-fit, minmax(${width}px, 1fr))`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function iconsGridStyle(iconSize: IconSize, itemCount: number): CSSProperties {
|
||||||
|
return {
|
||||||
|
gridTemplateColumns: responsiveGridTemplate(iconSize, itemCount),
|
||||||
|
gap: `${GRID_GAP_PX}px`,
|
||||||
|
justifyContent: itemCount <= SMALL_GRID_ITEM_COUNT ? 'start' : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue