Compare commits

...
Author SHA1 Message Date
tannerlinsley 488da2ecc5 v7.0.0-beta.2 2019-09-30 07:32:56 -06:00
tannerlinsley 5f0e7cab8b fix: fix colspan prop to use column visibility
Fixes #1555
2019-09-30 07:31:43 -06:00
Nick OomsandTanner Linsley e2e67ed181 Added "in" to make the sentence more readable (#1554) 2019-09-28 06:44:01 -06:00
goldenLunchboxandTanner Linsley c8857a2871 Update api.md (#1551)
The state variable seemed to be missing in the useTable part (row 481) and I felt the need to comment on an additional import being needed.
2019-09-27 05:43:13 -06:00
Tanner LinsleyandGitHub 98583d35f3 Update README.md 2019-09-26 13:28:31 -06:00
tannerlinsley 0a1bf55a2c Merge branch 'master' of https://github.com/react-tools/react-table 2019-09-26 13:23:03 -06:00
tannerlinsley 54b4f8a5d1 v7.0.0-beta.1 2019-09-26 13:22:14 -06:00
tannerlinsley f552c94972 fix(usepagination): fix unstable callbacks
Closes #1549
2019-09-26 13:21:34 -06:00
ggascoigneandTanner Linsley 7ab6385839 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<D = any>
    extends UseFiltersValues<D>,
      UsePaginationValues<D>,
      UseExpandedValues,
      UseGroupByValues {}

  export interface TableState<D = any>
    extends UsePaginationState,
      UseGroupByState,
      UseSortbyState<D>,
      UseFiltersState<D> {}
}
```

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
2019-09-20 09:37:45 -06:00
Tanner LinsleyandGitHub b8ed02cadc Update README.md 2019-09-17 15:44:02 -06:00
Tanner LinsleyandGitHub c3e917f13b Update README.md 2019-09-17 15:42:36 -06:00
tannerlinsley 7e6d719af4 docs(changelog): update changelog 2019-09-13 09:24:24 -06:00
tannerlinsley da678d0a61 Merge branch 'master' of https://github.com/react-tools/react-table 2019-09-13 09:22:09 -06:00
Tanner LinsleyandGitHub c3fe4c7fd8 Update README.md 2019-09-13 09:22:03 -06:00
9 changed files with 364 additions and 227 deletions
+11 -9
View File
@@ -1,7 +1,6 @@
---
name: Bug report
about: Create a report to help us improve
---
# Using v6?
@@ -10,13 +9,14 @@ v6 is now considered feature complete to its current abilities and limitations.
# Using v7?
Thanks for using the alpha version of React Table v7! We're very excited about it.
Thanks for using the beta version of React Table v7! We're very excited about it.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@@ -32,15 +32,17 @@ Use a new [react-table codesandbox](https://codesandbox.io/s/m5lxzzpz69) to repr
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+4
View File
@@ -1,3 +1,7 @@
## 7.0.0-beta.0
- Massive changes to the entire project and library. Please consult the README and documentation for more information regarding these changes.
## 6.8.6
#### Fixes & Optimizations
+8 -4
View File
@@ -7,6 +7,9 @@ Hooks for building **lightweight, fast and extendable datagrids** for React
<a href="https://travis-ci.org/tannerlinsley/react-table" target="\_parent">
<img alt="" src="https://travis-ci.org/tannerlinsley/react-table.svg?branch=master" />
</a>
<a href="https://bundlephobia.com/result?p=react-table@next" target="\_parent">
<img alt="" src="https://badgen.net/bundlephobia/minzip/react-table@next" />
</a>
<a href="https://npmjs.com/package/react-table" target="\_parent">
<img alt="" src="https://img.shields.io/npm/dm/react-table.svg" />
</a>
@@ -30,7 +33,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)
@@ -48,11 +51,11 @@ Hooks for building **lightweight, fast and extendable datagrids** for React
#### What is the current state of React Table?
React Table v7 is still under active development, and its API is still changing, albeit only slightly. For this reason, it is currently in an **alpha** release state. It's estimated that it will be out of alpha and into **beta** sometime during September 2019. It will then remain in beta for a short time before being released sometime in Q4 of 2019.
React Table v7 is still under active development, and its API is still changing, albeit only slightly. For this reason, it is currently in an **beta** release state. It's estimated that it will be fully released as a stable version sometime during October 2019.
#### Should I use v7@alpha in production?
#### Should I use v7@beta in production?
You can use it production as long as you lock in the alpha version in your package.json and also accept that the API will likely change before it's official release.
You can use it in production as long as you lock in the beta version in your package.json and also accept that there may be unlikely, but possible bug fixes and/or API changes before it's official release.
#### I'm still using v6, what should I do?
@@ -172,6 +175,7 @@ The differences between the 2 versions are incredibly massive. Unfortunately, I
<div>Dan Houle</div>
<div>David Pickut</div>
<div>Jordan Soltman</div>
<div>Robert Tajnšek</div>
</td>
</tr>
</tbody>
+2 -1
View File
@@ -475,13 +475,14 @@ The following properties are available on every `Column` object returned by the
```js
function Table({ columns, data }) {
// Set some default sorting state
// Set some default sorting state. For this an additional import of useTableState is needed
const state = useTableState({ sortBy: [{ id: 'firstName', desc: true }] })
const { getTableProps, headerGroups, rows, prepareRow } = useTable(
{
columns,
data,
state,
},
useSortBy // Use the sortBy hook
)
Vendored
+281 -177
View File
@@ -1,184 +1,288 @@
import { Dispatch, SetStateAction, ReactNode } from 'react';
declare module 'react-table' {
export interface Cell<D> {
render: (type: string) => any;
getCellProps: () => any;
column: Column<D>;
row: Row<D>;
state: any;
value: any;
import { ReactNode, useState } from 'react'
type StringKey<D> = Extract<keyof D, string>
type IdType<D> = StringKey<D> | string
type SortingRule<D> = {
id: IdType<D>
desc: boolean
}
export type SortingRules<D> = SortingRule<D>[]
export type SortByFn = (a: any, b: any, desc: boolean) => 0 | 1 | -1
export type Filters<D> = Record<IdType<D>, string>
export interface Cell<D = {}> extends TableInstance<D> {
cell: { value: any }
column: Column<D>
row: Row<D>
render: (type: 'Cell' | 'Aggregated', userProps?: any) => any
isGrouped?: boolean
isAggregated?: boolean
isRepeatedValue?: boolean
getCellProps: () => any
}
export interface Row<D = {}> {
index: number
cells: Cell<D>[]
getRowProps: (userProps?: any) => any
original: D
path: any[]
values: any[]
depth: number
}
export interface UseExpandedRow<D = {}> {
subRows?: D[]
groupByID?: string | number
toggleExpanded?: () => any
isExpanded?: boolean
isAggregated?: boolean
}
export type AccessorFn<D> = (
originalRow: D,
index: number,
sub: {
subRows: [D]
depth: number
data: [D]
}
) => unknown
export interface Row<D> {
index: number;
cells: Cell<D>[];
getRowProps: () => any;
original: any;
export interface HeaderColumn<D> {
/**
* This string/function is used to build the data model for your column.
*/
accessor: IdType<D> | AccessorFn<D>
Header?: ReactNode | ((props: TableInstance<D>) => ReactNode)
Filter?: ReactNode | ((props: TableInstance<D>) => ReactNode)
Cell?: ReactNode | ((cell: Cell<D>) => ReactNode)
/**
* This is the unique ID for the column. It is used by reference in things like sorting, grouping, filtering etc.
*/
id?: IdType<D>
minWidth?: string | number
maxWidth?: string | number
width?: string | number
disableSorting?: boolean
canSortBy?: boolean
sortByFn?: SortByFn
defaultSortDesc?: boolean
isAggregated?: any
}
export interface Column<D> extends HeaderColumn<D> {
show?: boolean | ((instance: TableInstance<D>) => boolean)
columns?: Column<D>[]
}
export type Page<D = {}> = Row<D>[]
export interface EnhancedColumn<D>
extends Omit<Column<D>, 'columns'>,
TableInstance<D> {
id: IdType<D>
column: Column<D>
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<D = {}> {
headers: EnhancedColumn<D>[]
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<D = {}> {
page: Page<D>
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<D> {
filters?: Filters<D>
}
export interface UseFiltersValues<D> {
setFilter: (columnID: keyof D, value: string) => void
setAllFilters: (values: Filters<D>) => 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<D> {
sortBy?: SortingRules<D>
}
export interface TableInstance<D = {}> extends TableOptions<D> {
hooks: Hooks
rows: Row<D>[]
columns: EnhancedColumn<D>[]
headerGroups: HeaderGroup<D>[]
headers: HeaderGroup<D>[]
getTableProps: (userProps?: any) => any
getRowProps: (userProps?: any) => any
prepareRow: (row: Row<D>) => any
}
export interface TableOptions<D = {}> {
data: D[]
columns: HeaderColumn<D>[]
state: State<D>
debug?: boolean
loading: boolean
defaultColumn?: Partial<Column<D>>
}
// 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<D = {}}>
// extends UsePaginationState,
// UseGroupByState,
// UseSortbyState<D>,
// UseFiltersState<D> {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface TableState<D = {}> {}
export type SetState<D> = (
updater: (old: TableState<D>) => TableState<D>,
actions: any
) => void
export type State<D> = [TableState<D>, SetState<D>]
export function useTable<D = {}>(
props: TableOptions<D>,
...plugins: any[]
): TableInstance<D>
export function useFilters<D = {}>(
props: TableOptions<D>
): TableOptions<D> & {
rows: Row<D>[]
}
export function useSortBy<D = {}>(
props: TableOptions<D>
): TableOptions<D> & {
rows: Row<D>[]
}
export function useGroupBy<D = {}>(
props: TableOptions<D>
): TableOptions<D> & { rows: Row<D>[] }
export function usePagination<D = {}>(
props: TableOptions<D>
): UsePaginationValues<D>
export function useExpanded<D = {}>(
props: TableOptions<D>
): TableOptions<D> & {
toggleExpandedByPath: () => any
expandedDepth: []
rows: Row<D>[]
}
export function useTableState<D = {}>(
initialState?: Partial<TableState<D>>,
overriddenState?: Partial<TableState<D>>,
options?: {
reducer?: (
oldState: TableState<D>,
newState: TableState<D>,
type: string
) => any
useState?: typeof useState
}
): State<D>
export interface HeaderColumn<D, A extends keyof D = never> {
/**
* This string/function is used to build the data model for your column.
*/
accessor: A | ((originalRow: D) => string);
Header?: string | ((props: TableInstance<D>) => ReactNode);
Filter?: string | ((props: TableInstance<D>) => ReactNode);
Cell?: string | ((cell: Cell<D>) => ReactNode);
export const actions: Record<string, string>
/**
* 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<D, A extends keyof D = never> extends HeaderColumn<D, A> {
id: string | number;
}
export type Page<D> = Row<D>[];
export interface EnhancedColumn<D, A extends keyof D = never> extends Column<D, A> {
render: (type: string) => any;
getHeaderProps: (userProps?: any) => any;
getSortByToggleProps: (userProps?: any) => any;
sorted: boolean;
sortedDesc: boolean;
sortedIndex: number;
}
export type HeaderGroup<D, A extends keyof D = never> = {
headers: EnhancedColumn<D, A>[];
getRowProps: (userProps?: any) => any;
};
export interface Hooks<D> {
beforeRender: [];
columns: [];
headerGroups: [];
headers: [];
rows: Row<D>[];
row: [];
renderableRows: [];
getTableProps: [];
getRowProps: [];
getHeaderRowProps: [];
getHeaderProps: [];
getCellProps: [];
}
export interface TableInstance<D>
extends TableOptions<D>,
UseRowsValues<D>,
UseFiltersValues,
UsePaginationValues<D>,
UseColumnsValues<D> {
hooks: Hooks<D>;
rows: Row<D>[];
columns: EnhancedColumn<D>[];
getTableProps: (userProps?: any) => any;
getRowProps: (userProps?: any) => any;
prepareRow: (row: Row<D>) => any;
getSelectRowToggleProps: (userProps?: any) => any;
toggleSelectAll: (forcedState: boolean) => any;
}
export interface TableOptions<D> {
data: D[];
columns: HeaderColumn<D>[];
state?: [any, Dispatch<SetStateAction<any>>];
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<D> {
nextPage: () => any;
previousPage: () => any;
setPageSize: (size: number) => any;
gotoPage: (page: number) => any;
canPreviousPage: boolean;
canNextPage: boolean;
page: Page<D>;
pageOptions: [];
}
export interface UseRowsValues<D> {
rows: Row<D>[];
}
export interface UseColumnsValues<D> {
columns: EnhancedColumn<D>[];
headerGroups: HeaderGroup<D>[];
headers: EnhancedColumn<D>[];
}
export interface UseFiltersValues {
setFilter: () => any;
setAllFilters: () => any;
}
export function useTable<D>(props: TableOptions<D>, ...plugins: any[]): TableInstance<D>;
export function useColumns<D>(props: TableOptions<D>): TableOptions<D> & UseColumnsValues<D>;
export function useRows<D>(props: TableOptions<D>): TableOptions<D> & UseRowsValues<D>;
export function useFilters<D>(
props: TableOptions<D>,
): TableOptions<D> & {
rows: Row<D>[];
};
export function useSortBy<D>(
props: TableOptions<D>,
): TableOptions<D> & {
rows: Row<D>[];
};
export function useGroupBy<D>(props: TableOptions<D>): TableOptions<D> & { rows: Row<D>[] };
export function usePagination<D>(props: TableOptions<D>): UsePaginationValues<D>;
export function useFlexLayout<D>(props: TableOptions<D>): TableOptions<D>;
export function useExpanded<D>(
props: TableOptions<D>,
): TableOptions<D> & {
toggleExpandedByPath: () => any;
expandedDepth: [];
rows: [];
};
export function useTableState(
initialState?: any,
overriddenState?: any,
options?: {
reducer?: (oldState: any, newState: any, type: string) => any;
useState?: [any, Dispatch<SetStateAction<any>>];
},
): any;
export const actions: any;
}
export const defaultState: Record<string, any>
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "7.0.0-beta.0",
"version": "7.0.0-beta.2",
"description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -27,7 +27,7 @@
"prepare": "yarn build",
"release": "yarn publish",
"releaseNext": "yarn publish --tag next",
"format": "prettier ./src/**/*.{md,js,jsx,tsx} --write"
"format": "prettier {src,src/**,examples/*/src,examples/*/src/**}/*.{md,js,jsx,tsx} --write"
},
"files": [
"CHANGELOG.md",
+1 -1
View File
@@ -246,7 +246,7 @@ export const useTable = (props, ...plugins) => {
mergeProps(
{
key: ['header', column.id].join('_'),
colSpan: column.totalHeaderCount,
colSpan: column.totalVisibleHeaderCount,
},
applyPropHooks(
instanceRef.current.hooks.getHeaderProps,
+39 -30
View File
@@ -116,39 +116,48 @@ function useMain(instance) {
const canPreviousPage = pageIndex > 0
const canNextPage = pageCount === -1 || pageIndex < pageCount - 1
const gotoPage = pageIndex => {
if (process.env.NODE_ENV === 'development' && debug)
console.info('gotoPage')
return setState(old => {
if (pageIndex < 0 || pageIndex > pageCount - 1) {
return old
}
return {
...old,
pageIndex,
}
}, actions.pageChange)
}
const gotoPage = React.useCallback(
updater => {
if (process.env.NODE_ENV === 'development' && debug)
console.info('gotoPage')
return setState(old => {
const newPageIndex =
typeof updater === 'function' ? updater(old.pageIndex) : updater
const previousPage = () => {
return gotoPage(pageIndex - 1)
}
if (newPageIndex < 0 || newPageIndex > pageCount - 1) {
return old
}
return {
...old,
pageIndex: newPageIndex,
}
}, actions.pageChange)
},
[debug, pageCount, setState]
)
const nextPage = () => {
return gotoPage(pageIndex + 1)
}
const previousPage = React.useCallback(() => {
return gotoPage(old => old - 1)
}, [gotoPage])
const setPageSize = pageSize => {
setState(old => {
const topRowIndex = old.pageSize * old.pageIndex
const pageIndex = Math.floor(topRowIndex / pageSize)
return {
...old,
pageIndex,
pageSize,
}
}, actions.pageSizeChange)
}
const nextPage = React.useCallback(() => {
return gotoPage(old => old + 1)
}, [gotoPage])
const setPageSize = React.useCallback(
pageSize => {
setState(old => {
const topRowIndex = old.pageSize * old.pageIndex
const pageIndex = Math.floor(topRowIndex / pageSize)
return {
...old,
pageIndex,
pageSize,
}
}, actions.pageSizeChange)
},
[setState]
)
return {
...instance,
+16 -3
View File
@@ -182,14 +182,27 @@ export function determineHeaderVisibility(instance) {
: !!column.show
: false
let totalVisibleHeaderCount = 0
if (column.headers && column.headers.length) {
column.headers.forEach(subColumn =>
handleColumn(subColumn, column.isVisible)
column.headers.forEach(
subColumn =>
(totalVisibleHeaderCount += handleColumn(subColumn, column.isVisible))
)
} else {
totalVisibleHeaderCount = column.isVisible ? 1 : 0
}
column.totalVisibleHeaderCount = totalVisibleHeaderCount
return totalVisibleHeaderCount
}
headers.forEach(subHeader => handleColumn(subHeader, true))
let totalVisibleHeaderCount = 0
headers.forEach(
subHeader => (totalVisibleHeaderCount += handleColumn(subHeader, true))
)
}
export function getBy(obj, path, def) {