// 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: Array> ): TableInstance /** * NOTE: To use custom options, use "Interface Merging" to add the custom options */ export type UseTableOptions = { columns: Array> data: D[] } & Partial<{ initialState: Partial> state: Partial> reducer: ( oldState: TableState, newState: TableState, type: string ) => TableState defaultColumn: Partial> initialRowStateKey: IdType getSubRows: (originalRow: D, relativeIndex: number) => Array getRowID: (originalRow: D, relativeIndex: number) => IdType debug: boolean }> export interface UseTableHooks { columnsBeforeHeaderGroups: Array< ( flatColumns: Array>, instance: TableInstance ) => Array> > columnsBeforeHeaderGroupsDeps: Array< (deps: any[], instance: TableInstance) => any[] > useMain: Array<(instance: TableInstance) => TableInstance> useRows: Array< (rows: Array>, instance: TableInstance) => Array> > prepareRow: Array<(row: Row, instance: TableInstance) => Row> // Prop Hooks getTableProps: Array<(instance: TableInstance) => object> getTableBodyProps: Array<(instance: TableInstance) => object> getRowProps: Array<(row: Row, instance: TableInstance) => object> getHeaderGroupProps: Array< (headerGroup: HeaderGroup, instance: TableInstance) => object > getHeaderProps: Array< (column: Column, instance: TableInstance) => object > getCellProps: Array<(cell: Cell, instance: TableInstance) => object> } export interface UseTableColumnOptions extends Accessor, Partial<{ columns: Array> show: boolean | ((instance: TableInstance) => boolean) Header: Renderer> Cell: Renderer> width?: number minWidth?: number maxWidth?: number }> {} export interface UseTableInstanceProps { columns: Array> flatColumns: Array> headerGroups: Array> headers: Array> flatHeaders: Array> rows: Array> getTableProps: (props?: object) => object getTableBodyProps: (props?: object) => object prepareRow: (row: Row) => void rowPaths: string[] flatRows: Array> state: TableState setState: SetState totalColumnsWidth: number } export interface UseTableHeaderGroupProps { headers: Array> 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: Array> values: Record, CellValue> getRowProps: (props?: object) => object index: number original: D path: Array> subRows: Array> } 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 } export type CellProps = TableInstance & { column: ColumnInstance row: Row cell: Cell } // 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: Array> } export interface UseColumnOrderInstanceProps { setColumnOrder: ( updater: (columnOrder: Array>) => Array> ) => void } /* #endregion */ /* #region useExpanded */ export function useExpanded(hooks: Hooks): void export namespace useExpanded { const pluginName = 'useExpanded' } export type UseExpandedOptions = Partial<{ manualExpandedKey: IdType paginateExpandedRows: boolean getResetExpandedDeps: (i: TableInstance) => Array }> export interface UseExpandedHooks { getExpandedToggleProps: Array< (row: Row, instance: TableInstance) => object > } export interface UseExpandedState { expanded: Array> } export interface UseExpandedInstanceProps { rows: Array> toggleExpandedByPath: (path: Array>, isExpanded: boolean) => void expandedDepth: number } export interface UseExpandedRowProps { isExpanded: boolean canExpand: boolean subRows: Array> 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 getResetFiltersDeps: (i: TableInstance) => Array }> export interface UseFiltersState { filters: Filters } export type UseFiltersColumnOptions = Partial<{ disableFilters: boolean Filter: Renderer> filter: FilterType | DefaultFilterTypes | keyof Filters }> export interface UseFiltersInstanceProps { rows: Array> preFilteredRows: Array> 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: Array> filteredRows: Array> } 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: Array>, columnId: IdType, filterValue: FilterValue, column: ColumnInstance ): Array> 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 disableGroupBy: boolean aggregations: Record> groupByFn: ( rows: Array>, columnId: IdType ) => Record> getResetGroupByDeps: (i: TableInstance) => Array }> export interface UseGroupByHooks { getGroupByToggleProps: Array< (header: HeaderGroup, instance: TableInstance) => object > } export interface UseGroupByState { groupBy: Array> } export type UseGroupByColumnOptions = Partial<{ aggregate: Aggregator | Array> Aggregated: Renderer> disableGroupBy: boolean groupByBoundary: boolean }> export interface UseGroupByInstanceProps { rows: Array> preGroupedRows: Array> toggleGroupBy: (columnId: IdType, toggle: boolean) => void } export interface UseGroupByColumnProps { canGroupBy: boolean isGrouped: boolean groupedIndex: number toggleGroupBy: () => void getGroupByToggleProps: (props?: object) => object } export interface UseGroupByRowProps { isAggregated: boolean groupByID: IdType groupByVal: string values: Record, AggregatedValue> subRows: Array> depth: number path: Array> 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: Array> ) => 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 getResetPageDeps: (i: TableInstance) => Array paginateExpandedRows: boolean }> export interface UsePaginationState { pageSize: number pageIndex: number } export interface UsePaginationInstanceProps { page: Array> 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 getResetSelectedRowPathsDeps: (i: TableInstance) => Array }> export interface UseRowSelectHooks { getToggleRowSelectedProps: Array< (row: Row, instance: TableInstance) => object > getToggleAllRowsSelectedProps: Array<(instance: TableInstance) => object> } export interface UseRowSelectState { selectedRowPaths: Array> } export interface UseRowSelectInstanceProps { toggleRowSelected: (rowPath: IdType, set?: boolean) => void toggleRowSelectedAll: (set?: boolean) => void getToggleAllRowsSelectedProps: (props?: object) => object isAllRowsSelected: boolean selectedFlatRows: Array> } 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 disableSortBy: boolean disableMultiSort: boolean isMultiSortEvent: (e: MouseEvent) => boolean maxMultiSortColCount: number disableSortRemove: boolean disabledMultiRemove: boolean orderByFn: ( rows: Array>, sortFns: Array>, directions: boolean[] ) => Array> sortTypes: Record> getResetSortByDeps: (i: TableInstance) => Array }> export interface UseSortByHooks { getSortByToggleProps: Array< (column: Column, instance: TableInstance) => object > } export interface UseSortByState { sortBy: Array> } export type UseSortByColumnOptions = Partial<{ disableSortBy: boolean sortDescFirst: boolean sortInverted: boolean sortType: SortByFn | DefaultSortTypes | string }> export interface UseSortByInstanceProps { rows: Array> preSortedRows: Array> 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