From c3e917f13b3e376ff6977478d3c96d0edcb84f9b Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Tue, 17 Sep 2019 15:42:36 -0600 Subject: [PATCH 1/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 94f9a1e..ef1f83b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Hooks for building **lightweight, fast and extendable datagrids** for React ## Features -- Lightweight (4kb - 11kb depending on features and tree-shaking) +- Lightweight (4kb - 9kb depending on features and tree-shaking) - Headless (100% customizable, Bring-your-own-UI) - Auto out of the box, fully controllable API - Sorting (Multi and Stable) From b8ed02cadc0315b119045da62cc52599b37baea4 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Tue, 17 Sep 2019 15:44:02 -0600 Subject: [PATCH 2/3] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ef1f83b..8f2879d 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Hooks for building **lightweight, fast and extendable datagrids** for React + + + From 7ab63858391ebb2ff621fa71411157df19d916ba Mon Sep 17 00:00:00 2001 From: ggascoigne Date: Fri, 20 Sep 2019 08:37:45 -0700 Subject: [PATCH 3/3] TypeScript updates (#1521) * TypeScript updates I've found that trying to get solid TypeScript typings for this library are a bit of a challenge. The composable nature of the library means that the types for the builtin functions are by their nature somewhat minimal, and that the user needs to be able to extend those interfaces to reflect the specific plugins that are in use. With that in mind I propose something like this. To get the best out of them, you then need to extend those interfaces using declaration merging, see https://www.typescriptlang.org/docs/handbook/declaration-merging.html e.g. ```ts declare module 'react-table-hooks' { export interface TableInstance extends UseFiltersValues, UsePaginationValues, UseExpandedValues, UseGroupByValues {} export interface TableState extends UsePaginationState, UseGroupByState, UseSortbyState, UseFiltersState {} } ``` This also puts the ability to extend those types with any user defined hooks completely in the users hands. This gives the greatest flexibility, but I'll admit that it isn't particularly obvious. Perhaps a typescript readme and example is needed. * fix useExpanded type * fix module name * fix typo * address review feedback * add IdType, update Filters definition --- index.d.ts | 458 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 281 insertions(+), 177 deletions(-) diff --git a/index.d.ts b/index.d.ts index 69f3551..6eb5524 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,184 +1,288 @@ -import { Dispatch, SetStateAction, ReactNode } from 'react'; - declare module 'react-table' { - export interface Cell { - render: (type: string) => any; - getCellProps: () => any; - column: Column; - row: Row; - state: any; - value: any; + import { ReactNode, useState } from 'react' + + type StringKey = Extract + type IdType = StringKey | string + + type SortingRule = { + id: IdType + desc: boolean + } + + export type SortingRules = SortingRule[] + + export type SortByFn = (a: any, b: any, desc: boolean) => 0 | 1 | -1 + + export type Filters = Record, string> + + export interface Cell extends TableInstance { + cell: { value: any } + column: Column + row: Row + render: (type: 'Cell' | 'Aggregated', userProps?: any) => any + isGrouped?: boolean + isAggregated?: boolean + isRepeatedValue?: boolean + getCellProps: () => any + } + + export interface Row { + index: number + cells: Cell[] + getRowProps: (userProps?: any) => any + original: D + path: any[] + values: any[] + depth: number + } + + export interface UseExpandedRow { + subRows?: D[] + groupByID?: string | number + toggleExpanded?: () => any + isExpanded?: boolean + isAggregated?: boolean + } + + export type AccessorFn = ( + originalRow: D, + index: number, + sub: { + subRows: [D] + depth: number + data: [D] } + ) => unknown - export interface Row { - index: number; - cells: Cell[]; - getRowProps: () => any; - original: any; + export interface HeaderColumn { + /** + * This string/function is used to build the data model for your column. + */ + accessor: IdType | AccessorFn + Header?: ReactNode | ((props: TableInstance) => ReactNode) + Filter?: ReactNode | ((props: TableInstance) => ReactNode) + Cell?: ReactNode | ((cell: Cell) => ReactNode) + /** + * This is the unique ID for the column. It is used by reference in things like sorting, grouping, filtering etc. + */ + id?: IdType + minWidth?: string | number + maxWidth?: string | number + width?: string | number + disableSorting?: boolean + canSortBy?: boolean + sortByFn?: SortByFn + defaultSortDesc?: boolean + isAggregated?: any + } + + export interface Column extends HeaderColumn { + show?: boolean | ((instance: TableInstance) => boolean) + columns?: Column[] + } + + export type Page = Row[] + + export interface EnhancedColumn + extends Omit, 'columns'>, + TableInstance { + id: IdType + column: Column + render: (type: 'Header' | 'Filter', userProps?: any) => any + getHeaderProps: (userProps?: any) => any + getSortByToggleProps: (userProps?: any) => any + isSorted: boolean + isSortedDesc: boolean + sortedIndex: number + isVisible: boolean + canSort?: boolean + } + + export interface HeaderGroup { + headers: EnhancedColumn[] + getHeaderGroupProps: (userProps?: any) => any + } + + export interface Hooks { + columnsBeforeHeaderGroups: any[] + columnsBeforeHeaderGroupsDeps: any[] + useMain: any[] + useColumns: any[] + useHeaders: any[] + useHeaderGroups: any[] + useRows: any[] + prepareRow: any[] + getTableProps: any[] + getRowProps: any[] + getHeaderGroupProps: any[] + getHeaderProps: any[] + getCellProps: any[] + } + + export interface RowsProps { + subRowsKey: string + } + + export interface FiltersProps { + filterFn: () => void + manualFilters: boolean + disableFilters: boolean + setFilter: () => any + setAllFilters: () => any + } + + export interface UsePaginationState { + pageIndex: number + pageSize: number + pageCount: number + rowCount: number + } + + export interface UsePaginationValues { + page: Page + pageIndex: number // yes, this is on instance and state + pageSize: number // yes, this is on instance and state + canPreviousPage: boolean + canNextPage: boolean + nextPage: () => any + previousPage: () => any + setPageSize: (size: number) => any + pageOptions: any[] + manualPagination: boolean + paginateExpandedRows: boolean + disablePageResetOnDataChange: boolean + pageCount: number + gotoPage: (page: number) => any + } + + export interface UseFiltersState { + filters?: Filters + } + + export interface UseFiltersValues { + setFilter: (columnID: keyof D, value: string) => void + setAllFilters: (values: Filters) => void + disableFilters: boolean + } + + export interface UseGroupByValues { + groupByFn: any + manualGroupBy: boolean + disableGrouping: boolean + aggregations: any + } + + export interface UseGroupByState { + groupBy: string[] + isAggregated?: boolean + } + + export interface UseExpandedValues { + toggleExpanded?: () => any + } + + export interface UseSortbyOptions { + sortByFn?: SortByFn + manualSorting?: boolean + disableSorting?: boolean + defaultSortDesc?: boolean + disableMultiSort?: boolean + } + + export interface UseSortbyState { + sortBy?: SortingRules + } + + export interface TableInstance extends TableOptions { + hooks: Hooks + rows: Row[] + columns: EnhancedColumn[] + headerGroups: HeaderGroup[] + headers: HeaderGroup[] + getTableProps: (userProps?: any) => any + getRowProps: (userProps?: any) => any + prepareRow: (row: Row) => any + } + + export interface TableOptions { + data: D[] + columns: HeaderColumn[] + state: State + debug?: boolean + loading: boolean + defaultColumn?: Partial> + } + + // The empty definition of TableState is not an error. It provides a definition + // for the state, that can then be extended in the users code. + // + // e.g. + // + // export interface TableState + // extends UsePaginationState, + // UseGroupByState, + // UseSortbyState, + // UseFiltersState {} + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface TableState {} + + export type SetState = ( + updater: (old: TableState) => TableState, + actions: any + ) => void + + export type State = [TableState, SetState] + + export function useTable( + props: TableOptions, + ...plugins: any[] + ): TableInstance + + export function useFilters( + props: TableOptions + ): TableOptions & { + rows: Row[] + } + + export function useSortBy( + props: TableOptions + ): TableOptions & { + rows: Row[] + } + + export function useGroupBy( + props: TableOptions + ): TableOptions & { rows: Row[] } + + export function usePagination( + props: TableOptions + ): UsePaginationValues + + export function useExpanded( + props: TableOptions + ): TableOptions & { + toggleExpandedByPath: () => any + expandedDepth: [] + rows: Row[] + } + + export function useTableState( + initialState?: Partial>, + overriddenState?: Partial>, + options?: { + reducer?: ( + oldState: TableState, + newState: TableState, + type: string + ) => any + useState?: typeof useState } + ): State - export interface HeaderColumn { - /** - * This string/function is used to build the data model for your column. - */ - accessor: A | ((originalRow: D) => string); - Header?: string | ((props: TableInstance) => ReactNode); - Filter?: string | ((props: TableInstance) => ReactNode); - Cell?: string | ((cell: Cell) => ReactNode); + export const actions: Record - /** - * This is the unique ID for the column. It is used by reference in things like sorting, grouping, filtering etc. - */ - id?: string | number; - minWidth?: string | number; - maxWidth?: string | number; - width?: string | number; - canSortBy?: boolean; - sortByFn?: (a: any, b: any, desc: boolean) => 0 | 1 | -1; - defaultSortDesc?: boolean; - } + export function addActions(...actions: string[]): void - export interface Column extends HeaderColumn { - id: string | number; - } - - export type Page = Row[]; - - export interface EnhancedColumn extends Column { - render: (type: string) => any; - getHeaderProps: (userProps?: any) => any; - getSortByToggleProps: (userProps?: any) => any; - sorted: boolean; - sortedDesc: boolean; - sortedIndex: number; - } - - export type HeaderGroup = { - headers: EnhancedColumn[]; - getRowProps: (userProps?: any) => any; - }; - - export interface Hooks { - beforeRender: []; - columns: []; - headerGroups: []; - headers: []; - rows: Row[]; - row: []; - renderableRows: []; - getTableProps: []; - getRowProps: []; - getHeaderRowProps: []; - getHeaderProps: []; - getCellProps: []; - } - - export interface TableInstance - extends TableOptions, - UseRowsValues, - UseFiltersValues, - UsePaginationValues, - UseColumnsValues { - hooks: Hooks; - rows: Row[]; - columns: EnhancedColumn[]; - getTableProps: (userProps?: any) => any; - getRowProps: (userProps?: any) => any; - prepareRow: (row: Row) => any; - getSelectRowToggleProps: (userProps?: any) => any; - toggleSelectAll: (forcedState: boolean) => any; - } - - export interface TableOptions { - data: D[]; - columns: HeaderColumn[]; - state?: [any, Dispatch>]; - debug?: boolean; - sortByFn?: (a: any, b: any, desc: boolean) => 0 | 1 | -1; - manualSorting?: boolean; - disableSorting?: boolean; - defaultSortDesc?: boolean; - disableMultiSort?: boolean; - } - - export interface RowsProps { - subRowsKey: string; - } - - export interface FiltersProps { - filterFn: () => void; - manualFilters: boolean; - disableFilters: boolean; - setFilter: () => any; - setAllFilters: () => any; - } - - export interface UsePaginationValues { - nextPage: () => any; - previousPage: () => any; - setPageSize: (size: number) => any; - gotoPage: (page: number) => any; - canPreviousPage: boolean; - canNextPage: boolean; - page: Page; - pageOptions: []; - } - - export interface UseRowsValues { - rows: Row[]; - } - - export interface UseColumnsValues { - columns: EnhancedColumn[]; - headerGroups: HeaderGroup[]; - headers: EnhancedColumn[]; - } - - export interface UseFiltersValues { - setFilter: () => any; - setAllFilters: () => any; - } - - export function useTable(props: TableOptions, ...plugins: any[]): TableInstance; - - export function useColumns(props: TableOptions): TableOptions & UseColumnsValues; - - export function useRows(props: TableOptions): TableOptions & UseRowsValues; - - export function useFilters( - props: TableOptions, - ): TableOptions & { - rows: Row[]; - }; - - export function useSortBy( - props: TableOptions, - ): TableOptions & { - rows: Row[]; - }; - - export function useGroupBy(props: TableOptions): TableOptions & { rows: Row[] }; - - export function usePagination(props: TableOptions): UsePaginationValues; - - export function useFlexLayout(props: TableOptions): TableOptions; - - export function useExpanded( - props: TableOptions, - ): TableOptions & { - toggleExpandedByPath: () => any; - expandedDepth: []; - rows: []; - }; - - export function useTableState( - initialState?: any, - overriddenState?: any, - options?: { - reducer?: (oldState: any, newState: any, type: string) => any; - useState?: [any, Dispatch>]; - }, - ): any; - - export const actions: any; -} \ No newline at end of file + export const defaultState: Record +}