'use client'; import React, { ReactNode } from 'react'; import { cn } from '@/lib/utils'; import { LoadingSkeleton } from '@/components/ui'; // CardGrid column options export type GridColumns = 1 | 2 | 3 | 4; // CardGrid gap options export type GridGap = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; // CardGrid props interface export interface CardGridProps { /** Card items to render */ items?: ReactNode[]; /** Number of columns */ columns?: GridColumns; /** Gap spacing */ gap?: GridGap; /** Loading state */ loading?: boolean; /** Empty state message */ emptyMessage?: string; /** Empty state component */ emptyComponent?: ReactNode; /** Loading skeleton count */ skeletonCount?: number; /** Additional classes */ className?: string; /** Children (alternative to items) */ children?: ReactNode; } // Helper function to get gap classes const getGapClasses = (gap: GridGap): string => { const gapMap = { xs: 'gap-2', sm: 'gap-4', md: 'gap-6', lg: 'gap-8', xl: 'gap-12', }; return gapMap[gap]; }; // Helper function to get column classes const getColumnClasses = (columns: GridColumns): string => { const columnMap = { 1: 'grid-cols-1', 2: 'grid-cols-1 md:grid-cols-2', 3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4', }; return columnMap[columns]; }; // Skeleton loader component const GridSkeleton = ({ count, columns, gap }: { count: number; columns: GridColumns; gap: GridGap; }) => { const gapClasses = getGapClasses(gap); const columnClasses = getColumnClasses(columns); return (
{Array.from({ length: count }).map((_, index) => (
))}
); }; // Empty state component const EmptyState = ({ message, customComponent }: { message?: string; customComponent?: ReactNode; }) => { if (customComponent) { return
{customComponent}
; } return (
{message || 'No items to display'}
{message ? '' : 'Try adjusting your filters or check back later'}
); }; export const CardGrid: React.FC = ({ items, columns = 3, gap = 'md', loading = false, emptyMessage, emptyComponent, skeletonCount = 6, className = '', children, }) => { // Use children if provided, otherwise use items const content = children || items; // Loading state if (loading) { return ( ); } // Empty state if (!content || (Array.isArray(content) && content.length === 0)) { return ( ); } // Render grid const gapClasses = getGapClasses(gap); const columnClasses = getColumnClasses(columns); return (
{Array.isArray(content) ? content.map((item, index) => (
{item}
)) : content }
); }; // Grid variations export const CardGrid2: React.FC = (props) => ( ); export const CardGrid3: React.FC = (props) => ( ); export const CardGrid4: React.FC = (props) => ( ); // Responsive grid with auto columns export const CardGridAuto: React.FC = ({ gap = 'md', className = '', ...props }) => { const gapClasses = getGapClasses(gap); return (
{props.items && Array.isArray(props.items) ? props.items.map((item, index) => (
{item}
)) : props.children }
); };