2024-06-06 11:05:54 +00:00
|
|
|
import {
|
|
|
|
|
OnChangeFn,
|
|
|
|
|
PaginationState,
|
|
|
|
|
getCoreRowModel,
|
|
|
|
|
getFacetedRowModel,
|
|
|
|
|
getFacetedUniqueValues,
|
|
|
|
|
getFilteredRowModel,
|
|
|
|
|
getSortedRowModel,
|
|
|
|
|
useReactTable,
|
|
|
|
|
type ColumnDef,
|
|
|
|
|
type SortingState,
|
|
|
|
|
type VisibilityState,
|
|
|
|
|
} from "@tanstack/react-table";
|
|
|
|
|
|
|
|
|
|
import { getDataTableSelectionColumn } from "@/components";
|
2024-06-13 11:09:26 +00:00
|
|
|
import React, { useCallback } from "react";
|
2024-06-11 16:48:09 +00:00
|
|
|
import { DataTableFilterField } from "./types";
|
|
|
|
|
import { useDataTableContext } from "./useDataTableContext";
|
2024-06-06 11:05:54 +00:00
|
|
|
|
|
|
|
|
//import { useDebounce } from "@/hooks/use-debounce";
|
|
|
|
|
|
|
|
|
|
interface UseDataTableProps<TData, TValue> {
|
|
|
|
|
/**
|
|
|
|
|
* The data for the table.
|
|
|
|
|
* @default []
|
|
|
|
|
* @type TData[]
|
|
|
|
|
*/
|
|
|
|
|
data: TData[];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The columns of the table.
|
|
|
|
|
* @default []
|
|
|
|
|
* @type ColumnDef<TData, TValue>[]
|
|
|
|
|
*/
|
|
|
|
|
columns: ColumnDef<TData, TValue>[];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The number of pages in the table.
|
|
|
|
|
* @type number
|
|
|
|
|
*/
|
|
|
|
|
pageCount: number;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enable sorting columns.
|
|
|
|
|
* @default false
|
|
|
|
|
* @type boolean
|
|
|
|
|
*/
|
|
|
|
|
enableSorting?: boolean;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enable hiding columns.
|
|
|
|
|
* @default false
|
|
|
|
|
* @type boolean
|
|
|
|
|
*/
|
|
|
|
|
enableHiding?: boolean;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enable selection rows.
|
|
|
|
|
* @default false
|
|
|
|
|
* @type boolean
|
|
|
|
|
*/
|
|
|
|
|
enableRowSelection?: boolean;
|
|
|
|
|
|
2024-06-13 11:09:26 +00:00
|
|
|
/**
|
|
|
|
|
* The default number of rows per page.
|
|
|
|
|
* @default 10
|
|
|
|
|
* @type number | undefined
|
|
|
|
|
* @example 20
|
|
|
|
|
*/
|
|
|
|
|
defaultPerPage?: number;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The default sort order.
|
|
|
|
|
* @default undefined
|
|
|
|
|
* @type `${Extract<keyof TData, string | number>}.${"asc" | "desc"}` | undefined
|
|
|
|
|
* @example "createdAt.desc"
|
|
|
|
|
*/
|
|
|
|
|
defaultSort?: `${Extract<keyof TData, string | number>}.${"asc" | "desc"}`;
|
|
|
|
|
|
2024-06-06 11:05:54 +00:00
|
|
|
/**
|
|
|
|
|
* Defines filter fields for the table. Supports both dynamic faceted filters and search filters.
|
|
|
|
|
* - Faceted filters are rendered when `options` are provided for a filter field.
|
|
|
|
|
* - Otherwise, search filters are rendered.
|
|
|
|
|
*
|
|
|
|
|
* The indie filter field `value` represents the corresponding column name in the database table.
|
|
|
|
|
* @default []
|
|
|
|
|
* @type { label: string, value: keyof TData, placeholder?: string, options?: { label: string, value: string, icon?: React.ComponentType<{ className?: string }> }[] }[]
|
|
|
|
|
* @example
|
|
|
|
|
* ```ts
|
|
|
|
|
* // Render a search filter
|
|
|
|
|
* const filterFields = [
|
|
|
|
|
* { label: "Title", value: "title", placeholder: "Search titles" }
|
|
|
|
|
* ];
|
|
|
|
|
* // Render a faceted filter
|
|
|
|
|
* const filterFields = [
|
|
|
|
|
* {
|
|
|
|
|
* label: "Status",
|
|
|
|
|
* value: "status",
|
|
|
|
|
* options: [
|
|
|
|
|
* { label: "Todo", value: "todo" },
|
|
|
|
|
* { label: "In Progress", value: "in-progress" },
|
|
|
|
|
* { label: "Done", value: "done" },
|
|
|
|
|
* { label: "Canceled", value: "canceled" }
|
|
|
|
|
* ]
|
|
|
|
|
* }
|
|
|
|
|
* ];
|
|
|
|
|
* ```
|
|
|
|
|
*/
|
|
|
|
|
filterFields?: DataTableFilterField<TData>[];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Enable notion like column filters.
|
|
|
|
|
* Advanced filters and column filters cannot be used at the same time.
|
|
|
|
|
* @default false
|
|
|
|
|
* @type boolean
|
|
|
|
|
*/
|
|
|
|
|
enableAdvancedFilter?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useDataTable<TData, TValue>({
|
|
|
|
|
data,
|
|
|
|
|
columns,
|
|
|
|
|
pageCount,
|
|
|
|
|
enableSorting = false,
|
|
|
|
|
enableHiding = false,
|
|
|
|
|
enableRowSelection = false,
|
|
|
|
|
}: UseDataTableProps<TData, TValue>) {
|
2024-06-13 11:09:26 +00:00
|
|
|
const { pagination, setPagination, sorting, setSorting } = useDataTableContext();
|
2024-06-06 11:05:54 +00:00
|
|
|
|
|
|
|
|
// Table states
|
|
|
|
|
const [rowSelection, setRowSelection] = React.useState({});
|
2024-06-11 16:48:09 +00:00
|
|
|
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
|
2024-06-06 11:05:54 +00:00
|
|
|
|
|
|
|
|
const paginationUpdater: OnChangeFn<PaginationState> = (updater) => {
|
|
|
|
|
if (typeof updater === "function") {
|
|
|
|
|
const newPagination = updater(pagination);
|
|
|
|
|
setPagination(newPagination);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const sortingUpdater: OnChangeFn<SortingState> = (updater) => {
|
|
|
|
|
if (typeof updater === "function") {
|
2024-06-13 11:09:26 +00:00
|
|
|
const newSorting = updater(sorting);
|
|
|
|
|
console.log(newSorting);
|
|
|
|
|
setSorting(newSorting);
|
2024-06-06 11:05:54 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getTableColumns = useCallback(() => {
|
|
|
|
|
const _columns = columns;
|
|
|
|
|
if (enableRowSelection) {
|
|
|
|
|
_columns.unshift(getDataTableSelectionColumn());
|
|
|
|
|
}
|
|
|
|
|
return _columns;
|
|
|
|
|
}, [columns, enableRowSelection]);
|
|
|
|
|
|
|
|
|
|
const table = useReactTable({
|
|
|
|
|
data,
|
2024-06-13 11:09:26 +00:00
|
|
|
columns: getTableColumns(),
|
|
|
|
|
pageCount: pageCount ?? -1,
|
2024-06-06 11:05:54 +00:00
|
|
|
getCoreRowModel: getCoreRowModel(),
|
|
|
|
|
|
|
|
|
|
state: {
|
|
|
|
|
pagination,
|
|
|
|
|
sorting,
|
|
|
|
|
columnVisibility,
|
|
|
|
|
rowSelection,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
enableRowSelection,
|
|
|
|
|
onRowSelectionChange: setRowSelection,
|
|
|
|
|
|
|
|
|
|
manualSorting: true,
|
|
|
|
|
enableSorting,
|
|
|
|
|
getSortedRowModel: getSortedRowModel(),
|
|
|
|
|
onSortingChange: sortingUpdater,
|
|
|
|
|
|
|
|
|
|
enableHiding,
|
|
|
|
|
onColumnVisibilityChange: setColumnVisibility,
|
|
|
|
|
|
|
|
|
|
manualPagination: true,
|
|
|
|
|
onPaginationChange: paginationUpdater,
|
|
|
|
|
|
|
|
|
|
manualFiltering: true,
|
2024-06-13 11:09:26 +00:00
|
|
|
getFilteredRowModel: getFilteredRowModel(),
|
2024-06-06 11:05:54 +00:00
|
|
|
|
|
|
|
|
getFacetedRowModel: getFacetedRowModel(),
|
|
|
|
|
getFacetedUniqueValues: getFacetedUniqueValues(),
|
2024-06-13 11:09:26 +00:00
|
|
|
|
|
|
|
|
debugTable: true,
|
|
|
|
|
debugHeaders: true,
|
|
|
|
|
debugColumns: true,
|
2024-06-06 11:05:54 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return { table };
|
|
|
|
|
}
|