mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
Compare commits
76
Commits
v7.0.0-rc.16
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bb6aa435d | ||
|
|
052633a786 | ||
|
|
25f1fba133 | ||
|
|
ec54c00d26 | ||
|
|
550e055518 | ||
|
|
9b1f670ccd | ||
|
|
0bcf87a216 | ||
|
|
9a8dc0feda | ||
|
|
e0a6a04137 | ||
|
|
428382c17c | ||
|
|
ad3ce36930 | ||
|
|
7c08467ddb | ||
|
|
34d8b77210 | ||
|
|
e949994e9b | ||
|
|
41647dfd35 | ||
|
|
e73199a04d | ||
|
|
0f695e7321 | ||
|
|
354d9bed14 | ||
|
|
d51aac11f3 | ||
|
|
d7cabd9e06 | ||
|
|
4eb430a0cb | ||
|
|
d2acfc4235 | ||
|
|
d0a9b97ed0 | ||
|
|
294193376d | ||
|
|
683bc20b8c | ||
|
|
0db7980add | ||
|
|
2c39bd89e2 | ||
|
|
61e65e84d3 | ||
|
|
e935d349e7 | ||
|
|
60d8244f58 | ||
|
|
e5c2d6ba84 | ||
|
|
689db0755f | ||
|
|
5e875aa6e2 | ||
|
|
73627b8dcb | ||
|
|
813d152b0a | ||
|
|
64b64f7a60 | ||
|
|
581c174301 | ||
|
|
2deb526378 | ||
|
|
aad37b84e5 | ||
|
|
5dfb08c615 | ||
|
|
5dd628144c | ||
|
|
0d0ce01544 | ||
|
|
afa21b0ad4 | ||
|
|
f42300d9e2 | ||
|
|
920420e330 | ||
|
|
6482869e8a | ||
|
|
42b41d1260 | ||
|
|
3aa016e056 | ||
|
|
bfcc08e7eb | ||
|
|
512f615988 | ||
|
|
63754a58dd | ||
|
|
4a483214ff | ||
|
|
b2af02407b | ||
|
|
b9f7bda223 | ||
|
|
acdb28df60 | ||
|
|
34be17b093 | ||
|
|
544c30b358 | ||
|
|
343e76ce65 | ||
|
|
23c9ad23fa | ||
|
|
9e1a3bfe99 | ||
|
|
6d4a733a88 | ||
|
|
c740a0c7af | ||
|
|
48d6fcd60d | ||
|
|
10b84faa29 | ||
|
|
292bbea1bf | ||
|
|
2a72667ec1 | ||
|
|
c92f3fb855 | ||
|
|
fe1c9b4b11 | ||
|
|
e28fa775f2 | ||
|
|
d9b2a9dc54 | ||
|
|
73ed7efbe6 | ||
|
|
7498059e98 | ||
|
|
a52a2e1265 | ||
|
|
facb216f5c | ||
|
|
b1a31b8176 | ||
|
|
5949932e77 |
@@ -3,18 +3,13 @@ name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
# Using v6?
|
||||
|
||||
v6 is now considered feature complete to its current abilities and limitations. We are not actively working to fix any issues for v6 any more. We will, however, merge any non-breaking pull requests submitted to fix anything in v6.
|
||||
|
||||
# Using v7?
|
||||
|
||||
Thanks for using the beta version of React Table v7! We're very excited about it.
|
||||
|
||||
**Describe the bug**
|
||||
**Describe the bug (required)**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
**Provide an example via Codesandbox! (required)**
|
||||
Use a new [react-table codesandbox](https://codesandbox.io/s/m5lxzzpz69) to reproduce the issue.
|
||||
|
||||
**Steps To Reproduce (required)**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
@@ -22,12 +17,9 @@ Steps to reproduce the behavior:
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
**Expected behavior (Recommended)**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Codesandbox!**
|
||||
Use a new [react-table codesandbox](https://codesandbox.io/s/m5lxzzpz69) to reproduce the issue.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
# STOP
|
||||
|
||||
We do not track feature requests through Github. Please use the [Spectrum React Table Forum](https://spectrum.chat/react-table) to talk about new ideas and features.
|
||||
We do not track feature requests through Github. Please use [Github Discussions](https://github.com/tannerlinsley/react-table/discussions) to talk about new ideas and features.
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
---
|
||||
name: Questions, Support & Help
|
||||
about: Looking for help? Need a question answered?
|
||||
|
||||
---
|
||||
|
||||
# STOP
|
||||
|
||||
We do not use Github to track general support. Please use our public support forum at https://spectrum.chat/react-table.
|
||||
We do not use Github to track general support. Please use our public support forum at https://github.com/tannerlinsley/react-table/discussions.
|
||||
|
||||
NOTE: If a support/help/question issue is opened, it will be closed immediately and be redirected to the forum. Thanks for helping us keep our issues clean and productive!
|
||||
|
||||
@@ -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
|
||||
@@ -1,3 +0,0 @@
|
||||
size-files:
|
||||
- sizes-cjs.json
|
||||
- sizes-es.json
|
||||
@@ -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 }}'
|
||||
@@ -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
|
||||
@@ -10,5 +10,7 @@ react-table.css
|
||||
.idea
|
||||
.DS_Store
|
||||
.history
|
||||
.vscode
|
||||
package-lock.json
|
||||
coverage
|
||||
.docz
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
hooks: {
|
||||
'pre-commit': 'lint-staged && yarn test:ci',
|
||||
// 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
|
||||
},
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
Vendored
+8
@@ -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!
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,41 @@
|
||||
---
|
||||
name: Changelog
|
||||
route: /changelog
|
||||
---
|
||||
|
||||
# React Table Changelog
|
||||
|
||||
## 7.0.4
|
||||
|
||||
- Fixed a regression where @scarf/scarf was somehow removed from the package dependencies
|
||||
|
||||
## 7.0.3
|
||||
|
||||
- Fixed an issue where unnecessary documentation dependencies were added when installing the library
|
||||
- Fixed an issue where the `scripts` directory was not added to the npm package on build
|
||||
|
||||
## 7.0.2
|
||||
|
||||
- Fixed an issue where the internal flexRenderer would not work correctly in production due to the strangest friggin' minification bug I've ever encountered. 🤷♂️
|
||||
|
||||
## 7.0.1
|
||||
|
||||
- Added the `value` property to cell renderers so that destructurin the value from the `cell` property is now not necessary. This should help with people migrating from v6 and also just to cut down on noise in cell renderers
|
||||
- Fixed an issue where rollup would not build correctly
|
||||
- Fixed an issue where a page index of `-1` would result in an error
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: Code of Conduct
|
||||
route: /code-of-conduct
|
||||
---
|
||||
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
+8
-3
@@ -1,12 +1,17 @@
|
||||
---
|
||||
name: Contributing
|
||||
route: /contributing
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
## Questions
|
||||
|
||||
If you have questions about implementation details, help or support, then please use our dedicated community forum at [Spectrum.chat/react-table](https://spectrum.chat/react-table) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum.
|
||||
If you have questions about implementation details, help or support, then please use our dedicated community forum at [Github Discussions](https://github.com/tannerlinsley/react-table/discussions) **PLEASE NOTE:** If you choose to instead open an issue for your question, your issue will be immediately closed and redirected to the forum.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you have found what you think is a bug, please [file an issue](https://github.com/tannerlinsley/react-table/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [Spectrum.chat/react-table](https://spectrum.chat/react-table)
|
||||
If you have found what you think is a bug, please [file an issue](https://github.com/tannerlinsley/react-table/issues/new). **PLEASE NOTE:** Issues that are identified as implementation questions or non-issues will be immediately closed and redirected to [Github Discussions](https://github.com/tannerlinsley/react-table/discussions)
|
||||
|
||||
## Suggesting new features
|
||||
|
||||
@@ -23,6 +28,6 @@ If you have been assigned to fix an issue or develop a new feature, please follo
|
||||
- Implement your changes and tests to files in the `src/` directory and corresponding test files
|
||||
- To run examples, follow their individual directions. Usually this is just `$ yarn && yarn start`.
|
||||
- To run examples using your local build, link to the local `react-table` by running `$ yarn link react-table` from the example's directory
|
||||
- Document your changes in the root `README.md`
|
||||
- Document your changes in the appropriate doc page
|
||||
- To stage a commit, run `yarn commit`
|
||||
- Submit PR for review
|
||||
|
||||
@@ -1,19 +1,29 @@
|
||||
---
|
||||
name: Getting Started
|
||||
route: /
|
||||
---
|
||||
|
||||

|
||||
|
||||
<img src='https://github.com/tannerlinsley/react-table/raw/master/media/logo.png' width='300'/>
|
||||
|
||||
Hooks for building **lightweight, fast and extendable datagrids** for React
|
||||
|
||||
[](https://twitter.com/intent/tweet?button_hashtag=TanStack)
|
||||
|
||||
<!-- [](https://github.com/tannerlinsley/react-table/actions) -->
|
||||
|
||||
[](https://travis-ci.org/tannerlinsley/react-table)
|
||||
[](https://bundlephobia.com/result?p=react-table@next)
|
||||
[](https://npmjs.com/package/react-table)
|
||||
[](https://spectrum.chat/react-table)
|
||||
[](https://github.com/tannerlinsley/react-table)
|
||||
[](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://github.com/tannerlinsley/react-table/discussions">
|
||||
<img alt="Join the discussion on Github" src="https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue" />
|
||||
</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)
|
||||
|
||||
@@ -21,7 +31,7 @@ Enjoy this library? Try them all! [React Query](https://github.com/tannerlinsley
|
||||
|
||||
## Features
|
||||
|
||||
- Lightweight (5kb - 12kb+ depending on features used and tree-shaking)
|
||||
- Lightweight (5kb - 14kb+ depending on features used and tree-shaking)
|
||||
- Headless (100% customizable, Bring-your-own-UI)
|
||||
- Auto out of the box, fully controllable API
|
||||
- Sorting (Multi and Stable)
|
||||
@@ -38,14 +48,7 @@ Enjoy this library? Try them all! [React Query](https://github.com/tannerlinsley
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Installation](./docs/installation.md) - Walk through how to install React Table
|
||||
- [Concepts](./docs/concepts.md) - Read how React Table works and how you can use it better
|
||||
- [Examples](./docs/examples.md) - Experience and learn from some examples and guides of how to use React Table and implement common patterns
|
||||
- [API](./docs/api/README.md) - Get to know React Table's API
|
||||
- [FAQ](./docs/faq.md) - Learn how to use React Table for specific challenges and tasks
|
||||
- [Previous Versions](#previous-versions)
|
||||
- [Contributing](./CONTRIBUTING.md) - Become familiar with how to contribute back to React Table
|
||||
- [Code of Conduct](./CODE_OF_CONDUCT.md) - Be a good React Table citizen by following these repository rules
|
||||
Visit our new documentation site at https://react-table.js.org
|
||||
|
||||
## Sponsors
|
||||
|
||||
@@ -56,7 +59,7 @@ This library is being built and maintained by me, @tannerlinsley and I am always
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://github.com/sponsors/tannerlinsley" target="_blank">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/diamond.png">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/diamond.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
@@ -73,12 +76,12 @@ This library is being built and maintained by me, @tannerlinsley and I am always
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/platinum.png">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/platinum.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://tryretool.com/?utm_source=sponsor&utm_campaign=react_table" target="_blank">
|
||||
<img width='225' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/sponsor-retool.png">
|
||||
<img width='300' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/sponsor-retool.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
@@ -95,12 +98,12 @@ This library is being built and maintained by me, @tannerlinsley and I am always
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/gold.png">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/gold.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://nozzle.io" target="_blank">
|
||||
<img width='225' src="https://nozzle.io/img/logo-blue.png">
|
||||
<img width='225' src="https://nozzle.io/img/logo-blue.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
@@ -117,7 +120,17 @@ This library is being built and maintained by me, @tannerlinsley and I am always
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://github.com/sponsors/tannerlinsley/" target="_blank">
|
||||
<img width='150' src="https://raw.githubusercontent.com/tannerlinsley/files/master/images/patreon/silver.png">
|
||||
<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='170' src="https://www.tripwire.com/-/media/tripwiredotcom/icons/tripwire-logo-footer.svg" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.fream.pl/" target="_blank">
|
||||
<img width='170' src="https://www.fream.pl/wp-content/uploads/2017/08/logo.png" />
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
@@ -163,16 +176,19 @@ 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>
|
||||
<li>Matt Stvartak (@mattstvartak)</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] }
|
||||
@@ -1 +0,0 @@
|
||||
To get started with React Table, [click here](../README.md), or select a specific document from this directory.
|
||||
+22
-16
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: Overview
|
||||
route: /api
|
||||
menu: API
|
||||
---
|
||||
|
||||
# API
|
||||
|
||||
React Table uses React Hooks both internally and externally for almost all of its configuration and lifecycle management. Naturally, this is what allows React Table to be headless and lightweight while still having a concise and simple API.
|
||||
@@ -5,24 +11,24 @@ React Table uses React Hooks both internally and externally for almost all of it
|
||||
React Table is essentially a compatible collection of **custom React hooks**:
|
||||
|
||||
- The primary React Table hook
|
||||
- [`useTable`](./useTable.md)
|
||||
- [`useTable`](./api/useTable)
|
||||
- Plugin Hooks
|
||||
- Core Plugin Hooks
|
||||
- [`useGroupBy`](./useGroupBy.md)
|
||||
- [`useFilters`](./useFilters.md)
|
||||
- [`useGlobalFilter`](./useGlobalFilter.md)
|
||||
- [`useSortBy`](./useSortBy.md)
|
||||
- [`useExpanded`](./useExpanded.md)
|
||||
- [`usePagination`](./usePagination.md)
|
||||
- [`useTokenPagination` (Coming Soon)](./useTokenPagination.md)
|
||||
- [`useRowSelect`](./useRowSelect.md)
|
||||
- [`useRowState`](./useRowState.md)
|
||||
- [`useColumnOrder`](./useColumnOrder.md)
|
||||
- [`useGroupBy`](./api/useGroupBy)
|
||||
- [`useFilters`](./api/useFilters)
|
||||
- [`useGlobalFilter`](./api/useGlobalFilter)
|
||||
- [`useSortBy`](./api/useSortBy)
|
||||
- [`useExpanded`](./api/useExpanded)
|
||||
- [`usePagination`](./api/usePagination)
|
||||
- [`useTokenPagination` (Coming Soon)](./api/useTokenPagination)
|
||||
- [`useRowSelect`](./api/useRowSelect)
|
||||
- [`useRowState`](./api/useRowState)
|
||||
- [`useColumnOrder`](./api/useColumnOrder)
|
||||
- Layout Hooks
|
||||
- [`useBlockLayout`](./useBlockLayout.md)
|
||||
- [`useAbsoluteLayout`](./useAbsoluteLayout.md)
|
||||
- [`useFlexLayout`](./useFlexLayout.md)
|
||||
- [`useResizeColumns`](./useResizeColumns.md)
|
||||
- [`useBlockLayout`](./api/useBlockLayout)
|
||||
- [`useAbsoluteLayout`](./api/useAbsoluteLayout)
|
||||
- [`useFlexLayout`](./api/useFlexLayout)
|
||||
- [`useResizeColumns`](./api/useResizeColumns)
|
||||
- 3rd Party Plugin Hooks
|
||||
- Want your custom plugin hook listed here? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
|
||||
@@ -65,4 +71,4 @@ The order and usage of plugin hooks must follow The Laws of Hooks, just like any
|
||||
|
||||
### Option Memoization
|
||||
|
||||
React Table relies on memoization to determine when state and side effects should update or be calculated. This means that every option you pass to `useTable` should be memoized either via `React.useMemo` (for objects) or `React.useCallback` (for functions).
|
||||
React Table relies on memoization to determine when state and side effects should update or be calculated. This means that every option you pass to `useTable` should be memoized either via [`React.useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) (for objects) or [`React.useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback) (for functions).
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useAbsoluteLayout
|
||||
route: /api/useAbsoluteLayout
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useAbsoluteLayout`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useBlocklayout
|
||||
route: /api/useBlocklayout
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useBlocklayout`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useColumnOrder
|
||||
route: /api/useColumnOrder
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useColumnOrder`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useExpanded
|
||||
route: /api/useExpanded
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useExpanded`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -33,7 +39,7 @@ The following options are supported via the main options object passed to `useTa
|
||||
- When `true`, the `expanded` state will automatically reset if any of the following conditions are met:
|
||||
- `data` 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.md#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#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
|
||||
|
||||
### Instance Properties
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useFilters
|
||||
route: /api/useFilters
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useFilters`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -30,7 +36,7 @@ The following options are supported via the main options object passed to `useTa
|
||||
- When `true`, the `filters` state will automatically reset if any of the following conditions are met:
|
||||
- `data` 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#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
|
||||
|
||||
### Column Options
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useFlexLayout
|
||||
route: /api/useFlexLayout
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useFlexLayout`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useGlobalFilter
|
||||
route: /api/useGlobalFilter
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useGlobalFilter`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -23,6 +29,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 +42,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,3 +1,9 @@
|
||||
---
|
||||
name: useGroupBy
|
||||
route: /api/useGroupBy
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useGroupBy`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: usePagination
|
||||
route: /api/usePagination
|
||||
menu: API
|
||||
---
|
||||
# `usePagination`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -34,7 +39,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#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
|
||||
@@ -81,5 +86,5 @@ The following values are provided to the table `instance`:
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- Controlled Pagination
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useResizeColumns
|
||||
route: /api/useResizeColumns
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useResizeColumns`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useRowSelect
|
||||
route: /api/useRowSelect
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useRowSelect`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -58,6 +64,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
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useRowState
|
||||
route: /api/useRowState
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useRowState`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useSortBy
|
||||
route: /api/useSortBy
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useSortBy`
|
||||
|
||||
- Plugin Hook
|
||||
@@ -49,7 +55,7 @@ The following options are supported via the main options object passed to `useTa
|
||||
- When `true`, the `sortBy` state will automatically reset if any of the following conditions are met:
|
||||
- `data` 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.md#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#how-do-i-stop-my-table-state-from-automatically-resetting-when-my-data-changes)
|
||||
|
||||
### Column Options
|
||||
|
||||
|
||||
+14
-2
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useTable
|
||||
route: /api/useTable
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useTable`
|
||||
|
||||
- Required
|
||||
@@ -25,6 +31,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.
|
||||
@@ -35,7 +46,7 @@ The following options are supported via the main options object passed to `useTa
|
||||
- If you need to control part of the table state, this is the place to do it.
|
||||
- This function is run on every single render, just like a hook and allows you to alter the final state of the table if necessary.
|
||||
- You can use hooks inside of this function, but most of the time, we just suggest using `React.useMemo` to memoize your state overrides.
|
||||
- See the FAQ ["How can I manually control the table state?"](../faq.md#how-can-i-manually-control-the-table-state) for a an example.
|
||||
- See the FAQ ["How can I manually control the table state?"](/faq#how-can-i-manually-control-the-table-state) for a an example.
|
||||
- `defaultColumn: Object`
|
||||
- Optional
|
||||
- Defaults to `{}`
|
||||
@@ -73,6 +84,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.
|
||||
@@ -89,7 +101,7 @@ The following options are supported on any column object you can pass to `column
|
||||
- If a function/component is passed, it will be used for formatting the header value, eg. You can use a `Header` function to dynamically format the header using any table or column state.
|
||||
- `Cell: Function | React.Component => JSX`
|
||||
- Optional
|
||||
- Defaults to `({ cell: { value } }) => String(value)`
|
||||
- Defaults to `({ value }) => String(value)`
|
||||
- Receives the table instance and cell model as props
|
||||
- Must return valid JSX
|
||||
- This function (or component) is primarily used for formatting the column value, eg. If your column accessor returns a date object, you can use a `Cell` function to format that date to a readable format.
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
---
|
||||
name: useTokenPagination
|
||||
route: /api/useTokenPagination
|
||||
menu: API
|
||||
---
|
||||
|
||||
# `useTokenPagination (Coming Soon)`
|
||||
|
||||
- Plugin Hook
|
||||
|
||||
+9
-4
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: Concepts
|
||||
route: /concepts
|
||||
---
|
||||
|
||||
# Concepts
|
||||
|
||||
## React Table is a "headless" UI library
|
||||
@@ -23,11 +28,11 @@ At the heart of every React Table is the `useTable` hook and the table `instance
|
||||
|
||||
## Rendering your own UI
|
||||
|
||||
As of React Table v7, **you the developer** are responsible for rendering your own UI, but don't let that intimidate you! Table UIs are fun and React Table makes it so easy to wire up your own table UI. The easiest way to learn how to build your own table UI is to [see some existing React Table examples](./examples.md)!
|
||||
As of React Table v7, **you the developer** are responsible for rendering your own UI, but don't let that intimidate you! Table UIs are fun and React Table makes it so easy to wire up your own table UI. The easiest way to learn how to build your own table UI is to [see some existing React Table examples](./examples)!
|
||||
|
||||
---
|
||||
|
||||
After reading about React Table's concepts, you should:
|
||||
|
||||
- [Check Out Some Examples](./examples.md)
|
||||
- [Study the API](./api/README.md)
|
||||
- [Follow the Quick Start](./quickstart)
|
||||
- [Check Out Some Examples](./examples)
|
||||
- [Study the API](./api)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
# Examples
|
||||
|
||||
- **Simple** - All of these examples use automatic state management, meaning, they don't hoist any state out of the table or manually control anything. Start here for understanding the basics about how to build your table UI.
|
||||
- Basic
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/basic)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/basic)
|
||||
- Footers
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/footers)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/footers)
|
||||
- Sorting
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/sorting)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sorting)
|
||||
- Filtering
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/filtering)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/filtering)
|
||||
- Grouping
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/grouping)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/grouping)
|
||||
- Grouping (Single Column)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/grouping-column)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/grouping-column)
|
||||
- Pagination
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- Row Selection
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/row-selection)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-selection)
|
||||
- Expanding
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/expanding)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/expanding)
|
||||
- Sub Components
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/sub-components)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sub-components)
|
||||
- Editable Data
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/editable-data)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/editable-data)
|
||||
- Column Ordering
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-ordering)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-ordering)
|
||||
- Column Hiding
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-hiding)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-hiding)
|
||||
- Column Resizing
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-resizing)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-resizing)
|
||||
- Data-Driven Classes and Styles
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles)
|
||||
- Row DnD
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/row-dnd)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-dnd)
|
||||
- Full Width Table (Table Elements with collapsible content)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/full-width-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/full-width-table)
|
||||
- Full Width Resizable Table (via `useFlexLayout`)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/full-width-resizable-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/full-width-resizable-table)
|
||||
- **Complex**
|
||||
- The "Kitchen Sink"
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/kitchen-sink)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink)
|
||||
- **Controlled** - These examples are more advanced because they demonstrate how to manually control and respond to the state of the table.
|
||||
- Pagination (Controlled)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
- [Open in CodeSandobx](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
- **UI & Rendering** - These examples demonstrate how to use React Table with your favorite UI libraries or tools!
|
||||
- Virtualized Rows (React-Window)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/virtualized-rows)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/virtualized-rows)
|
||||
- Animated (Framer-Motion)
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/animated-framer-motion)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/animated-framer-motion)
|
||||
- Material-UI
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/material-UI-components)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/material-UI-components)
|
||||
- Material-UI Enhanced Table
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/material-UI-enhanced-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/material-UI-enhanced-table)
|
||||
- [ ] Styled-Components
|
||||
- [ ] CSS
|
||||
- [ ] Bootstrap
|
||||
- Want to write one of these examples or add another? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Examples
|
||||
route: /examples
|
||||
---
|
||||
|
||||
# Examples
|
||||
|
||||
- [**Simple**](./examples/simple) - All of these examples use automatic state management, meaning, they don't hoist any state out of the table or manually control anything. Start here for understanding the basics about how to build your table UI.
|
||||
|
||||
- [**Complex**](./examples/complex) - These examples are more advanced because they demonstrate how to manually control and respond to the state of the table.
|
||||
|
||||
- [**Controlled**](./examples/controlled) - These examples are more advanced because they demonstrate how to manually control and respond to the state of the table.
|
||||
|
||||
- [**UI & Rendering**](./examples/ui) - These examples demonstrate how to use React Table with your favorite UI libraries or tools!
|
||||
|
||||
* Want to add another example? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: Complex
|
||||
route: /examples/complex
|
||||
menu: Examples
|
||||
---
|
||||
|
||||
# Complex
|
||||
|
||||
These examples are more advanced because they demonstrate how to manually control and respond to the state of the table.
|
||||
|
||||
## The "Kitchen Sink"
|
||||
|
||||
This example includes Pagination, Sorting, Filtering, Grouping, Expandable Rows and Row Selection so it's called the _Kitchen Sink_.
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/kitchen-sink)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/kitchen-sink?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: kitchen-sink"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
* Want to add another example? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Controlled
|
||||
route: /examples/controlled
|
||||
menu: Examples
|
||||
---
|
||||
|
||||
# Controlled
|
||||
|
||||
These examples are more advanced because they demonstrate how to manually control and respond to the state of the table.
|
||||
|
||||
## Pagination (Controlled)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/pagination-controlled)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/pagination-controlled?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: pagination-controlled"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
* Want to add another example? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
name: Simple
|
||||
route: /examples/simple
|
||||
menu: Examples
|
||||
---
|
||||
|
||||
# Simple
|
||||
|
||||
All of these examples use automatic state management, meaning, they don't hoist any state out of the table or manually control anything. Start here for understanding the basics about how to build your table UI.
|
||||
|
||||
## Basic
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/basic)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/basic)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/basic?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: basic"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
## Footers
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/footers)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/footers)
|
||||
|
||||
## Sorting
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/sorting)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/sorting)
|
||||
|
||||
## Filtering
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/filtering)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/filtering)
|
||||
|
||||
## Grouping
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/grouping)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/grouping)
|
||||
|
||||
## Grouping (Single Column)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/grouping-column)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/grouping-column)
|
||||
|
||||
## Pagination
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/pagination)
|
||||
|
||||
## Row Selection
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/row-selection)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/row-selection)
|
||||
|
||||
## Expanding
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/expanding)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/sub-components)
|
||||
|
||||
## Sub Components
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/sub-components)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/sub-components)
|
||||
|
||||
## Editable Data
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/editable-data)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/editable-data)
|
||||
|
||||
## Column Ordering
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-ordering)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-ordering)
|
||||
|
||||
## Column Hiding
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-hiding)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-hiding)
|
||||
|
||||
## Column Resizing
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/column-resizing)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/column-resizing)
|
||||
|
||||
## Data-Driven Classes and Styles
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/data-driven-classes-and-styles)
|
||||
|
||||
## Row DnD
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/row-dnd)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/row-dnd)
|
||||
|
||||
## Full Width Table (Table Elements with collapsible content)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/full-width-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/full-width-table)
|
||||
|
||||
## Full Width Resizable Table (via `useFlexLayout`)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/full-width-resizable-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/full-width-resizable-table)
|
||||
|
||||
* Want to add another example? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
name: UI/Rendering
|
||||
route: /examples/ui
|
||||
menu: Examples
|
||||
---
|
||||
|
||||
# UI and Rendering
|
||||
|
||||
These examples demonstrate how to use React Table with your favorite UI libraries or tools!
|
||||
|
||||
## Virtualized Rows (React-Window)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/virtualized-rows)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/virtualized-rows)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/virtualized-rows?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: virtualized-rows"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
## Animated (Framer-Motion)
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/animated-framer-motion)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/animated-framer-motion)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/animated-framer-motion?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: animated-framer-motion"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
## Material-UI
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/material-UI-components)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/material-UI-components)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/material-UI-components?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: material-UI-components"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
## Material-UI Enhanced Table
|
||||
|
||||
- [Source](https://github.com/tannerlinsley/react-table/tree/master/examples/material-UI-enhanced-table)
|
||||
- [Open in CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/material-UI-enhanced-table)
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/github/tannerlinsley/react-table/tree/master/examples/material-UI-enhanced-table?autoresize=1&fontsize=14&module=%2Fsrc%2FApp.js&theme=dark"
|
||||
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
|
||||
title="tannerlinsley/react-table: material-UI-enhanced-table"
|
||||
allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb"
|
||||
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
||||
></iframe>
|
||||
|
||||
## Todo
|
||||
|
||||
- [ ] Styled-Components
|
||||
- [ ] CSS
|
||||
- [ ] Bootstrap
|
||||
|
||||
* Want to write one of these examples or add another? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
|
||||
+12
-7
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: FAQ
|
||||
route: /faq
|
||||
---
|
||||
|
||||
# FAQ
|
||||
|
||||
Below are some of the most frequently asked questions on how to use the React Table API to solve various table challenges you may encounter
|
||||
@@ -108,13 +113,13 @@ React.useEffect(() => {
|
||||
|
||||
useTable({
|
||||
...
|
||||
autoResetPage: !skipPageReset,
|
||||
autoResetExpanded: !skipPageReset,
|
||||
autoResetGroupBy: !skipPageReset,
|
||||
autoResetSelectedRows: !skipPageReset,
|
||||
autoResetSortBy: !skipPageReset,
|
||||
autoResetFilters: !skipPageReset,
|
||||
autoResetRowState: !skipPageReset,
|
||||
autoResetPage: !skipPageResetRef.current,
|
||||
autoResetExpanded: !skipPageResetRef.current,
|
||||
autoResetGroupBy: !skipPageResetRef.current,
|
||||
autoResetSelectedRows: !skipPageResetRef.current,
|
||||
autoResetSortBy: !skipPageResetRef.current,
|
||||
autoResetFilters: !skipPageResetRef.current,
|
||||
autoResetRowState: !skipPageResetRef.current,
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
+12
-1
@@ -1,3 +1,8 @@
|
||||
---
|
||||
name: Installation
|
||||
route: /installation
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
Install React Table as a dependency using `npm` or `yarn`
|
||||
@@ -10,6 +15,12 @@ $ npm install react-table
|
||||
$ yarn add react-table
|
||||
```
|
||||
|
||||
React Table uses [Scarf](https://www.npmjs.com/package/@scarf/scarf) to collect
|
||||
anonymized installation analytics. These anlytics help support the maintainers
|
||||
of this library. However, if you'd like to opt out, you can do so by setting the
|
||||
environment variable `SCARF_ANALYTICS=false` before you install, or by setting
|
||||
`scarfSettings.enabled = false` in your project's `package.json`
|
||||
|
||||
To import React Table:
|
||||
|
||||
```js
|
||||
@@ -24,4 +35,4 @@ import {
|
||||
} from 'react-table'
|
||||
```
|
||||
|
||||
Once you've installed React Table, continue to [Concepts](./concepts.md) to read more about how to utilize its API
|
||||
Once you've installed React Table, continue to [Concepts](./concepts) to read more about how to utilize its API
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
---
|
||||
name: Quick Start
|
||||
route: /quickstart
|
||||
---
|
||||
|
||||
# Quick Start
|
||||
|
||||
As explained in the [Concepts](./concepts) document, react-table is a headless tool, meaning you'll have to build your own UI. We recognize this can be potentially daunting, so here's a very basic table to start with.
|
||||
|
||||
## Define Row Shape
|
||||
|
||||
When thinking about a table, you typically have a number of rows split into a number of columns. While table configurations can get far more complex with nested columns, subrows, etc. for this basic quick start, we need to define some data. Note that this data must be defined using [`React.useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) in order to take advantage of the power of memoization.
|
||||
|
||||
```javascript
|
||||
const data = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
col1: 'Hello',
|
||||
col2: 'World',
|
||||
},
|
||||
{
|
||||
col1: 'react-table',
|
||||
col2: 'rocks',
|
||||
},
|
||||
{
|
||||
col1: 'whatever',
|
||||
col2: 'you want',
|
||||
},
|
||||
],
|
||||
[]
|
||||
)
|
||||
```
|
||||
|
||||
## Define Columns
|
||||
|
||||
The first step to using react-table is to create a set of column definitions to pass into the `useTable` hook. These columns must be defined using `React.useMemo` in order to take advantage of the power of memoization.
|
||||
|
||||
```javascript
|
||||
const columns = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: 'Column 1',
|
||||
accessor: 'col1', // accessor is the "key" in the data
|
||||
},
|
||||
{
|
||||
Header: 'Column 2',
|
||||
accessor: 'col2',
|
||||
},
|
||||
],
|
||||
[]
|
||||
)
|
||||
```
|
||||
|
||||
## Implement `useTable` hook
|
||||
|
||||
Now that you have the basic `columns` and `data` defined, you can pass those into `useTable` and retrieve the properties you need.
|
||||
|
||||
```javascript
|
||||
const {
|
||||
getTableProps,
|
||||
getTableBodyProps,
|
||||
headerGroups,
|
||||
rows,
|
||||
prepareRow,
|
||||
} = useTable({ columns, data })
|
||||
```
|
||||
|
||||
If you're new to JavaScript (especially ES2015+), this syntax may look a little strange. The lefthand side of the assigment is using [object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to extract the properties we need that are returned from the `useTable` hook (or function). On the right hand side, at a minimum, `useTable` needs to be provided with an object containing the memoized columns and data that we created above.
|
||||
|
||||
## Build a basic UI structure
|
||||
|
||||
OK, so that's great, we've implemented the hook, but we still don't have a table to show, right? Let's use the properties returned from `useTable` to build a basic table structure.
|
||||
|
||||
```javascript
|
||||
return (
|
||||
<table {...getTableProps()}>
|
||||
<thead>
|
||||
{headerGroups.map(headerGroup => (
|
||||
<tr {...headerGroup.getHeaderGroupProps()}>
|
||||
{headerGroup.headers.map(column => (
|
||||
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody {...getTableBodyProps()}>
|
||||
{rows.map(row => {
|
||||
prepareRow(row)
|
||||
return (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map(cell => {
|
||||
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
```
|
||||
|
||||
Again, if you're relatively new to JavaScript (or ES2015+ syntax), you may wonder, "What is with all the ...s?". This is the [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) that _spreads_ all properties of an object (or array) without having to manually extract them all. So, with the first row, `<table {...getRowProps()}>` will return a `table` element with all of the properties returned by `getTableProps()`.
|
||||
|
||||
## Final Result
|
||||
|
||||
If we put all of this together, we should get a very basic (boring) table. (_Styles added just to make it a little more attractive..._)
|
||||
|
||||
_The following example is a live component, so as you make changes in the code, it should update the table at the top._
|
||||
|
||||
import { Playground } from 'docz'
|
||||
import { useTable } from '../src/hooks/useTable'
|
||||
|
||||
<Playground>
|
||||
{() => {
|
||||
const data = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
col1: 'Hello',
|
||||
col2: 'World',
|
||||
},
|
||||
{
|
||||
col1: 'react-table',
|
||||
col2: 'rocks',
|
||||
},
|
||||
{
|
||||
col1: 'whatever',
|
||||
col2: 'you want',
|
||||
},
|
||||
],
|
||||
[]
|
||||
)
|
||||
const columns = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: 'Column 1',
|
||||
accessor: 'col1', // accessor is the "key" in the data
|
||||
},
|
||||
{
|
||||
Header: 'Column 2',
|
||||
accessor: 'col2',
|
||||
},
|
||||
],
|
||||
[]
|
||||
)
|
||||
const {
|
||||
getTableProps,
|
||||
getTableBodyProps,
|
||||
headerGroups,
|
||||
rows,
|
||||
prepareRow,
|
||||
} = useTable({ columns, data })
|
||||
return (
|
||||
<table {...getTableProps()} style={{ border: 'solid 1px blue'}}>
|
||||
<thead>
|
||||
{headerGroups.map(headerGroup => (
|
||||
<tr {...headerGroup.getHeaderGroupProps()}>
|
||||
{headerGroup.headers.map(column => (
|
||||
<th {...column.getHeaderProps()} style={{ borderBottom: 'solid 3px red', background: 'aliceblue', color: 'black', fontWeight: 'bold'}}>{column.render('Header')}</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody {...getTableBodyProps()}>
|
||||
{rows.map(row => {
|
||||
prepareRow(row)
|
||||
return (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map(cell => {
|
||||
return <td {...cell.getCellProps()} style={{ padding: '10px', border: 'solid 1px gray', background: 'papayawhip'}}>{cell.render('Cell')}</td>
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
)
|
||||
}}
|
||||
</Playground>
|
||||
@@ -0,0 +1,23 @@
|
||||
export default {
|
||||
title: 'React Table Documentation',
|
||||
description: 'Documentation for the react-table library built in Docz',
|
||||
ignore: ['docs/README.md', 'examples/**/*.md'],
|
||||
propsParser: false,
|
||||
port: 3002,
|
||||
menu: [
|
||||
'Getting Started',
|
||||
'Installation',
|
||||
'Concepts',
|
||||
'Quick Start',
|
||||
{
|
||||
name: 'Examples',
|
||||
menu: ['Simple', 'Complex', 'Controlled', 'UI/Rendering'],
|
||||
},
|
||||
{ name: 'API', menu: ['Overview', 'useTable'] },
|
||||
'FAQ',
|
||||
'Contributing',
|
||||
'Code of Conduct',
|
||||
'Typescript',
|
||||
'Changelog',
|
||||
],
|
||||
}
|
||||
@@ -1578,9 +1578,9 @@ acorn-walk@^6.0.1:
|
||||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
|
||||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
|
||||
version "5.7.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
||||
|
||||
acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7:
|
||||
version "6.2.0"
|
||||
|
||||
@@ -1578,9 +1578,9 @@ acorn-walk@^6.0.1:
|
||||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
|
||||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
|
||||
version "5.7.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
||||
|
||||
acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7:
|
||||
version "6.2.0"
|
||||
|
||||
@@ -46,7 +46,7 @@ const Styles = styled.div`
|
||||
|
||||
// Create an editable cell renderer
|
||||
const EditableCell = ({
|
||||
cell: { value: initialValue },
|
||||
value: initialValue,
|
||||
row: { index },
|
||||
column: { id },
|
||||
updateMyData, // This is a custom function that we supplied to our table instance
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -260,7 +260,7 @@ function App() {
|
||||
// then sum any of those counts if they are
|
||||
// aggregated further
|
||||
aggregate: 'count',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Names`,
|
||||
Aggregated: ({ value }) => `${value} Names`,
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
@@ -270,7 +270,7 @@ function App() {
|
||||
// being aggregated, then sum those counts if
|
||||
// they are aggregated further
|
||||
aggregate: 'uniqueCount',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Unique Names`,
|
||||
Aggregated: ({ value }) => `${value} Unique Names`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -282,14 +282,14 @@ function App() {
|
||||
accessor: 'age',
|
||||
// Aggregate the average age of visitors
|
||||
aggregate: 'average',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (avg)`,
|
||||
Aggregated: ({ value }) => `${value} (avg)`,
|
||||
},
|
||||
{
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
// Aggregate the sum of all visits
|
||||
aggregate: 'sum',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (total)`,
|
||||
Aggregated: ({ value }) => `${value} (total)`,
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
@@ -300,7 +300,7 @@ function App() {
|
||||
accessor: 'progress',
|
||||
// Use our custom roundedMedian aggregator
|
||||
aggregate: roundedMedian,
|
||||
Aggregated: ({ cell: { value } }) => `${value} (med)`,
|
||||
Aggregated: ({ value }) => `${value} (med)`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -197,7 +197,7 @@ function App() {
|
||||
// then sum any of those counts if they are
|
||||
// aggregated further
|
||||
aggregate: 'count',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Names`,
|
||||
Aggregated: ({ value }) => `${value} Names`,
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
@@ -207,7 +207,7 @@ function App() {
|
||||
// being aggregated, then sum those counts if
|
||||
// they are aggregated further
|
||||
aggregate: 'uniqueCount',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Unique Names`,
|
||||
Aggregated: ({ value }) => `${value} Unique Names`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -219,15 +219,14 @@ function App() {
|
||||
accessor: 'age',
|
||||
// Aggregate the average age of visitors
|
||||
aggregate: 'average',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
`${Math.round(value * 100) / 100} (avg)`,
|
||||
Aggregated: ({ value }) => `${Math.round(value * 100) / 100} (avg)`,
|
||||
},
|
||||
{
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
// Aggregate the sum of all visits
|
||||
aggregate: 'sum',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (total)`,
|
||||
Aggregated: ({ value }) => `${value} (total)`,
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
@@ -238,7 +237,7 @@ function App() {
|
||||
accessor: 'progress',
|
||||
// Use our custom roundedMedian aggregator
|
||||
aggregate: roundedMedian,
|
||||
Aggregated: ({ cell: { value } }) => `${value} (med)`,
|
||||
Aggregated: ({ value }) => `${value} (med)`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1578,9 +1578,9 @@ acorn-walk@^6.0.1:
|
||||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
|
||||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
|
||||
version "5.7.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
||||
|
||||
acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7:
|
||||
version "6.2.0"
|
||||
|
||||
@@ -57,7 +57,7 @@ const Styles = styled.div`
|
||||
|
||||
// Create an editable cell renderer
|
||||
const EditableCell = ({
|
||||
cell: { value: initialValue },
|
||||
value: initialValue,
|
||||
row: { index },
|
||||
column: { id },
|
||||
updateMyData, // This is a custom function that we supplied to our table instance
|
||||
@@ -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,
|
||||
@@ -400,8 +400,8 @@ function Table({ columns, data, updateMyData, skipPageReset }) {
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{/*
|
||||
Pagination can be built however you'd like.
|
||||
{/*
|
||||
Pagination can be built however you'd like.
|
||||
This is just a very basic UI implementation:
|
||||
*/}
|
||||
<div className="pagination">
|
||||
@@ -514,7 +514,7 @@ function App() {
|
||||
// then sum any of those counts if they are
|
||||
// aggregated further
|
||||
aggregate: 'count',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Names`,
|
||||
Aggregated: ({ value }) => `${value} Names`,
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
@@ -526,7 +526,7 @@ function App() {
|
||||
// being aggregated, then sum those counts if
|
||||
// they are aggregated further
|
||||
aggregate: 'uniqueCount',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Unique Names`,
|
||||
Aggregated: ({ value }) => `${value} Unique Names`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -540,7 +540,7 @@ function App() {
|
||||
filter: 'equals',
|
||||
// Aggregate the average age of visitors
|
||||
aggregate: 'average',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (avg)`,
|
||||
Aggregated: ({ value }) => `${value} (avg)`,
|
||||
},
|
||||
{
|
||||
Header: 'Visits',
|
||||
@@ -549,7 +549,7 @@ function App() {
|
||||
filter: 'between',
|
||||
// Aggregate the sum of all visits
|
||||
aggregate: 'sum',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (total)`,
|
||||
Aggregated: ({ value }) => `${value} (total)`,
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
@@ -564,7 +564,7 @@ function App() {
|
||||
filter: filterGreaterThan,
|
||||
// Use our custom roundedMedian aggregator
|
||||
aggregate: roundedMedian,
|
||||
Aggregated: ({ cell: { value } }) => `${value} (med)`,
|
||||
Aggregated: ({ value }) => `${value} (med)`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ const Styles = styled.div`
|
||||
|
||||
// Create an editable cell renderer
|
||||
const EditableCell = ({
|
||||
cell: { value: initialValue },
|
||||
value: initialValue,
|
||||
row: { index },
|
||||
column: { id },
|
||||
updateMyData, // This is a custom function that we supplied to our table instance
|
||||
@@ -411,8 +411,8 @@ function Table({ columns, data, updateMyData, skipReset }) {
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{/*
|
||||
Pagination can be built however you'd like.
|
||||
{/*
|
||||
Pagination can be built however you'd like.
|
||||
This is just a very basic UI implementation:
|
||||
*/}
|
||||
<div className="pagination">
|
||||
@@ -543,7 +543,7 @@ function App() {
|
||||
// then sum any of those counts if they are
|
||||
// aggregated further
|
||||
aggregate: 'count',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Names`,
|
||||
Aggregated: ({ value }) => `${value} Names`,
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
@@ -555,7 +555,7 @@ function App() {
|
||||
// being aggregated, then sum those counts if
|
||||
// they are aggregated further
|
||||
aggregate: 'uniqueCount',
|
||||
Aggregated: ({ cell: { value } }) => `${value} Unique Names`,
|
||||
Aggregated: ({ value }) => `${value} Unique Names`,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -569,7 +569,7 @@ function App() {
|
||||
filter: 'equals',
|
||||
// Aggregate the average age of visitors
|
||||
aggregate: 'average',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (avg)`,
|
||||
Aggregated: ({ value }) => `${value} (avg)`,
|
||||
},
|
||||
{
|
||||
Header: 'Visits',
|
||||
@@ -578,7 +578,7 @@ function App() {
|
||||
filter: 'between',
|
||||
// Aggregate the sum of all visits
|
||||
aggregate: 'sum',
|
||||
Aggregated: ({ cell: { value } }) => `${value} (total)`,
|
||||
Aggregated: ({ value }) => `${value} (total)`,
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
@@ -593,7 +593,7 @@ function App() {
|
||||
filter: filterGreaterThan,
|
||||
// Use our custom roundedMedian aggregator
|
||||
aggregate: roundedMedian,
|
||||
Aggregated: ({ cell: { value } }) => `${value} (med)`,
|
||||
Aggregated: ({ value }) => `${value} (med)`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ const inputStyle = {
|
||||
|
||||
// Create an editable cell renderer
|
||||
const EditableCell = ({
|
||||
cell: { value: initialValue },
|
||||
value: initialValue,
|
||||
row: { index },
|
||||
column: { id },
|
||||
updateMyData, // This is a custom function that we supplied to our table instance
|
||||
|
||||
@@ -233,8 +233,8 @@ function App() {
|
||||
accessor: d => new Date(d.date),
|
||||
sortType: 'basic',
|
||||
aggregate: 'count',
|
||||
Cell: ({ cell: { value } }) => (value ? dayjs(value).format('l') : ''),
|
||||
Aggregated: ({ cell: { value } }) => `${value} Orders`,
|
||||
Cell: ({ value }) => (value ? dayjs(value).format('l') : ''),
|
||||
Aggregated: ({ value }) => `${value} Orders`,
|
||||
},
|
||||
{
|
||||
Header: 'Employee',
|
||||
@@ -260,7 +260,7 @@ function App() {
|
||||
Header: 'Unit Cost',
|
||||
accessor: 'unitCost',
|
||||
aggregate: 'average',
|
||||
Cell: ({ cell: { value } }) =>
|
||||
Cell: ({ value }) =>
|
||||
typeof value !== 'undefined' ? (
|
||||
<div
|
||||
style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}
|
||||
@@ -273,7 +273,7 @@ function App() {
|
||||
Header: 'Total',
|
||||
accessor: 'total',
|
||||
aggregate: 'sum',
|
||||
Cell: ({ cell: { value } }) =>
|
||||
Cell: ({ value }) =>
|
||||
typeof value !== 'undefined' ? (
|
||||
<div
|
||||
style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -1578,9 +1578,9 @@ acorn-walk@^6.0.1:
|
||||
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
|
||||
|
||||
acorn@^5.5.3:
|
||||
version "5.7.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
|
||||
integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
|
||||
version "5.7.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
|
||||
integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
|
||||
|
||||
acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7:
|
||||
version "6.2.0"
|
||||
|
||||
@@ -21,3 +21,5 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
.docz
|
||||
|
||||
@@ -65,7 +65,7 @@ By default, the sorting will be `alphanumeric`. This can be changed in your `col
|
||||
Other options include `basic` and `datetime`.
|
||||
Note that if you're planning on sorting numbers between 0 and 1, `basic` sorting will be more accurate.
|
||||
|
||||
More information can be found in the [API Docs](/docs/api/README.md#useSortBy)
|
||||
More information can be found in the [API Docs](/api/useSortBy)
|
||||
|
||||
````diff
|
||||
const columns = React.useMemo(
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
'*.{md,js,ts,jsx,tsx}': ['prettier --write --no-editorconfig', 'git add'],
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# COMMENT: This is a rule for Single Page Apps. Docz site is one...
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/"
|
||||
status = 200
|
||||
+20
-25
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "7.0.0-rc.16",
|
||||
"version": "7.0.4",
|
||||
"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",
|
||||
@@ -28,38 +26,43 @@
|
||||
"prepare": "yarn build",
|
||||
"release": "yarn publish",
|
||||
"releaseNext": "yarn publish --tag next",
|
||||
"format": "prettier {src,src/**,examples/*/src,examples/*/src/**}/*.{md,js,jsx,tsx} --write"
|
||||
"format": "prettier {src,src/**,examples/*/src,examples/*/src/**}/*.{md,js,jsx,tsx} --write",
|
||||
"docz:build": "docz build",
|
||||
"docz:dev": "docz dev",
|
||||
"docz:serve": "docz build && docz serve",
|
||||
"postinstall": "node ./scripts/postinstall.js || exit 0"
|
||||
},
|
||||
"files": [
|
||||
"CHANGELOG.md",
|
||||
"src/**/*.js",
|
||||
"index.d.ts",
|
||||
"dist",
|
||||
"LICENCE",
|
||||
"package.json",
|
||||
"README.md"
|
||||
"README.md",
|
||||
"scripts/"
|
||||
],
|
||||
"browserslist": "> 0.25%, not dead",
|
||||
"dependencies": {
|
||||
"@scarf/scarf": "^0.1.5"
|
||||
},
|
||||
"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",
|
||||
"docz": "^2.2.0",
|
||||
"eslint": "6.6.0",
|
||||
"eslint-config-prettier": "^6.7.0",
|
||||
"eslint-config-react-app": "^5.0.2",
|
||||
@@ -74,7 +77,7 @@
|
||||
"eslint-plugin-react": "7.16.0",
|
||||
"eslint-plugin-react-hooks": "2.3.0",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"husky": "^3.1.0",
|
||||
"gatsby-theme-docz": "^2.2.0",
|
||||
"is-ci-cli": "^2.0.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-cli": "^24.9.0",
|
||||
@@ -87,7 +90,8 @@
|
||||
"prop-types": "^15.5.0",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"rollup": "^1.27.3",
|
||||
"react-test-renderer": "^16.13.0",
|
||||
"rollup": "^1.32.1",
|
||||
"rollup-plugin-babel": "^4.3.3",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-node-resolve": "^5.2.0",
|
||||
@@ -96,14 +100,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
@@ -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(),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var msg = `
|
||||
👩💻 Use react-table at work?
|
||||
🎉 Consider sponsoring/supporting its development at:
|
||||
|
||||
https://github.com/sponsors/tannerlinsley
|
||||
`
|
||||
|
||||
console.log(msg)
|
||||
@@ -1,12 +0,0 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1581795972580,
|
||||
"files": [
|
||||
{
|
||||
"filename": "index.js",
|
||||
"size": 26248,
|
||||
"delta": 414
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,12 +0,0 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1581795982924,
|
||||
"files": [
|
||||
{
|
||||
"filename": "index.es.js",
|
||||
"size": 26040,
|
||||
"delta": 407
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
+1
-1
@@ -42,7 +42,7 @@ export const includes = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return filterValue.includes(rowValue)
|
||||
return rowValue.includes(filterValue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
|
||||
export const Logo = () => (
|
||||
<img
|
||||
src="https://github.com/tannerlinsley/react-table/raw/master/media/logo.png"
|
||||
alt="react-table Logo"
|
||||
style={{ maxHeight: 50 }}
|
||||
/>
|
||||
)
|
||||
@@ -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,
|
||||
|
||||
+68
-93
@@ -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)
|
||||
@@ -289,13 +237,35 @@ 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]
|
||||
)
|
||||
// Combine new visible columns with all columns
|
||||
allColumns = React.useMemo(() => {
|
||||
const columns = [...visibleColumns]
|
||||
|
||||
allColumns.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()
|
||||
@@ -430,10 +402,12 @@ export const useTable = (props, ...plugins) => {
|
||||
|
||||
// Build the visible cells for each row
|
||||
row.allCells = allColumns.map(column => {
|
||||
const value = row.values[column.id]
|
||||
|
||||
const cell = {
|
||||
column,
|
||||
row,
|
||||
value: row.values[column.id],
|
||||
value,
|
||||
}
|
||||
|
||||
// Give each cell a getCellProps base
|
||||
@@ -446,6 +420,7 @@ export const useTable = (props, ...plugins) => {
|
||||
cell.render = makeRenderer(getInstance(), column, {
|
||||
row,
|
||||
cell,
|
||||
value,
|
||||
})
|
||||
|
||||
return cell
|
||||
|
||||
+2
-2
@@ -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'
|
||||
|
||||
@@ -31,7 +31,7 @@ const data = [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
width: 200,
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
|
||||
@@ -31,7 +31,7 @@ const data = [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
width: 200,
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
|
||||
@@ -40,7 +40,7 @@ const makeData = () => [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
Filter: ({ column: { filterValue, setFilter } }) => (
|
||||
<input
|
||||
value={filterValue || ''}
|
||||
@@ -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: ({ 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
|
||||
})
|
||||
@@ -31,7 +31,7 @@ const data = [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
width: 200,
|
||||
minWidth: 100,
|
||||
maxWidth: 300,
|
||||
|
||||
@@ -48,7 +48,7 @@ const data = [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
Filter: ({ filterValue, setFilter }) => (
|
||||
<input
|
||||
value={filterValue || ''}
|
||||
@@ -160,14 +160,14 @@ function App() {
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
aggregate: 'count',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`First Name Aggregated: ${value} Names`,
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
accessor: 'lastName',
|
||||
aggregate: 'uniqueCount',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Last Name Aggregated: ${value} Unique Names`,
|
||||
},
|
||||
],
|
||||
@@ -179,14 +179,14 @@ function App() {
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: 'average',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Age Aggregated: ${value} (avg)`,
|
||||
},
|
||||
{
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: 'sum',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Visits Aggregated: ${value} (total)`,
|
||||
},
|
||||
{
|
||||
@@ -194,7 +194,7 @@ function App() {
|
||||
id: 'minVisits',
|
||||
accessor: 'visits',
|
||||
aggregate: 'min',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Visits Aggregated: ${value} (min)`,
|
||||
},
|
||||
{
|
||||
@@ -202,7 +202,7 @@ function App() {
|
||||
id: 'maxVisits',
|
||||
accessor: 'visits',
|
||||
aggregate: 'max',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Visits Aggregated: ${value} (max)`,
|
||||
},
|
||||
{
|
||||
@@ -210,14 +210,14 @@ function App() {
|
||||
id: 'minMaxVisits',
|
||||
accessor: 'visits',
|
||||
aggregate: 'minMax',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Visits Aggregated: ${value} (minMax)`,
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
accessor: 'status',
|
||||
aggregate: 'unique',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Visits Aggregated: ${value.join(', ')} (unique)`,
|
||||
},
|
||||
{
|
||||
@@ -225,7 +225,7 @@ function App() {
|
||||
accessor: 'progress',
|
||||
id: 'progress',
|
||||
aggregate: 'median',
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Process Aggregated: ${value} (median)`,
|
||||
},
|
||||
{
|
||||
@@ -233,7 +233,7 @@ function App() {
|
||||
accessor: 'progress',
|
||||
id: 'progressRounded',
|
||||
aggregate: roundedMedian,
|
||||
Aggregated: ({ cell: { value } }) =>
|
||||
Aggregated: ({ value }) =>
|
||||
`Process Aggregated: ${value} (rounded median)`,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -31,7 +31,7 @@ const data = [
|
||||
]
|
||||
|
||||
const defaultColumn = {
|
||||
Cell: ({ cell: { value }, column: { id } }) => `${id}: ${value}`,
|
||||
Cell: ({ value, column: { id } }) => `${id}: ${value}`,
|
||||
}
|
||||
|
||||
function Table({ columns, data }) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}, {})
|
||||
}
|
||||
|
||||
@@ -43,12 +43,18 @@ function reducer(state, action, previousState, instance) {
|
||||
}
|
||||
|
||||
if (action.type === actions.gotoPage) {
|
||||
const { pageCount } = instance
|
||||
const { pageCount, page } = instance
|
||||
const newPageIndex = functionalUpdate(action.pageIndex, state.pageIndex)
|
||||
const cannnotPreviousPage = newPageIndex < 0
|
||||
const cannotNextPage =
|
||||
pageCount === -1
|
||||
? page.length < state.pageSize
|
||||
: newPageIndex > pageCount - 1
|
||||
|
||||
if (newPageIndex < 0 || newPageIndex > pageCount - 1) {
|
||||
if (cannnotPreviousPage || cannotNextPage) {
|
||||
return state
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
pageIndex: newPageIndex,
|
||||
@@ -89,10 +95,6 @@ function useInstance(instance) {
|
||||
dispatch,
|
||||
data,
|
||||
manualPagination,
|
||||
manualGlobalFilter,
|
||||
manualFilters,
|
||||
manualGroupBy,
|
||||
manualSortBy,
|
||||
} = instance
|
||||
|
||||
ensurePluginOrder(
|
||||
@@ -110,10 +112,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 +123,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]
|
||||
)
|
||||
|
||||
@@ -154,7 +159,8 @@ function useInstance(instance) {
|
||||
])
|
||||
|
||||
const canPreviousPage = pageIndex > 0
|
||||
const canNextPage = pageCount === -1 || pageIndex < pageCount - 1
|
||||
const canNextPage =
|
||||
pageCount === -1 ? page.length >= pageSize : pageIndex < pageCount - 1
|
||||
|
||||
const gotoPage = React.useCallback(
|
||||
pageIndex => {
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
+13
-42
@@ -7,37 +7,12 @@ export const actions = {
|
||||
}
|
||||
|
||||
export const defaultColumn = {
|
||||
Cell: ({ cell: { value = '' } }) => value,
|
||||
Cell: ({ value = '' }) => value,
|
||||
width: 150,
|
||||
minWidth: 0,
|
||||
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
|
||||
@@ -235,18 +210,22 @@ export function flexRender(Comp, props) {
|
||||
return isReactComponent(Comp) ? <Comp {...props} /> : Comp
|
||||
}
|
||||
|
||||
function isClassComponent(component) {
|
||||
function isReactComponent(component) {
|
||||
return (
|
||||
typeof component === 'function' &&
|
||||
!!(() => {
|
||||
let proto = Object.getPrototypeOf(component)
|
||||
return proto.prototype && proto.prototype.isReactComponent
|
||||
})()
|
||||
isClassComponent(component) ||
|
||||
typeof component === 'function' ||
|
||||
isExoticComponent(component)
|
||||
)
|
||||
}
|
||||
|
||||
function isFunctionComponent(component) {
|
||||
return typeof component === 'function'
|
||||
function isClassComponent(component) {
|
||||
return (
|
||||
typeof component === 'function' &&
|
||||
(() => {
|
||||
const proto = Object.getPrototypeOf(component)
|
||||
return proto.prototype && proto.prototype.isReactComponent
|
||||
})()
|
||||
)
|
||||
}
|
||||
|
||||
function isExoticComponent(component) {
|
||||
@@ -256,11 +235,3 @@ function isExoticComponent(component) {
|
||||
['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)
|
||||
)
|
||||
}
|
||||
|
||||
function isReactComponent(component) {
|
||||
return (
|
||||
isClassComponent(component) ||
|
||||
isFunctionComponent(component) ||
|
||||
isExoticComponent(component)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
* https://github.com/tannerlinsley/react-table
|
||||
Reference in New Issue
Block a user