11"use client" ;
22
3- import { ColumnDef , flexRender , getCoreRowModel , useReactTable } from "@tanstack/react-table" ;
4- import React , { useState } from "react" ;
3+ import React from "react" ;
4+
5+ import {
6+ ColumnDef ,
7+ CoreOptions ,
8+ ExpandedState ,
9+ flexRender ,
10+ getCoreRowModel ,
11+ getExpandedRowModel ,
12+ OnChangeFn ,
13+ RowSelectionState ,
14+ SortingState ,
15+ useReactTable
16+ } from "@tanstack/react-table" ;
17+
518import { Table , TableBody , TableCell , TableHead , TableHeader , TableRow } from "./Table" ;
19+ import { SortableHeader } from "./Sorting" ;
20+ import { cn } from "../.." ;
621
722interface DataTableProps < TData , TValue > {
823 columns : ColumnDef < TData , TValue > [ ] ;
924 data : TData [ ] ;
25+ filters ?: Record < string , string > ;
26+ resetFilters ?: ( ) => void ;
27+ getRowId ?: CoreOptions < TData > [ "getRowId" ] ;
28+ rowSelection ?: RowSelectionState ;
29+ onRowSelectionChange ?: OnChangeFn < RowSelectionState > ;
30+ sorting ?: SortingState ;
31+ onSortingChange ?: OnChangeFn < SortingState > ;
32+ expanded ?: ExpandedState ;
33+ onExpandedChange ?: OnChangeFn < ExpandedState > ;
34+ getSubRows ?: ( row : TData ) => TData [ ] ;
1035}
1136
12- export function DataTable < TData , TValue > ( { columns, data } : DataTableProps < TData , TValue > ) {
13- const [ rowSelection , setRowSelection ] = useState ( { } ) ;
37+ export function DataTable < TData , TValue > ( {
38+ columns,
39+ data,
40+ filters,
41+ resetFilters,
42+ sorting,
43+ onSortingChange,
44+ expanded,
45+ onExpandedChange,
46+ getSubRows,
47+ getRowId,
48+ rowSelection = { } ,
49+ onRowSelectionChange
50+ } : DataTableProps < TData , TValue > ) {
1451 const table = useReactTable ( {
1552 data,
16- columns,
17- onRowSelectionChange : setRowSelection ,
53+ columns : columns . map ( ( col ) => {
54+ // if col.enableSorting is not defined, set it to false
55+ if ( col . enableSorting === undefined ) {
56+ col . enableSorting = false ;
57+ }
58+ return col ;
59+ } ) ,
60+ manualSorting : true ,
61+ onRowSelectionChange,
62+ onSortingChange,
63+ enableSortingRemoval : false ,
64+ enableMultiSort : false ,
65+ enableRowSelection : true ,
66+ onExpandedChange,
67+ getRowId,
68+ getSubRows,
1869 getCoreRowModel : getCoreRowModel ( ) ,
70+ getExpandedRowModel : getExpandedRowModel ( ) ,
1971 state : {
20- rowSelection
72+ rowSelection,
73+ sorting,
74+ expanded
2175 }
2276 } ) ;
2377
@@ -28,16 +82,29 @@ export function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData
2882 { table . getHeaderGroups ( ) . map ( ( headerGroup ) => (
2983 < TableRow key = { headerGroup . id } >
3084 { headerGroup . headers . map ( ( header ) => {
85+ const canSort = header . column . getCanSort ( ) ;
3186 return (
3287 < TableHead
33- className = "text-theme-text-secondary"
88+ className = { cn (
89+ header . column . columnDef . meta ?. className ,
90+ `${
91+ canSort ? "p-0" : ""
92+ } bg-theme-surface-tertiary font-semibold text-theme-text-secondary`
93+ ) }
3494 key = { header . id }
35- // @ts -expect-error width doesnt exist on the type, and would need a global fragmentation
36- style = { { width : header . column . columnDef . meta ?. width || undefined } }
95+ style = { {
96+ width : header . column . columnDef . meta ?. width
97+ } }
3798 >
38- { header . isPlaceholder
39- ? null
40- : flexRender ( header . column . columnDef . header , header . getContext ( ) ) }
99+ { canSort ? (
100+ < SortableHeader header = { header } >
101+ { header . isPlaceholder
102+ ? null
103+ : flexRender ( header . column . columnDef . header , header . getContext ( ) ) }
104+ </ SortableHeader >
105+ ) : header . isPlaceholder ? null : (
106+ flexRender ( header . column . columnDef . header , header . getContext ( ) )
107+ ) }
41108 </ TableHead >
42109 ) ;
43110 } ) }
@@ -53,12 +120,40 @@ export function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData
53120 data-state = { row . getIsSelected ( ) && "selected" }
54121 >
55122 { row . getVisibleCells ( ) . map ( ( cell ) => (
56- < TableCell className = "font-medium text-theme-text-primary" key = { cell . id } >
123+ < TableCell
124+ className = { cn (
125+ "font-medium text-theme-text-primary" ,
126+ cell . column . columnDef . meta ?. className
127+ ) }
128+ key = { cell . id }
129+ >
57130 { flexRender ( cell . column . columnDef . cell , cell . getContext ( ) ) }
58131 </ TableCell >
59132 ) ) }
60133 </ TableRow >
61134 ) )
135+ ) : filters && Object . keys ( filters ) . length ? (
136+ < TableRow >
137+ < TableCell
138+ colSpan = { columns . length }
139+ className = "h-24 bg-theme-surface-primary p-9 text-center"
140+ >
141+ < p className = "text-text-lg text-theme-text-secondary" >
142+ No items match your current selection.
143+ </ p >
144+ < p className = "text-text-lg text-theme-text-secondary" >
145+ Refine your filters and try again.
146+ </ p >
147+ < div className = "mt-5" >
148+ < p
149+ className = "inline-block cursor-pointer text-text-lg text-theme-text-brand underline"
150+ onClick = { resetFilters }
151+ >
152+ Clear filters
153+ </ p >
154+ </ div >
155+ </ TableCell >
156+ </ TableRow >
62157 ) : (
63158 < TableRow >
64159 < TableCell
0 commit comments