// TypeScript Version: 3.5 import { ReactNode, ComponentType, MouseEvent } from 'react' /** * The empty definitions of below provides a base definition for the parts used by useTable, that can then be extended in the users code. * * @example * export interface TableOptions * extends * UseExpandedOptions, * UseFiltersOptions {} */ export interface TableOptions extends UseTableOptions {} export interface TableInstance extends Omit, 'columns' | 'state'>, UseTableInstanceProps {} export interface TableState< D extends object = {} > {} /* tslint:disable-line no-empty-interface */ // eslint-disable-line @typescript-eslint/no-empty-interface export interface Hooks extends UseTableHooks {} export interface Cell extends UseTableCellProps {} export interface Column extends UseTableColumnOptions {} export interface ColumnInstance extends Omit, 'id'>, UseTableColumnProps {} export interface HeaderGroup extends ColumnInstance, UseTableHeaderGroupProps {} export interface Row extends UseTableRowProps {} /* #region useTable */ export function useTable( options: TableOptions, ...plugins: PluginHook[] ): TableInstance /** * NOTE: To use custom options, use "Interface Merging" to add the custom options */ export type UseTableOptions = { columns: Column[] data: D[] } & Partial<{ initialState: Partial> state: Partial> reducer: ( oldState: TableState, newState: TableState, type: string ) => TableState defaultColumn: Partial> initialRowStateKey: IdType getSubRows: (row: Row, relativeIndex: number) => Row[] getRowID: (row: Row, relativeIndex: number) => string debug: boolean }> export interface UseTableHooks { columnsBeforeHeaderGroups: (( flatColumns: Column[], instance: TableInstance ) => Column[])[] columnsBeforeHeaderGroupsDeps: (( deps: any[], instance: TableInstance ) => any[])[] useMain: ((instance: TableInstance) => TableInstance)[] useRows: ((rows: Row[], instance: TableInstance) => Row[])[] prepareRow: ((row: Row, instance: TableInstance) => Row)[] // Prop Hooks getTableProps: ((instance: TableInstance) => object)[] getTableBodyProps: ((instance: TableInstance) => object)[] getRowProps: ((row: Row, instance: TableInstance) => object)[] getHeaderGroupProps: (( headerGroup: HeaderGroup, instance: TableInstance ) => object)[] getHeaderProps: ((column: Column, instance: TableInstance) => object)[] getCellProps: ((cell: Cell, instance: TableInstance) => object)[] } export interface UseTableColumnOptions extends Accessor, Partial<{ columns: Column[] show: boolean | ((instance: TableInstance) => boolean) Header: Renderer> Cell: Renderer> width?: number minWidth?: number maxWidth?: number }> {} export interface UseTableInstanceProps { columns: ColumnInstance[] flatColumns: ColumnInstance[] headerGroups: HeaderGroup[] headers: ColumnInstance[] flatHeaders: ColumnInstance[] rows: Row[] getTableProps: (props?: object) => object getTableBodyProps: (props?: object) => object prepareRow: (row: Row) => void rowPaths: string[] flatRows: Row[] state: TableState setState: SetState totalColumnsWidth: number } export interface UseTableHeaderGroupProps { headers: ColumnInstance[] getHeaderGroupProps: (props?: object) => object totalHeaderCount: number } export interface UseTableColumnProps { id: IdType isVisible: boolean render: (type: 'Header' | string, props?: object) => ReactNode getHeaderProps: (props?: object) => object parent: ColumnInstance depth: number index: number } export interface UseTableRowProps { cells: Cell[] values: Record, CellValue> getRowProps: (props?: object) => object index: number original: D path: IdType[] subRows: Row[] } export interface UseTableCellProps { column: ColumnInstance row: Row value: CellValue getCellProps: (props?: object) => object render: (type: 'Cell' | string, userProps?: object) => ReactNode } export type HeaderProps = TableInstance & { column: ColumnInstance } & Record export type CellProps = TableInstance & { column: ColumnInstance row: Row cell: Cell } & Record // NOTE: At least one of (id | accessor | Header as string) required export interface Accessor { accessor?: | IdType | (( originalRow: D, index: number, sub: { subRows: D[] depth: number data: D[] } ) => CellValue) id?: IdType } /* #endregion */ // Plugins /* #region useColumnOrder */ export function useColumnOrder(hooks: Hooks): void export namespace useColumnOrder { const pluginName = 'useColumnOrder' } export interface UseColumnOrderState { columnOrder: IdType[] } export interface UseColumnOrderInstanceProps { setColumnOrder: (updater: (columnOrder: IdType[]) => IdType[]) => void } /* #endregion */ /* #region useExpanded */ export function useExpanded(hooks: Hooks): void export namespace useExpanded { const pluginName = 'useExpanded' } export type UseExpandedOptions = Partial<{ getSubRows: (row: Row, relativeIndex: number) => Row[] manualExpandedKey: IdType paginateExpandedRows: boolean }> export interface UseExpandedHooks { getExpandedToggleProps: (( row: Row, instance: TableInstance ) => object)[] } export interface UseExpandedState { expanded: IdType[] } export interface UseExpandedInstanceProps { rows: Row[] toggleExpandedByPath: (path: IdType[], isExpanded: boolean) => void expandedDepth: number } export interface UseExpandedRowProps { isExpanded: boolean canExpand: boolean subRows: Row[] toggleExpanded: (isExpanded?: boolean) => void getExpandedToggleProps: (props?: object) => object } /* #endregion */ /* #region useFilters */ export function useFilters(hooks: Hooks): void export namespace useFilters { const pluginName = 'useFilters' } export type UseFiltersOptions = Partial<{ manualFilters: boolean disableFilters: boolean filterTypes: Filters }> export interface UseFiltersState { filters: Filters } export type UseFiltersColumnOptions = Partial<{ disableFilters: boolean Filter: Renderer> filter: FilterType | DefaultFilterTypes | keyof Filters }> export interface UseFiltersInstanceProps { rows: Row[] preFilteredRows: Row[] setFilter: ( columnId: IdType, updater: ((filterValue: FilterValue) => FilterValue) | FilterValue ) => void setAllFilters: ( updater: Filters | ((filters: Filters) => Filters) ) => void } export interface UseFiltersColumnProps { canFilter: boolean setFilter: ( updater: ((filterValue: FilterValue) => FilterValue) | FilterValue ) => void filterValue: FilterValue preFilteredRows: Row[] filteredRows: Row[] } export type FilterProps = HeaderProps export type FilterValue = any export type Filters = Record, FilterValue> export type DefaultFilterTypes = | 'text' | 'exactText' | 'exactTextCase' | 'includes' | 'includesAll' | 'exact' | 'equals' | 'between' export interface FilterType { ( rows: Row[], columnId: IdType, filterValue: FilterValue, column: ColumnInstance ): Row[] autoRemove?: (filterValue: FilterValue) => boolean } /* #endregion */ /* #region useGroupBy */ export function useGroupBy(hooks: Hooks): void export namespace useGroupBy { const pluginName = 'useGroupBy' } export type UseGroupByOptions = Partial<{ manualGroupBy: boolean disableGrouping: boolean aggregations: Record> groupByFn: (rows: Row[], columnId: IdType) => Record> }> export interface UseGroupByHooks { getGroupByToggleProps: (( header: HeaderGroup, instance: TableInstance ) => object)[] } export interface UseGroupByState { groupBy: IdType[] } export type UseGroupByColumnOptions = Partial<{ aggregate: Aggregator | Aggregator[] Aggregated: Renderer> disableGrouping: boolean groupByBoundary: boolean }> export interface UseGroupByInstanceProps { rows: Row[] preGroupedRows: Row[] toggleGroupBy: (columnId: IdType, toggle: boolean) => void } export interface UseGroupByColumnProps { canGroupBy: boolean isGrouped: boolean groupedIndex: number toggleGroupBy: () => void } export interface UseGroupByHeaderProps { getGroupByToggleProps: (props?: object) => object } export interface UseGroupByRowProps { isAggregated: boolean groupByID: IdType groupByVal: string values: Record, AggregatedValue> subRows: Row[] depth: number path: IdType[] index: number } export interface UseGroupByCellProps { isGrouped: boolean isRepeatedValue: boolean isAggregated: boolean } export type DefaultAggregators = | 'sum' | 'average' | 'median' | 'uniqueCount' | 'count' export type AggregatorFn = ( columnValues: CellValue[], rows: Row[] ) => AggregatedValue export type Aggregator = | AggregatorFn | DefaultAggregators | string export type AggregatedValue = any /* #endregion */ /* #region usePagination */ export function usePagination(hooks: Hooks): void export namespace usePagination { const pluginName = 'usePagination' } export type UsePaginationOptions = Partial<{ pageCount: number manualPagination: boolean disablePageResetOnDataChange: boolean paginateExpandedRows: boolean }> export interface UsePaginationState { pageSize: number pageIndex: number } export interface UsePaginationInstanceProps { page: Row[] pageCount: number pageOptions: number[] canPreviousPage: boolean canNextPage: boolean gotoPage: (updater: ((pageIndex: number) => number) | number) => void previousPage: () => void nextPage: () => void setPageSize: (pageSize: number) => void pageIndex: number pageSize: number } /* #endregion */ /* #region useRowSelect */ export function useRowSelect(hooks: Hooks): void export namespace useRowSelect { const pluginName = 'useRowSelect' } export type UseRowSelectOptions = Partial<{ manualRowSelectedKey: IdType }> export interface UseRowSelectHooks { getToggleRowSelectedProps: (( row: Row, instance: TableInstance ) => object)[] getToggleAllRowsSelectedProps: ((instance: TableInstance) => object)[] } export interface UseRowSelectState { selectedRows: IdType[] } export interface UseRowSelectInstanceProps { toggleRowSelected: (rowPath: IdType, set?: boolean) => void toggleRowSelectedAll: (set?: boolean) => void getToggleAllRowsSelectedProps: (props?: object) => object isAllRowsSelected: boolean } export interface UseRowSelectRowProps { isSelected: boolean toggleRowSelected: (set?: boolean) => void getToggleRowSelectedProps: (props?: object) => object } /* #endregion */ /* #region useRowState */ export function useRowState(hooks: Hooks): void export namespace useRowState { const pluginName = 'useRowState' } export type UseRowStateOptions = Partial<{ initialRowStateAccessor: (row: Row) => UseRowStateLocalState }> export interface UseRowStateState { rowState: Partial<{ cellState: UseRowStateLocalState rowState: UseRowStateLocalState }> } export interface UseRowStateInstanceProps { setRowState: (rowPath: string[], updater: UseRowUpdater) => void // Purposely not exposing action setCellState: ( rowPath: string[], columnID: IdType, updater: UseRowUpdater ) => void } export interface UseRowStateRowProps { state: UseRowStateLocalState setState: (updater: UseRowUpdater) => void } export interface UseRowStateCellProps { state: UseRowStateLocalState setState: (updater: UseRowUpdater) => void } export type UseRowUpdater = T | ((prev: T) => T) export type UseRowStateLocalState = Record< IdType, T > /* #endregion */ /* #region useSortBy */ export function useSortBy(hooks: Hooks): void export namespace useSortBy { const pluginName = 'useSortBy' } export type UseSortByOptions = Partial<{ manualSorting: boolean disableSorting: boolean disableMultiSort: boolean isMultiSortEvent: (e: MouseEvent) => boolean maxMultiSortColCount: number disableSortRemove: boolean disabledMultiRemove: boolean orderByFn: ( rows: Row[], sortFns: SortByFn[], directions: boolean[] ) => Row[] // CHECK sortTypes: Record> }> export interface UseSortByHooks { getSortByToggleProps: (( column: Column, instance: TableInstance ) => object)[] } export interface UseSortByState { sortBy: SortingRule[] } export type UseSortByColumnOptions = Partial<{ disableSorting: boolean sortDescFirst: boolean sortInverted: boolean sortType: SortByFn | DefaultSortTypes | string }> export interface UseSortByInstanceProps { rows: Row[] preSortedRows: Row[] toggleSortBy: ( columnId: IdType, descending: boolean, isMulti: boolean ) => void } export interface UseSortByColumnProps { canSort: boolean toggleSortBy: (descending: boolean, multi: boolean) => void getSortByToggleProps: (props?: object) => object clearSorting: () => void isSorted: boolean sortedIndex: number isSortedDesc: boolean | undefined } export type SortByFn = ( rowA: Row, rowB: Row, columnId: IdType ) => 0 | 1 | -1 export type DefaultSortTypes = 'alphanumeric' | 'datetime' | 'basic' export interface SortingRule { id: IdType desc?: boolean } /* #endregion */ /* #region useAbsoluteLayout */ export function useAbsoluteLayout(hooks: Hooks): void export namespace useAbsoluteLayout { const pluginName = 'useAbsoluteLayout' } /* #endregion */ /* #region useBlockLayout */ export function useBlockLayout(hooks: Hooks): void export namespace useBlockLayout { const pluginName = 'useBlockLayout' } /* #endregion */ /* #region useResizeColumns */ export function useResizeColumns(hooks: Hooks): void export namespace useResizeColumns { const pluginName = 'useResizeColumns' } export interface UseResizeColumnsOptions { disableResizing?: boolean } export interface UseResizeColumnsColumnOptions { disableResizing?: boolean } export interface UseResizeColumnsHeaderProps { getResizerProps: (props?: object) => object canResize: boolean isResizing: boolean } /* #endregion */ // Additional API export const actions: Record export function addActions(...actions: string[]): void export const defaultState: Record // Helpers export type StringKey = Extract export type IdType = StringKey | string export type CellValue = any export type Renderer = ComponentType | ReactNode export interface PluginHook { (hooks: Hooks): void pluginName: string } export type SetState = ( updater: (old: TableState) => TableState, type: keyof typeof actions ) => void