Compare commits

..
36 Commits
Author SHA1 Message Date
Tanner Linsley 5dd628144c v7.0.0 2020-03-10 13:28:30 -06:00
Tanner Linsley 0d0ce01544 Update README.md 2020-03-10 13:24:50 -06:00
Tanner Linsley afa21b0ad4 Update tests.yml 2020-03-10 13:21:51 -06:00
Tanner Linsley f42300d9e2 Update README.md 2020-03-10 13:21:17 -06:00
Tanner Linsley 920420e330 Workflows, not travis 2020-03-10 13:20:53 -06:00
Tanner Linsley 6482869e8a Fix possible empty page options 2020-03-10 12:05:13 -06:00
Tanner Linsley 42b41d1260 Fix #1944
Fix #1944
2020-03-09 10:43:59 -06:00
Tanner Linsley 3aa016e056 Move default sortBy and orderBy to plugin files 2020-03-09 07:58:42 -06:00
Tanner Linsley bfcc08e7eb Changing filters resets pagination 2020-03-09 06:54:14 -06:00
512f615988 Add disableGlobalFilter prop to allow for columns (and instance) to ignore global filter (#1963)
* size-snapshot created?

* Added `disableGlobalFilter` prop and associated tests

* Updated documentation

* improvement(useglobalfilter): add `disableGlobalFilter` prop

Adding `disableGlobalFilter` prop to both table and column to allow columns to be excluded from
Global Filter

* test(usefilters.test.js): added base test for disableGlobalFilter

Needed a test to make sure that disableGlobalFilter didn't break anything when applied

* Delete .size-snapshot.json

* Update README.md

Co-authored-by: Jason Clark <jason.clark@tcnbroadcasting.com>
Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
2020-03-06 15:49:00 -07:00
RandGitHub 63754a58dd Fixed link in Table Options section (#1950) 2020-03-06 15:41:58 -07:00
Mario RibeiroandGitHub 4a483214ff Update useRowSelect.md (#1948)
Missing documentation for `getToggleRowSelectedProps`, used on the [example](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-selection).

The `indeterminate` field is not documented at all, and I wonder what's the difference to the `checked` field.
2020-03-06 15:31:14 -07:00
GiorgioandGitHub b2af02407b Add additional info for accessor docs (#1943)
Adds additional context on `accessor` field for column options.

### Context

https://github.com/tannerlinsley/react-table/issues/1927
2020-03-06 15:30:43 -07:00
ironicbrewandGitHub b9f7bda223 Updated react-dnd package (#1939)
+ Prevents code sandbox from crashing the dnd example
2020-03-06 15:28:59 -07:00
ta-andersandGitHub acdb28df60 fix(usecolumnvisibility): trigger resetHiddenColumns on columns change (#1938)
fix #1919
2020-03-06 15:28:08 -07:00
Tanner Linsley 34be17b093 Update useRowSelect.js 2020-03-06 15:27:43 -07:00
Mark JonesGitHubboatcoder@gmail.com <Mark Jones>Tanner Linsley
544c30b358 Fixes the RowSelect Reducer #1901 (#1925)
* Fixes the RowSelect Reducer #1901

* Delete .size-snapshot.json

* Delete useFilters.test.js.snap

Co-authored-by: boatcoder@gmail.com <Mark Jones>
Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
2020-03-06 15:25:58 -07:00
343e76ce65 Fix useFlexLayout table min-width (#1924)
* Fix useFlexLayout table min-width

* Delete .size-snapshot.json

Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
2020-03-06 14:57:36 -07:00
Tanner Linsley 23c9ad23fa Remove commitizen and husky for now 2020-03-06 14:54:55 -07:00
Tanner Linsley 9e1a3bfe99 Update package.json 2020-03-06 14:53:14 -07:00
Tanner Linsley 6d4a733a88 Fix row selection when used with global filter
Fixes #1900
Closes #1937
2020-03-06 14:52:29 -07:00
Tanner Linsley c740a0c7af Github action for size tracking, better imports and building 2020-03-06 14:19:15 -07:00
Tanner Linsley 48d6fcd60d Create settings.json 2020-03-06 14:11:25 -07:00
Tanner LinsleyandGitHub 10b84faa29 Update README.md 2020-03-03 14:19:54 -07:00
Tanner LinsleyandGitHub 292bbea1bf Update README.md 2020-02-28 14:46:36 -07:00
size-plugin[bot]andGitHub 2a72667ec1 👩🏾🤝👩🏼 💁🏼‍♂️ update sizes-es.json 👍 2020-02-28 21:45:33 +00:00
size-plugin[bot]andGitHub c92f3fb855 👨‍✈️ 🍇 update sizes-cjs.json 👍 2020-02-28 21:45:32 +00:00
Tanner LinsleyandGitHub fe1c9b4b11 Update README.md 2020-02-28 14:43:58 -07:00
size-plugin[bot]andGitHub e28fa775f2 💎 🧙 update sizes-es.json 👍 2020-02-21 14:05:01 +00:00
size-plugin[bot]andGitHub d9b2a9dc54 👯 🧠 update sizes-cjs.json 👍 2020-02-21 14:05:00 +00:00
73ed7efbe6 useTable: Fixes memoizing of headerGroups (#1920)
Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
2020-02-21 07:04:41 -07:00
7498059e98 useRowSelect: remove redundant checks (#1918)
* useRowSelect: remove redundant checks

* Update useRowSelect.js

Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
2020-02-21 07:03:27 -07:00
Josh StevensandGitHub a52a2e1265 Fix code sandbox for kitchen sink (#1915)
There's an error on this page that says `useGroupBy` must come after `useFilters`
2020-02-21 06:58:41 -07:00
Tanner Linsley facb216f5c Merge branch 'master' of https://github.com/react-tools/react-table 2020-02-15 20:03:38 -07:00
size-plugin[bot]andGitHub b1a31b8176 📬 🇦🇩 update sizes-es.json 👍 2020-02-16 03:03:02 +00:00
size-plugin[bot]andGitHub 5949932e77 🤾🏽 🚴🏿‍♂️ update sizes-cjs.json 👍 2020-02-16 03:03:01 +00:00
41 changed files with 939 additions and 1451 deletions
-27
View File
@@ -1,27 +0,0 @@
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build-and-test:
name: '${{ matrix.platform }}: node.js ${{ matrix.node-version }}'
strategy:
matrix:
platform: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10, 12]
runs-on: ${{ matrix.platform }}
env:
CI: true
steps:
- name: Checkout
uses: actions/checkout@master
- name: Set up Node.js
uses: actions/setup-node@master
with:
node-version: ${{ matrix.node-version }}
- name: Build and test
run: |
yarn install
yarn test
-3
View File
@@ -1,3 +0,0 @@
size-files:
- sizes-cjs.json
- sizes-es.json
+15
View File
@@ -0,0 +1,15 @@
name: Compressed Size
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2-beta
with:
fetch-depth: 1
- uses: preactjs/compressed-size-action@v1
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
+26
View File
@@ -0,0 +1,26 @@
name: react-table tests
on:
push:
branches:
- 'master'
pull_request:
jobs:
test:
name: 'node ${{ matrix.node }} ${{ matrix.os }} '
runs-on: '${{ matrix.os }}'
strategy:
matrix:
os: [ubuntu-latest]
node: [12, 10]
steps:
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- uses: actions/checkout@v2-beta
with:
fetch-depth: 1
- run: npm i -g yarn
- run: yarn --frozen-lockfile
- run: yarn test:ci
+1
View File
@@ -10,5 +10,6 @@ react-table.css
.idea
.DS_Store
.history
.vscode
package-lock.json
coverage
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
hooks: {
'pre-commit': 'lint-staged && yarn test:ci',
// 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
},
}
-40
View File
@@ -1,40 +0,0 @@
{
"dist/index.js": {
"bundled": 130976,
"minified": 61378,
"gzipped": 15745
},
"dist/index.es.js": {
"bundled": 130034,
"minified": 60537,
"gzipped": 15571,
"treeshaked": {
"rollup": {
"code": 80,
"import_statements": 21
},
"webpack": {
"code": 7611
}
}
},
"dist\\index.js": {
"bundled": 113237,
"minified": 52528,
"gzipped": 13837
},
"dist\\index.es.js": {
"bundled": 112300,
"minified": 51692,
"gzipped": 13671,
"treeshaked": {
"rollup": {
"code": 80,
"import_statements": 21
},
"webpack": {
"code": 8461
}
}
}
}
-18
View File
@@ -1,18 +0,0 @@
language: node_js
node_js:
- 10
- 12
os:
- linux
- osx
- windows
env:
global:
- YARN_GPG=no
cache: yarn
script: yarn test
+8
View File
@@ -0,0 +1,8 @@
{
"workbench.colorCustomizations": {
"titleBar.inactiveBackground": "#ff4154", // change this color!
"titleBar.activeBackground": "#ff4154", // change this color!
"titleBar.inactiveForeground": "#ffffff", // change this color!
"titleBar.activeForeground": "#ffffff" // change this color!
}
}
+12
View File
@@ -1,3 +1,15 @@
## 7.0.0 🎉
- Fixed an issue where page options array could be empty
- Fixed an issue where duplicate columns would be silently deduped. There is now a warning when duplicate columns are found based on their IDs
- Moved some functions around so they will get treeshaked with their respective plugins that use them.
- Fixed an issue where filters, sorting, or grouping changes would not reset pagination
- Added table and column level options for disabling global filters
- Fixed an issue where row selection was not deselecting rows
- Fixed an issue where flex table rendering was not giving the table a minimum width with necessary
- Fixed an issue where row selection would not work when using other row-transformative plugins like filters or grouping
- Fixed an issue where header groups were not memoized correctly
## 7.0.0-rc.16
- Moved away from snapshot tests. No more testing implementation details.
+32 -20
View File
@@ -4,16 +4,21 @@
Hooks for building **lightweight, fast and extendable datagrids** for React
[![#TanStack](https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack)](https://twitter.com/intent/tweet?button_hashtag=TanStack)
<!-- [![GitHub Actions CI](https://github.com/tannerlinsley/react-table/workflows/CI/badge.svg)](https://github.com/tannerlinsley/react-table/actions) -->
[![Travis CI](https://travis-ci.org/tannerlinsley/react-table.svg?branch=master)](https://travis-ci.org/tannerlinsley/react-table)
[![Bundlephobia](https://badgen.net/bundlephobia/minzip/react-table@next)](https://bundlephobia.com/result?p=react-table@next)
[![NPM Package](https://img.shields.io/npm/dm/react-table.svg)](https://npmjs.com/package/react-table)
[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/react-table)
[![GitHub Stars](https://img.shields.io/github/stars/tannerlinsley/react-table.svg?style=social&label=Star)](https://github.com/tannerlinsley/react-table)
[![Twitter Followers](https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow)](https://twitter.com/tannerlinsley)
<a href="https://twitter.com/intent/tweet?button_hashtag=TanStack" target="\_parent">
<img alt="#TanStack" src="https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack">
</a><a href="https://github.com/tannerlinsley/react-table/actions?table=workflow%3A%22react-table+tests%22">
<img src="https://github.com/tannerlinsley/react-table/workflows/react-table%20tests/badge.svg" />
</a><a href="https://npmjs.com/package/react-table" target="\_parent">
<img alt="" src="https://img.shields.io/npm/dm/react-table.svg" />
</a><a href="https://bundlephobia.com/result?p=react-table@latest" target="\_parent">
<img alt="" src="https://badgen.net/bundlephobia/minzip/react-table@latest" />
</a><a href="https://spectrum.chat/react-table">
<img alt="Join the community on Spectrum" src="https://withspectrum.github.io/badge/badge.svg" />
</a><a href="https://github.com/tannerlinsley/react-table" target="\_parent">
<img alt="" src="https://img.shields.io/github/stars/tannerlinsley/react-table.svg?style=social&label=Star" />
</a><a href="https://twitter.com/tannerlinsley" target="\_parent">
<img alt="" src="https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow" />
</a>
Enjoy this library? Try them all! [React Query](https://github.com/tannerlinsley/react-query), [React Form](https://github.com/tannerlinsley/react-form), [React Charts](https://github.com/tannerlinsley/react-charts)
@@ -119,6 +124,11 @@ This library is being built and maintained by me, @tannerlinsley and I am always
<a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/silver.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://tripwire.com" target="_blank">
<img width='225' src="https://www.tripwire.com/-/media/tripwiredotcom/icons/tripwire-logo-footer.svg">
</a>
</td>
<td align="center" valign="middle">
<a href="https://github.com/sponsors/tannerlinsley" target="_blank">
@@ -163,16 +173,18 @@ This library is being built and maintained by me, @tannerlinsley and I am always
</td>
<td>
<ul>
<li>Hugo Meissner</li>
<li>Benoit Leger-Derville</li>
<li>Thomas Funk</li>
<li>David Pickut</li>
<li>Jordan Soltman</li>
<li>Robert Tajnšek</li>
<li>Eric Lanehart (@pushred)</li>
<li>Anish P Patel (@anishpatelyaadada)</li>
<li>Alin Porumb (@alinporumb)</li>
<li>Janus Reith (@janus-reith)</li>
<li>Hugo Meissner</li>
<li>Benoit Leger-Derville</li>
<li>Thomas Funk</li>
<li>David Pickut</li>
<li>Jordan Soltman</li>
<li>Robert Tajnšek</li>
<li>Eric Lanehart (@pushred)</li>
<li>Anish P Patel (@anishpatelyaadada)</li>
<li>Alin Porumb (@alinporumb)</li>
<li>Janus Reith (@janus-reith)</li>
<li>Timo Mämecke (@timomeh)</li>
<li>Tyler Reiff (@reiff12)</li>
</ul>
</td>
<td>
-1
View File
@@ -1 +0,0 @@
module.exports = { extends: ['@commitlint/config-conventional'] }
+10
View File
@@ -23,6 +23,8 @@ The following options are supported via the main options object passed to `useTa
- `manualGlobalFilter: Bool`
- Enables filter detection functionality, but does not automatically perform row filtering.
- Turn this on if you wish to implement your own row filter outside of the table (eg. server-side or manual row grouping/nesting)
- `disableGlobalFilter: Bool`
- Disables global filtering for every column in the entire table.
- `filterTypes: Object<filterKey: filterType>`
- Must be **memoized**
- Allows overriding or adding additional filter types for the table to use. If the globalFilter type isn't found on this object, it will default to using the built-in filter types.
@@ -34,6 +36,14 @@ The following options are supported via the main options object passed to `useTa
- To disable, set to `false`
- For more information see the FAQ ["How do I stop my table state from automatically resetting when my data changes?"](./faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
### Column Options
The following options are supported on any `Column` object passed to the `columns` option in `useTable()`
- `disableGlobalFilter: Bool`
- Optional
- If set to `true`, will disable global filtering for this column
### Instance Properties
The following values are provided to the table `instance`:
+1 -1
View File
@@ -34,7 +34,7 @@ The following options are supported via the main options object passed to `useTa
- `manualFilters` is `false` and `state.filters` is changed
- `manualGroupBy` is `false` and `state.groupBy` is changed
- To disable, set to `false`
- For more information see the FAQ ["How do I stop my table state from automatically resetting when my data changes?"](./faq#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
- For more information see the FAQ ["How do I stop my table state from automatically resetting when my data changes?"](../faq.md#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
- `paginateExpandedRows: Bool`
- Optional
- Only applies when using the `useExpanded` plugin hook simultaneously
+7
View File
@@ -58,6 +58,13 @@ The following additional properties are available on every **prepared** `row` ob
- `toggleRowSelected: Function(?set)`
- Use this function to toggle this row's selected state.
- Optionally pass `true` or `false` to set it to that state
- `getToggleRowSelectedProps: Function(props) => props`
- Use this function to get the props needed for a **select row checkbox**.
- Props:
- `onChange: Function()`
- `style.cursor: 'pointer'`
- `checked: Bool`
- `title: 'Toggle Row Selected'`
### Example
+6
View File
@@ -25,6 +25,11 @@ The following options are supported via the main options object passed to `useTa
- Optional
- The initial state object for hidden columns
- If a column's ID is contained in this array, it will be hidden
- `autoResetHiddenColumns: Boolean`
- Defaults to `true`
- When `true`, the `hiddenColumns` state will automatically reset if any of the following conditions are met:
- `columns` is changed
- To disable, set to `false`
- `stateReducer: Function(newState, action, prevState) => newState`
- Optional
- With every action that is dispatched to the table's internal `React.useReducer` instance, this reducer is called and is allowed to modify the final state object for updating.
@@ -73,6 +78,7 @@ The following options are supported on any column object you can pass to `column
- The data returned by an accessor should be **primitive** and sortable.
- If a string is passed, the column's value will be looked up on the original row via that key, eg. If your column's accessor is `firstName` then its value would be read from `row['firstName']`. You can also specify deeply nested values with accessors like `info.hobbies` or even `address[0].street`
- If a function is passed, the column's value will be looked up on the original row using this accessor function, eg. If your column's accessor is `row => row.firstName`, then its value would be determined by passing the row to this function and using the resulting value.
- Technically speaking, this field isn't required if you have a unique `id` for a column. This is used for things like expander or row selection columns. **Warning**: Only omit `accessor` if you really know what you're doing.
- `id: String`
- **Required if `accessor` is a function**
- This is the unique ID for the column. It is used by reference in things like sorting, grouping, filtering etc.
+7 -14
View File
@@ -11,13 +11,12 @@ import makeData from './makeData'
const Styles = styled.div`
padding: 1rem;
${'' /* These styles are suggested for the table fill all available space in its containing element */}
display: block;
${'' /* These styles are required for a horizontaly scrollable table overflow */}
overflow: auto;
.table {
${'' /* These styles are suggested for the table fill all available space in its containing element */}
display: block;
${'' /* These styles are required for a horizontaly scrollable table overflow */}
overflow: auto;
border-spacing: 0;
border: 1px solid black;
@@ -119,13 +118,7 @@ function Table({ columns, data }) {
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable(
const { getTableProps, headerGroups, rows, prepareRow } = useTable(
{
columns,
data,
@@ -195,8 +188,8 @@ function Table({ columns, data }) {
</div>
))}
</div>
<div {...getTableBodyProps()} className="tbody">
{rows.map((row, i) => {
<div className="tbody">
{rows.map(row => {
prepareRow(row)
return (
<div {...row.getRowProps()} className="tr">
+1 -1
View File
@@ -301,8 +301,8 @@ function Table({ columns, data, updateMyData, skipPageReset }) {
// when we edit the data, undefined means using the default
autoResetPage: !skipPageReset,
},
useGroupBy,
useFilters,
useGroupBy,
useSortBy,
useExpanded,
usePagination,
+1 -1
View File
@@ -13,7 +13,7 @@
"react-scripts": "3.0.1",
"react-table": "latest",
"styled-components": "^4.3.2",
"react-dnd": "^9.4.0",
"react-dnd": "^10.0.2",
"react-dnd-html5-backend": "^9.4.0",
"immutability-helper": "^3.0.1"
},
+5
View File
@@ -0,0 +1,5 @@
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/react-table.production.min.js')
} else {
module.exports = require('./dist/react-table.development.js')
}
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
'*.{md,js,ts,jsx,tsx}': ['prettier --write --no-editorconfig', 'git add'],
}
+7 -20
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "7.0.0-rc.16",
"version": "7.0.0",
"description": "Hooks for building lightweight, fast and extendable datagrids for React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -14,10 +14,8 @@
"react-table",
"datagrid"
],
"main": "dist/index.js",
"module": "dist/index.es.js",
"main": "index.js",
"scripts": {
"commit": "git add . && git-cz",
"test": "is-ci \"test:ci\" \"test:dev\"",
"test:dev": "jest --watch",
"test:ci": "yarn test:jest",
@@ -39,27 +37,25 @@
"package.json",
"README.md"
],
"browserslist": "> 0.25%, not dead",
"peerDependencies": {
"react": "^16.8.3",
"react-dom": "^16.8.3"
"react": "^16.8.3"
},
"devDependencies": {
"@babel/core": "^7.7.2",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.7.1",
"@babel/preset-react": "^7.7.0",
"@babel/runtime": "^7.7.2",
"@commitlint/cli": "^8.2.0",
"@commitlint/config-conventional": "^8.2.0",
"@svgr/rollup": "^4.3.3",
"@testing-library/dom": "^6.10.1",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/react-hooks": "^3.2.1",
"babel-eslint": "9.x",
"babel-jest": "^24.9.0",
"commitizen": "^4.0.3",
"core-js": "3.4.1",
"cross-env": "^6.0.3",
"dtslint": "^0.9.8",
"eslint": "6.6.0",
"eslint-config-prettier": "^6.7.0",
"eslint-config-react-app": "^5.0.2",
@@ -74,7 +70,6 @@
"eslint-plugin-react": "7.16.0",
"eslint-plugin-react-hooks": "2.3.0",
"eslint-plugin-standard": "^4.0.1",
"husky": "^3.1.0",
"is-ci-cli": "^2.0.0",
"jest": "^24.9.0",
"jest-cli": "^24.9.0",
@@ -87,6 +82,7 @@
"prop-types": "^15.5.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-test-renderer": "^16.13.0",
"rollup": "^1.27.3",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
@@ -96,14 +92,5 @@
"rollup-plugin-size-snapshot": "^0.10.0",
"rollup-plugin-terser": "^5.1.2",
"serve": "^11.2.0"
},
"config": {
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
},
"browserslist": "> 0.25%, not dead",
"dependencies": {
"@babel/plugin-transform-runtime": "^7.8.3"
}
}
+22 -28
View File
@@ -1,50 +1,44 @@
import babel from 'rollup-plugin-babel'
import commonjs from 'rollup-plugin-commonjs'
import external from 'rollup-plugin-peer-deps-external'
import resolve from 'rollup-plugin-node-resolve'
import { sizeSnapshot } from 'rollup-plugin-size-snapshot'
import { terser } from 'rollup-plugin-terser'
import size from 'rollup-plugin-size'
import pkg from './package.json'
import externalDeps from 'rollup-plugin-peer-deps-external'
const external = ['react']
const globals = {
react: 'React',
}
export default [
{
input: 'src/index.js',
output: {
file: pkg.main,
format: 'cjs',
name: 'ReactQuery',
file: 'dist/react-table.development.js',
format: 'umd',
sourcemap: true,
globals,
},
plugins: [
external(),
babel(),
resolve(),
commonjs(),
size({
publish: true,
exclude: pkg.module,
filename: 'sizes-cjs.json',
writeFile: process.env.CI ? true : false,
}),
sizeSnapshot(),
],
external,
plugins: [babel(), externalDeps()],
},
{
input: 'src/index.js',
output: {
file: pkg.module,
format: 'es',
name: 'ReactQuery',
file: 'dist/react-table.production.min.js',
format: 'umd',
sourcemap: true,
globals,
},
external,
plugins: [
external(),
babel(),
externalDeps(),
terser(),
size({
publish: true,
exclude: pkg.main,
filename: 'sizes-es.json',
writeFile: process.env.CI ? true : false,
writeFile: false,
}),
sizeSnapshot(),
],
},
]
-12
View File
@@ -1,12 +0,0 @@
[
{
"timestamp": 1581795972580,
"files": [
{
"filename": "index.js",
"size": 26248,
"delta": 414
}
]
}
]
-12
View File
@@ -1,12 +0,0 @@
[
{
"timestamp": 1581795982924,
"files": [
{
"filename": "index.es.js",
"size": 26040,
"delta": 407
}
]
}
]
+11
View File
@@ -5,6 +5,7 @@ import {
functionalUpdate,
useGetLatest,
makePropGetter,
useMountedLayoutEffect,
} from '../publicUtils'
actions.resetHiddenColumns = 'resetHiddenColumns'
@@ -147,11 +148,13 @@ function useInstanceBeforeDimensions(instance) {
function useInstance(instance) {
const {
columns,
flatHeaders,
dispatch,
allColumns,
getHooks,
state: { hiddenColumns },
autoResetHiddenColumns = true,
} = instance
const getInstance = useGetLatest(instance)
@@ -197,6 +200,14 @@ function useInstance(instance) {
)
})
const getAutoResetHiddenColumns = useGetLatest(autoResetHiddenColumns)
useMountedLayoutEffect(() => {
if (getAutoResetHiddenColumns()) {
dispatch({ type: actions.resetHiddenColumns })
}
}, [dispatch, columns])
Object.assign(instance, {
allColumnsHidden,
toggleHideColumn,
+63 -91
View File
@@ -9,7 +9,6 @@ import {
unpreparedAccessWarning,
makeHeaderGroups,
decorateColumn,
dedupeBy,
} from '../utils'
import {
@@ -184,7 +183,7 @@ export const useTable = (props, ...plugins) => {
getInstance().allColumns = allColumns
// Access the row model using initial columns
const coreDataModel = React.useMemo(() => {
const [rows, flatRows, rowsById] = React.useMemo(() => {
let rows = []
let flatRows = []
const rowsById = {}
@@ -206,69 +205,18 @@ export const useTable = (props, ...plugins) => {
})
}
return { rows, flatRows, rowsById }
return [rows, flatRows, rowsById]
}, [allColumns, data, getRowId, getSubRows, getHooks, getInstance])
// Allow materialized columns to also access data
const [rows, flatRows, rowsById, materializedColumns] = React.useMemo(() => {
const { rows, flatRows, rowsById } = coreDataModel
const materializedColumns = reduceHooks(
getHooks().materializedColumns,
[],
{
instance: getInstance(),
}
)
materializedColumns.forEach(d => assignColumnAccessor(d))
const materializedColumnsQueue = [...materializedColumns]
while (materializedColumnsQueue.length) {
const column = materializedColumnsQueue.shift()
accessRowsForColumn({
data,
rows,
flatRows,
rowsById,
column,
getRowId,
getSubRows,
accessValueHooks: getHooks().accessValue,
getInstance,
})
}
return [rows, flatRows, rowsById, materializedColumns]
}, [
coreDataModel,
getHooks,
getInstance,
data,
getRowId,
getSubRows,
// eslint-disable-next-line react-hooks/exhaustive-deps
...reduceHooks(getHooks().materializedColumnsDeps, [], {
instance: getInstance(),
}),
])
Object.assign(getInstance(), {
rows,
flatRows,
rowsById,
materializedColumns,
// materializedColumns,
})
loopHooks(getHooks().useInstanceAfterData, getInstance())
// Combine new materialized columns with all columns (dedupe prefers later columns)
allColumns = React.useMemo(
() => dedupeBy([...allColumns, ...materializedColumns], d => d.id),
[allColumns, materializedColumns]
)
getInstance().allColumns = allColumns
// Get the flat list of all columns AFTER the rows
// have been access, and allow hooks to decorate
// those columns (and trigger this memoization via deps)
@@ -290,12 +238,34 @@ export const useTable = (props, ...plugins) => {
)
// Combine new visible columns with all columns (dedupe prefers later columns)
allColumns = React.useMemo(
() => dedupeBy([...allColumns, ...visibleColumns], d => d.id),
[allColumns, visibleColumns]
)
allColumns = React.useMemo(() => {
const columns = [...allColumns]
visibleColumns.forEach(column => {
if (!columns.find(d => d.id === column.id)) {
columns.push(column)
}
})
return columns
}, [allColumns, visibleColumns])
getInstance().allColumns = allColumns
if (process.env.NODE_ENV !== 'production') {
const duplicateColumns = allColumns.filter((column, i) => {
return allColumns.findIndex(d => d.id === column.id) !== i
})
if (duplicateColumns.length) {
console.info(allColumns)
throw new Error(
`Duplicate columns were found with ids: "${duplicateColumns
.map(d => d.id)
.join(', ')}" in the columns array above`
)
}
}
// Make the headerGroups
const headerGroups = React.useMemo(
() =>
@@ -380,40 +350,42 @@ export const useTable = (props, ...plugins) => {
}
)
getInstance().headerGroups = getInstance().headerGroups.filter(
(headerGroup, i) => {
// Filter out any headers and headerGroups that don't have visible columns
headerGroup.headers = headerGroup.headers.filter(column => {
const recurse = headers =>
headers.filter(column => {
if (column.headers) {
return recurse(column.headers)
}
return column.isVisible
}).length
if (column.headers) {
return recurse(column.headers)
getInstance().headerGroups = React.useMemo(
() =>
headerGroups.filter((headerGroup, i) => {
// Filter out any headers and headerGroups that don't have visible columns
headerGroup.headers = headerGroup.headers.filter(column => {
const recurse = headers =>
headers.filter(column => {
if (column.headers) {
return recurse(column.headers)
}
return column.isVisible
}).length
if (column.headers) {
return recurse(column.headers)
}
return column.isVisible
})
// Give headerGroups getRowProps
if (headerGroup.headers.length) {
headerGroup.getHeaderGroupProps = makePropGetter(
getHooks().getHeaderGroupProps,
{ instance: getInstance(), headerGroup, index: i }
)
headerGroup.getFooterGroupProps = makePropGetter(
getHooks().getFooterGroupProps,
{ instance: getInstance(), headerGroup, index: i }
)
return true
}
return column.isVisible
})
// Give headerGroups getRowProps
if (headerGroup.headers.length) {
headerGroup.getHeaderGroupProps = makePropGetter(
getHooks().getHeaderGroupProps,
{ instance: getInstance(), headerGroup, index: i }
)
headerGroup.getFooterGroupProps = makePropGetter(
getHooks().getFooterGroupProps,
{ instance: getInstance(), headerGroup, index: i }
)
return true
}
return false
}
return false
}),
[headerGroups, getInstance, getHooks]
)
getInstance().footerGroups = [...getInstance().headerGroups].reverse()
+2 -2
View File
@@ -3,8 +3,8 @@ export { useTable } from './hooks/useTable'
export { useExpanded } from './plugin-hooks/useExpanded'
export { useFilters } from './plugin-hooks/useFilters'
export { useGlobalFilter } from './plugin-hooks/useGlobalFilter'
export { useGroupBy } from './plugin-hooks/useGroupBy'
export { useSortBy } from './plugin-hooks/useSortBy'
export { useGroupBy, defaultGroupByFn } from './plugin-hooks/useGroupBy'
export { useSortBy, defaultOrderByFn } from './plugin-hooks/useSortBy'
export { usePagination } from './plugin-hooks/usePagination'
export { _UNSTABLE_usePivotColumns } from './plugin-hooks/_UNSTABLE_usePivotColumns'
export { useRowSelect } from './plugin-hooks/useRowSelect'
+154 -6
View File
@@ -52,10 +52,14 @@ const defaultColumn = {
),
}
function App() {
function App(props) {
const [data, setData] = React.useState(makeData)
const columns = React.useMemo(
() => [
const columns = React.useMemo(() => {
if (props.columns) {
return props.columns
}
return [
{
Header: 'Name',
columns: [
@@ -90,9 +94,8 @@ function App() {
},
],
},
],
[]
)
]
}, [props.columns])
const {
getTableProps,
@@ -177,6 +180,8 @@ test('renders a filterable table', async () => {
const globalFilterInput = rendered.getByPlaceholderText('Global search...')
const filterInputs = rendered.getAllByPlaceholderText('Search...')
expect(filterInputs).toHaveLength(6)
fireEvent.change(filterInputs[1], { target: { value: 'l' } })
expect(
rendered
@@ -243,3 +248,146 @@ test('renders a filterable table', async () => {
'firstName: jaylen',
])
})
test('does not filter columns marked as disableFilters', () => {
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
disableFilters: true,
},
{
Header: 'Last Name',
accessor: 'lastName',
disableFilters: true,
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
]
const rendered = render(<App columns={columns} />)
const filterInputs = rendered.getAllByPlaceholderText('Search...')
expect(filterInputs).toHaveLength(4)
// should be Age column
fireEvent.change(filterInputs[0], { target: { value: '45' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: joe'])
fireEvent.change(filterInputs[0], { target: { value: '' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual([
'firstName: tanner',
'firstName: derek',
'firstName: joe',
'firstName: jaylen',
])
})
test('does not filter columns with GlobalFilter if marked disableGlobalFilter', () => {
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
disableGlobalFilter: true,
},
{
Header: 'Last Name',
accessor: 'lastName',
disableGlobalFilter: true,
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
]
const rendered = render(<App columns={columns} />)
const globalFilterInput = rendered.getByPlaceholderText('Global search...')
fireEvent.change(globalFilterInput, { target: { value: '' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual([
'firstName: tanner',
'firstName: derek',
'firstName: joe',
'firstName: jaylen',
])
// global filter shouldn't apply to firstName or lastName
fireEvent.change(globalFilterInput, { target: { value: 'li' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: joe'])
// double check global filter ignore (should ignore joe bergevin)
fireEvent.change(globalFilterInput, { target: { value: 'in' } })
expect(
rendered
.queryAllByRole('row')
.slice(3)
.map(row => Array.from(row.children)[0].textContent)
).toEqual(['firstName: tanner', 'firstName: derek', 'firstName: jaylen'])
})
@@ -0,0 +1,258 @@
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import { useTable } from '../../hooks/useTable'
import { useRowSelect } from '../useRowSelect'
import { useFilters } from '../useFilters'
const dataPiece = [
{
firstName: 'tanner',
lastName: 'linsley',
age: 29,
visits: 100,
status: 'In Relationship',
progress: 50,
},
{
firstName: 'derek',
lastName: 'perkins',
age: 40,
visits: 40,
status: 'Single',
progress: 80,
},
{
firstName: 'jaylen',
lastName: 'linsley',
age: 26,
visits: 99,
status: 'In Relationship',
progress: 70,
},
]
const data = [
...dataPiece,
...dataPiece,
...dataPiece,
...dataPiece,
...dataPiece,
...dataPiece,
]
function Table({ columns, data }) {
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
} = useTable(
{
columns,
data,
defaultColumn,
},
useFilters,
useRowSelect
)
// Render the UI for your table
return (
<>
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>
{column.render('Header')}
{column.canFilter ? column.render('Filter') : null}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map(
(row, i) =>
prepareRow(row) || (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
)
})}
</tr>
)
)}
</tbody>
</table>
<p>
Selected Rows:{' '}
<span data-testid="selected-count">
{Object.keys(state.selectedRowIds).length}
</span>
</p>
<pre>
<code>
{JSON.stringify({ selectedRowIds: state.selectedRowIds }, null, 2)}
</code>
</pre>
</>
)
}
const defaultColumn = {
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
Filter: ({ column: { filterValue, setFilter } }) => (
<input
value={filterValue || ''}
onChange={e => {
setFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
}}
placeholder="Search..."
/>
),
}
const IndeterminateCheckbox = React.forwardRef(
({ indeterminate, ...rest }, ref) => {
const defaultRef = React.useRef()
const resolvedRef = ref || defaultRef
React.useEffect(() => {
resolvedRef.current.indeterminate = indeterminate
}, [resolvedRef, indeterminate])
return <input type="checkbox" ref={resolvedRef} {...rest} />
}
)
function App() {
const columns = React.useMemo(
() => [
{
id: 'selection',
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
Header: ({ getToggleAllRowsSelectedProps }) => (
<div>
<label>
<IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />{' '}
Select All
</label>
</div>
),
// The cell can use the individual row's getToggleRowSelectedProps method
// to the render a checkbox
Cell: ({ row }) => (
<div>
<label>
<IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />{' '}
Select Row
</label>
</div>
),
},
{
id: 'selectedStatus',
Cell: ({ row }) => (
<div>
Row {row.id} {row.isSelected ? 'Selected' : 'Not Selected'}
</div>
),
},
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
},
{
Header: 'Last Name',
accessor: 'lastName',
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
id: 'visits',
Header: 'Visits',
accessor: 'visits',
filter: 'equals',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
],
[]
)
return <Table columns={columns} data={data} />
}
test('Select/Clear All while filtered only affects visible rows', () => {
const { getAllByPlaceholderText, getByLabelText, getByTestId } = render(
<App />
)
const selectedCount = getByTestId('selected-count')
const selectAllCheckbox = getByLabelText('Select All')
const fe = fireEvent
const filterInputs = getAllByPlaceholderText('Search...')
fireEvent.change(filterInputs[3], { target: { value: '40' } })
expect(selectedCount.textContent).toBe('0') // No selection has been made
expect(selectAllCheckbox.checked).toBe(false)
fireEvent.click(selectAllCheckbox)
expect(selectAllCheckbox.checked).toBe(true)
expect(selectedCount.textContent).toBe('6') // "Select All" has happened
// This filter hides all the rows (nothing matches it)
fireEvent.change(filterInputs[3], { target: { value: '10' } })
expect(selectedCount.textContent).toBe('6') // Filtering does not alter the selection
expect(selectAllCheckbox.checked).toBe(false) // None of the selected items are visible, this should be false
fireEvent.click(selectAllCheckbox) // The selection is is for no rows
expect(selectAllCheckbox.checked).toBe(false) // So clicking this checkbox does nothing
expect(selectedCount.textContent).toBe('6') // And does not affect the existing selection
fireEvent.change(filterInputs[3], { target: { value: '100' } })
expect(selectAllCheckbox.checked).toBe(false) // None of the selected items are visible, this should be false
fireEvent.click(selectAllCheckbox)
expect(selectAllCheckbox.checked).toBe(true) // Now all of the visible rows are ALSO selected
expect(selectedCount.textContent).toBe('12') // Clearing all should leave the original 6 selected
// Now deselect all the rows that match the filter
fireEvent.click(selectAllCheckbox)
expect(selectAllCheckbox.checked).toBe(false) // Now all of the visible rows are ALSO selected
expect(selectedCount.textContent).toBe('6') // Clearing all should leave the original 6 selected
fireEvent.change(filterInputs[3], { target: { value: '' } })
expect(selectedCount.textContent).toBe('6') // Clearing the Filter does not alter the selection
expect(selectAllCheckbox.checked).toBe(false) // Only a subset are selected so this button should show indeterminant
fireEvent.click(selectAllCheckbox)
expect(selectAllCheckbox.checked).toBe(true) // Now all of the visible rows are ALSO selected
expect(selectedCount.textContent).toBe(data.length.toString()) // Select All should select ALL of the rows
fireEvent.click(selectAllCheckbox)
expect(selectedCount.textContent).toBe('0') // Select All should now clear ALL of the rows
})
+90 -41
View File
@@ -1,9 +1,11 @@
import React from 'react'
import { renderHook, act } from '@testing-library/react-hooks'
import { render, fireEvent } from '../../../test-utils/react-testing'
import { useTable } from '../../hooks/useTable'
import { usePagination } from '../usePagination'
import { useFilters } from '../useFilters'
const data = [...new Array(1000)].map((d, i) => ({
const data = [...new Array(1000)].fill(null).map((d, i) => ({
firstName: `tanner ${i + 1}`,
lastName: 'linsley',
age: 29,
@@ -12,6 +14,43 @@ const data = [...new Array(1000)].map((d, i) => ({
progress: 50,
}))
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
},
{
Header: 'Last Name',
accessor: 'lastName',
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
]
function Table({ columns, data }) {
const {
getTableProps,
@@ -114,46 +153,6 @@ function Table({ columns, data }) {
}
function App() {
const columns = React.useMemo(
() => [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
},
{
Header: 'Last Name',
accessor: 'lastName',
},
],
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age',
},
{
Header: 'Visits',
accessor: 'visits',
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
],
[]
)
return <Table columns={columns} data={data} />
}
@@ -185,3 +184,53 @@ test('renders a paginated table', () => {
.reverse()[0].children[0].textContent
).toEqual('tanner 30')
})
describe('usePagination', () => {
test('renders a paginated table', () => {
const rendered = render(<App />)
expect(rendered.queryAllByRole('cell')[0].textContent).toEqual('tanner 21')
fireEvent.click(rendered.getByText('>'))
expect(rendered.queryAllByRole('cell')[0].textContent).toEqual('tanner 31')
fireEvent.click(rendered.getByText('>'))
expect(rendered.queryAllByRole('cell')[0].textContent).toEqual('tanner 41')
fireEvent.click(rendered.getByText('>>'))
expect(rendered.queryAllByRole('cell')[0].textContent).toEqual('tanner 991')
fireEvent.click(rendered.getByText('<<'))
expect(rendered.queryAllByRole('cell')[0].textContent).toEqual('tanner 1')
fireEvent.change(rendered.getByTestId('page-size-select'), {
target: { value: 30 },
})
expect(
rendered
.queryAllByRole('row')
.slice(2)
.reverse()[0].children[0].textContent
).toEqual('tanner 30')
})
test('changing filters resets pagination', async () => {
const { result } = renderHook(() =>
useTable(
{
columns,
data,
},
useFilters,
usePagination
)
)
act(() => result.current.nextPage())
act(() => result.current.nextPage())
expect(result.current.state.pageIndex).toEqual(2)
act(() => result.current.visibleColumns[0].setFilter('tanner'))
expect(result.current.state.pageIndex).toEqual(0)
})
})
+7 -9
View File
@@ -237,19 +237,17 @@ function useInstance(instance) {
// We technically could do this recursively in the above loop,
// but that would severely hinder the API for the user, since they
// would be required to do that recursion in some scenarios
filteredRows = filteredRows.map(row => {
filteredRows.forEach(row => {
filteredFlatRows.push(row)
filteredRowsById[row.id] = row
if (!row.subRows) {
return row
}
return {
...row,
subRows:
row.subRows && row.subRows.length > 0
? filterRows(row.subRows, depth + 1)
: row.subRows,
return
}
row.subRows =
row.subRows && row.subRows.length > 0
? filterRows(row.subRows, depth + 1)
: row.subRows
})
return filteredRows
+5 -3
View File
@@ -1,5 +1,5 @@
export function useFlexLayout(hooks) {
hooks.getTableBodyProps.push(getTableBodyProps)
hooks.getTableProps.push(getTableProps)
hooks.getRowProps.push(getRowStyles)
hooks.getHeaderGroupProps.push(getRowStyles)
hooks.getHeaderProps.push(getHeaderProps)
@@ -8,7 +8,7 @@ export function useFlexLayout(hooks) {
useFlexLayout.pluginName = 'useFlexLayout'
const getTableBodyProps = (props, { instance }) => [
const getTableProps = (props, { instance }) => [
props,
{
style: {
@@ -33,7 +33,9 @@ const getHeaderProps = (props, { column }) => [
{
style: {
boxSizing: 'border-box',
flex: column.totalFlexWidth ? `${column.totalFlexWidth} 0 auto` : undefined,
flex: column.totalFlexWidth
? `${column.totalFlexWidth} 0 auto`
: undefined,
minWidth: `${column.totalMinWidth}px`,
width: `${column.totalWidth}px`,
},
+32 -12
View File
@@ -1,6 +1,10 @@
import React from 'react'
import { getFilterMethod, shouldAutoRemoveFilter } from '../utils'
import {
getFilterMethod,
shouldAutoRemoveFilter,
getFirstDefined,
} from '../utils'
import {
actions,
@@ -68,6 +72,7 @@ function useInstance(instance) {
state: { globalFilter: globalFilterValue },
dispatch,
autoResetGlobalFilter = true,
disableGlobalFilter,
} = instance
const setGlobalFilter = React.useCallback(
@@ -105,24 +110,37 @@ function useInstance(instance) {
return rows
}
allColumns.forEach(column => {
const { disableGlobalFilter: columnDisableGlobalFilter } = column
column.canFilter = getFirstDefined(
columnDisableGlobalFilter === true ? false : undefined,
disableGlobalFilter === true ? false : undefined,
true
)
})
const filterableColumns = allColumns.filter(c => c.canFilter === true)
// Filters top level and nested rows
const filterRows = filteredRows => {
return filterMethod(
filteredRows = filterMethod(
filteredRows,
allColumns.map(d => d.id),
filterableColumns.map(d => d.id),
globalFilterValue
).map(row => {
)
filteredRows.forEach(row => {
filteredFlatRows.push(row)
filteredRowsById[row.id] = row
return {
...row,
subRows:
row.subRows && row.subRows.length
? filterRows(row.subRows)
: row.subRows,
}
row.subRows =
row.subRows && row.subRows.length
? filterRows(row.subRows)
: row.subRows
})
return filteredRows
}
return [filterRows(rows), filteredFlatRows, filteredRowsById]
@@ -131,10 +149,11 @@ function useInstance(instance) {
globalFilterValue,
globalFilter,
userFilterTypes,
allColumns,
rows,
flatRows,
rowsById,
allColumns,
disableGlobalFilter,
])
const getAutoResetGlobalFilter = useGetLatest(autoResetGlobalFilter)
@@ -156,5 +175,6 @@ function useInstance(instance) {
flatRows: globalFilteredFlatRows,
rowsById: globalFilteredRowsById,
setGlobalFilter,
disableGlobalFilter,
})
}
+11 -1
View File
@@ -7,7 +7,6 @@ import { getFirstDefined, flattenBy } from '../utils'
import {
actions,
makePropGetter,
defaultGroupByFn,
ensurePluginOrder,
useMountedLayoutEffect,
useGetLatest,
@@ -408,3 +407,14 @@ function prepareRow(row) {
cell.isAggregated = !cell.isGrouped && !cell.isPlaceholder && row.canExpand
})
}
export function defaultGroupByFn(rows, columnId) {
return rows.reduce((prev, row, i) => {
// TODO: Might want to implement a key serializer here so
// irregular column values can still be grouped if needed?
const resKey = `${row.values[columnId]}`
prev[resKey] = Array.isArray(prev[resKey]) ? prev[resKey] : []
prev[resKey].push(row)
return prev
}, {})
}
+8 -9
View File
@@ -89,10 +89,6 @@ function useInstance(instance) {
dispatch,
data,
manualPagination,
manualGlobalFilter,
manualFilters,
manualGroupBy,
manualSortBy,
} = instance
ensurePluginOrder(
@@ -110,10 +106,10 @@ function useInstance(instance) {
}, [
dispatch,
manualPagination ? null : data,
manualGlobalFilter ? null : globalFilter,
manualFilters ? null : filters,
manualGroupBy ? null : groupBy,
manualSortBy ? null : sortBy,
globalFilter,
filters,
groupBy,
sortBy,
])
const pageCount = manualPagination
@@ -121,7 +117,10 @@ function useInstance(instance) {
: Math.ceil(rows.length / pageSize)
const pageOptions = React.useMemo(
() => (pageCount > 0 ? [...new Array(pageCount)].map((d, i) => i) : []),
() =>
pageCount > 0
? [...new Array(pageCount)].fill(null).map((d, i) => i)
: [],
[pageCount]
)
+12 -11
View File
@@ -95,22 +95,23 @@ function reducer(state, action, previousState, instance) {
const selectAll =
typeof setSelected !== 'undefined' ? setSelected : !isAllRowsSelected
if (selectAll) {
const selectedRowIds = {}
// Only remove/add the rows that are visible on the screen
// Leave all the other rows that are selected alone.
const selectedRowIds = Object.assign({}, state.selectedRowIds)
if (selectAll) {
Object.keys(nonGroupedRowsById).forEach(rowId => {
selectedRowIds[rowId] = true
})
return {
...state,
selectedRowIds,
}
} else {
Object.keys(nonGroupedRowsById).forEach(rowId => {
delete selectedRowIds[rowId]
})
}
return {
...state,
selectedRowIds: {},
selectedRowIds,
}
}
@@ -130,15 +131,15 @@ function reducer(state, action, previousState, instance) {
return state
}
let newSelectedRowIds = { ...state.selectedRowIds }
const newSelectedRowIds = { ...state.selectedRowIds }
const handleRowById = id => {
const row = rowsById[id]
if (!row.isGrouped) {
if (!isSelected && shouldExist) {
if (shouldExist) {
newSelectedRowIds[id] = true
} else if (isSelected && !shouldExist) {
} else {
delete newSelectedRowIds[id]
}
}
+14 -1
View File
@@ -5,7 +5,6 @@ import {
ensurePluginOrder,
defaultColumn,
makePropGetter,
defaultOrderByFn,
useGetLatest,
useMountedLayoutEffect,
} from '../publicUtils'
@@ -360,3 +359,17 @@ function useInstance(instance) {
toggleSortBy,
})
}
export function defaultOrderByFn(arr, funcs, dirs) {
return [...arr].sort((rowA, rowB) => {
for (let i = 0; i < funcs.length; i += 1) {
const sortFn = funcs[i]
const desc = dirs[i] === false || dirs[i] === 'desc'
const sortInt = sortFn(rowA, rowB)
if (sortInt !== 0) {
return desc ? -sortInt : sortInt
}
}
return dirs[0] ? rowA.index - rowB.index : rowB.index - rowA.index
})
}
-25
View File
@@ -13,31 +13,6 @@ export const defaultColumn = {
maxWidth: Number.MAX_SAFE_INTEGER,
}
export function defaultOrderByFn(arr, funcs, dirs) {
return [...arr].sort((rowA, rowB) => {
for (let i = 0; i < funcs.length; i += 1) {
const sortFn = funcs[i]
const desc = dirs[i] === false || dirs[i] === 'desc'
const sortInt = sortFn(rowA, rowB)
if (sortInt !== 0) {
return desc ? -sortInt : sortInt
}
}
return dirs[0] ? rowA.index - rowB.index : rowB.index - rowA.index
})
}
export function defaultGroupByFn(rows, columnId) {
return rows.reduce((prev, row, i) => {
// TODO: Might want to implement a key serializer here so
// irregular column values can still be grouped if needed?
const resKey = `${row.values[columnId]}`
prev[resKey] = Array.isArray(prev[resKey]) ? prev[resKey] : []
prev[resKey].push(row)
return prev
}, {})
}
function mergeProps(...propList) {
return propList.reduce((props, next) => {
const { style, className, ...rest } = next
-8
View File
@@ -65,14 +65,6 @@ export function assignColumnAccessor(column) {
return column
}
// Find the depth of the columns
export function dedupeBy(arr, fn) {
return [...arr]
.reverse()
.filter((d, i, all) => all.findIndex(dd => fn(dd) === fn(d)) === i)
.reverse()
}
export function decorateColumn(column, userDefaultColumn) {
if (!userDefaultColumn) {
throw new Error()
+111 -1025
View File
File diff suppressed because it is too large Load Diff