import { useMemo, useState, type ReactNode } from "react"; import { cn } from "../../lib/cn"; import { EmptyState, Skeleton } from "../feedback"; import { Pagination } from "../navigation"; import { RowActions, type DataRowAction } from "./row-actions"; import { cellAlignmentClass, MobileDataGridCard, nextSortState, resolveCellContent, resolveSortValue, type DataGridSortState, type TableColumn, } from "./shared"; export function DataGrid>({ columns, currentPage, data, action, emptyAction, emptyDescription = "No records are available for the current view.", emptyTitle = "No results", isLoading = false, itemCount, leadingIcon, mobileExpandedByDefault = false, mobilePrimaryKey, mobileView = "table", onPageChange, onPageSizeChange, onSortChange, pageSize = 10, pageSizeOptions, showPagination = true, sortState, subtitle, title, }: { action?: DataRowAction[]; columns: TableColumn[]; currentPage: number; data: T[]; emptyAction?: ReactNode; emptyDescription?: string; emptyTitle?: string; isLoading?: boolean; itemCount: number; leadingIcon?: ReactNode; mobileExpandedByDefault?: boolean; mobilePrimaryKey?: keyof T; mobileView?: "cards" | "table"; onPageChange?: (page: number) => void; onPageSizeChange?: (pageSize: number) => void; onSortChange?: (sort: DataGridSortState) => void; pageSize?: number; pageSizeOptions?: number[]; showPagination?: boolean; sortState?: DataGridSortState; subtitle?: ReactNode; title?: ReactNode; }) { const hasActions = Boolean(action?.length); const sortableColumns = columns.filter((column) => column.sortable); const [internalSortState, setInternalSortState] = useState< DataGridSortState | undefined >( sortableColumns[0] ? { direction: "asc", key: sortableColumns[0].key } : undefined, ); const resolvedSortState = sortState ?? internalSortState; const sortedData = useMemo(() => { if (!resolvedSortState) { return data; } const column = columns.find((entry) => entry.key === resolvedSortState.key); if (!column) { return data; } return [...data].sort((left, right) => { const leftValue = resolveSortValue(left, column); const rightValue = resolveSortValue(right, column); if (leftValue < rightValue) { return resolvedSortState.direction === "asc" ? -1 : 1; } if (leftValue > rightValue) { return resolvedSortState.direction === "asc" ? 1 : -1; } return 0; }); }, [columns, data, resolvedSortState]); function handleSortChange(nextSort: DataGridSortState) { if (sortState === undefined) { setInternalSortState(nextSort); } onSortChange?.(nextSort); } const resolvedMobilePrimaryKey = mobilePrimaryKey ?? columns[0]?.key; const hasHeading = Boolean(leadingIcon || title || subtitle); const heading = hasHeading ? (
{leadingIcon ? ( {leadingIcon} ) : null}
{title ? (

{title}

) : null} {subtitle ? (

{subtitle}

) : null}

{itemCount} items

) : null; return (
{isLoading ? (
{heading}
) : data.length === 0 ? ( ) : (
{heading}
{mobileView === "cards" && resolvedMobilePrimaryKey ? (
{sortedData.map((row, rowIndex) => ( ))}
) : (
Swipe for more columns
)}
{columns.map((column) => ( ))} {hasActions ? ( {sortedData.map((row, rowIndex) => ( {columns.map((column) => ( ))} {hasActions ? ( ) : null} ))}
{column.sortable ? ( ) : ( column.label )} ) : null}
{resolveCellContent(row, column)}
{showPagination ? ( ) : null}
)}
); }