import { InitialTableState, OnChangeFn, PaginationState, getCoreRowModel, getFacetedRowModel, getFacetedUniqueValues, getFilteredRowModel, getSortedRowModel, useReactTable, type ColumnDef, type SortingState, type VisibilityState, } from "@tanstack/react-table"; import { getDataTableSelectionColumn } from "@/components"; import React, { useCallback } from "react"; import { DataTableFilterField } from "./types"; import { useDataTableContext } from "./useDataTableContext"; //import { useDebounce } from "@/hooks/use-debounce"; interface UseDataTableProps { /** * The data for the table. * @default [] * @type TData[] */ data: TData[]; /** * The columns of the table. * @default [] * @type ColumnDef[] */ columns: ColumnDef[]; /** * 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; /** * The default number of rows per page. * @default 10 * @type number | undefined * @example 20 */ defaultPerPage?: number; /** * The default sort order. * @default undefined * @type `${Extract}.${"asc" | "desc"}` | undefined * @example "createdAt.desc" */ defaultSort?: `${Extract}.${"asc" | "desc"}`; /** * 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[]; /** * Enable notion like column filters. * Advanced filters and column filters cannot be used at the same time. * @default false * @type boolean */ enableAdvancedFilter?: boolean; initialState?: InitialTableState; onPaginationChange?: OnChangeFn; } export function useDataTable({ data, columns, pageCount, enableSorting = false, enableHiding = false, enableRowSelection = false, initialState, onPaginationChange, }: UseDataTableProps) { const { pagination, setPagination, sorting } = useDataTableContext(); // Table states const [rowSelection, setRowSelection] = React.useState({}); const [columnVisibility, setColumnVisibility] = React.useState( initialState?.columnVisibility || {} ); const paginationUpdater: OnChangeFn = (updater) => { if (typeof updater === "function") { const newPagination = updater(pagination); setPagination(newPagination); } if (onPaginationChange) { onPaginationChange(updater); } }; const sortingUpdater: OnChangeFn = (updater) => { if (typeof updater === "function") { const newSorting = updater(sorting); console.log(newSorting); //setSorting(newSorting); } }; const getTableColumns = useCallback(() => { const _columns = columns; if (enableRowSelection) { _columns.unshift(getDataTableSelectionColumn()); } return _columns; }, [columns, enableRowSelection]); const table = useReactTable({ data, columns: getTableColumns(), //autoResetPageIndex: true, pageCount: pageCount ?? -1, getCoreRowModel: getCoreRowModel(), initialState, state: { pagination, sorting, columnVisibility, rowSelection, }, enableRowSelection, onRowSelectionChange: setRowSelection, manualSorting: true, enableSorting, getSortedRowModel: getSortedRowModel(), onSortingChange: sortingUpdater, enableHiding, onColumnVisibilityChange: setColumnVisibility, manualPagination: true, onPaginationChange: paginationUpdater, manualFiltering: true, getFilteredRowModel: getFilteredRowModel(), getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), debugTable: false, debugHeaders: false, debugColumns: false, defaultColumn: { minSize: 0, //starting column size size: Number.MAX_SAFE_INTEGER, //enforced during column resizing maxSize: Number.MAX_SAFE_INTEGER, //enforced during column resizing }, }); return { table }; }