DataTableProvider.tsx85 lines · main
1import type {
2 ColumnDef,
3 ColumnFiltersState,
4 PaginationState,
5 RowSelectionState,
6 SortingState,
7 Table,
8 VisibilityState,
9} from '@tanstack/react-table'
10import { createContext, ReactNode, useContext, useMemo } from 'react'
11
12import { DataTableFilterField } from '../DataTable.types'
13import { QuerySearchParamsType } from '@/components/interfaces/UnifiedLogs/UnifiedLogs.types'
14import { ResponseError } from '@/types'
15
16// REMINDER: read about how to move controlled state out of the useReactTable hook
17// https://github.com/TanStack/table/discussions/4005#discussioncomment-7303569
18
19interface DataTableStateContextType {
20 columnFilters: ColumnFiltersState
21 sorting: SortingState
22 rowSelection: RowSelectionState
23 columnOrder: string[]
24 columnVisibility: VisibilityState
25 pagination: PaginationState
26 enableColumnOrdering: boolean
27 searchParameters: QuerySearchParamsType
28 openRowId: string | undefined
29 setOpenRowId: (id: string | undefined) => void
30}
31
32interface DataTableBaseContextType<TData = unknown, TValue = unknown> {
33 table: Table<TData>
34 error: ResponseError | null
35 filterFields: DataTableFilterField<TData>[]
36 columns: ColumnDef<TData, TValue>[]
37 isFetching: boolean
38 isError: boolean
39 isLoading: boolean
40 isLoadingCounts: boolean
41 getFacetedUniqueValues?: (table: Table<TData>, columnId: string) => Map<string, number>
42 getFacetedMinMaxValues?: (table: Table<TData>, columnId: string) => undefined | [number, number]
43}
44
45interface DataTableContextType<TData = unknown, TValue = unknown>
46 extends DataTableStateContextType, DataTableBaseContextType<TData, TValue> {}
47
48export const DataTableContext = createContext<DataTableContextType<any, any> | null>(null)
49
50export function DataTableProvider<TData, TValue>({
51 children,
52 ...props
53}: Partial<DataTableStateContextType> &
54 DataTableBaseContextType<TData, TValue> & {
55 children: ReactNode
56 }) {
57 const value = useMemo(
58 () => ({
59 ...props,
60 columnFilters: props.columnFilters ?? [],
61 sorting: props.sorting ?? [],
62 rowSelection: props.rowSelection ?? {},
63 columnOrder: props.columnOrder ?? [],
64 columnVisibility: props.columnVisibility ?? {},
65 pagination: props.pagination ?? { pageIndex: 0, pageSize: 10 },
66 enableColumnOrdering: props.enableColumnOrdering ?? false,
67 searchParameters: props.searchParameters ?? ({} as any),
68 openRowId: props.openRowId,
69 setOpenRowId: props.setOpenRowId ?? (() => {}),
70 }),
71 [props]
72 )
73
74 return <DataTableContext.Provider value={value}>{children}</DataTableContext.Provider>
75}
76
77export function useDataTable<TData, TValue>() {
78 const context = useContext(DataTableContext)
79
80 if (!context) {
81 throw new Error('useDataTable must be used within a DataTableProvider')
82 }
83
84 return context as DataTableContextType<TData, TValue>
85}