Compare commits

...
Author SHA1 Message Date
Tanner Linsley 63d54b1e87 v7.0.0-rc.14 2019-12-18 11:55:16 -07:00
Tanner Linsley 6e853a3cff Merge branch 'master' of https://github.com/react-tools/react-table 2019-12-18 11:54:57 -07:00
Tanner Linsley 30a40aa0a2 Change meta signature for hooks 2019-12-18 11:54:43 -07:00
size-plugin[bot]andGitHub a8e1b33284 😍 🤵🏽‍♂️ update sizes-es.json 👍 2019-12-18 17:42:06 +00:00
size-plugin[bot]andGitHub 67ce7d8f0b 🧖🏽 👵 update sizes-cjs.json 👍 2019-12-18 17:42:05 +00:00
Tanner Linsley 4e08fd500e v7.0.0-rc.13 2019-12-18 10:40:08 -07:00
Tanner Linsley cb59098685 Fix column hiding, add useControlledStat hook 2019-12-18 10:39:35 -07:00
Tanner Linsley d7b6e69c5f 7.0.0-rc.12 2019-12-17 22:10:56 -07:00
Tanner Linsley b69e300b00 Merge branch 'master' of https://github.com/react-tools/react-table 2019-12-17 20:54:33 -07:00
size-plugin[bot]andGitHub 04e1309ed7 📤 🙏🏻 update sizes-es.json 👍 2019-12-18 03:54:31 +00:00
size-plugin[bot]andGitHub 4ed950d990 🤾‍♂️ 🤤 update sizes-cjs.json 👍 2019-12-18 03:54:30 +00:00
Tanner Linsley fdc3b22e54 Merge branch 'master' of https://github.com/react-tools/react-table 2019-12-17 20:54:23 -07:00
hanvyjandTanner Linsley 4e013632dd Fix groupBy removed columns (#1776) (#1782) 2019-12-17 20:52:57 -07:00
Michael LiandTanner Linsley 80ceeee83f Update useTable.md (#1788) 2019-12-17 20:52:39 -07:00
Tanner Linsley b3771502f8 v7.0.0-rc.11 2019-12-17 20:50:59 -07:00
Tanner Linsley 0df8cc5088 Update useFlexLayout.md 2019-12-17 20:46:03 -07:00
Tanner Linsley 7cebab7fb6 Merge branch 'master' of https://github.com/react-tools/react-table 2019-12-17 20:44:48 -07:00
Tanner Linsley 717ea7b211 Update Docs 2019-12-17 20:44:33 -07:00
size-plugin[bot]andGitHub 823d93946b 💁🏿‍♂️ 🚵‍♂️ update sizes-es.json 👍 2019-12-18 03:43:47 +00:00
size-plugin[bot]andGitHub b01749c5c7 🕴️ 🍀 update sizes-cjs.json 👍 2019-12-18 03:43:46 +00:00
Tanner Linsley b48cddb92b Add back useFlexLayout and full-width-resizable-table example 2019-12-17 20:41:28 -07:00
Tanner Linsley f48ef14975 Fix reset to use initial state, then fall back to default state 2019-12-17 20:40:34 -07:00
Tanner Linsley eeee14830d Update Changelog 2019-12-17 19:32:07 -07:00
Tanner Linsley f2776d0005 Fix getcolumnsHooks 2019-12-17 19:31:50 -07:00
Tanner Linsley ee18cf4b89 Add streaming rows snapshot 2019-12-17 19:31:09 -07:00
Chris NorwoodandTanner Linsley 632ea28c4b Update to use React.Fragment spread with row props (#1781) 2019-12-13 18:08:01 -07:00
Tanner LinsleyandGitHub 506a22062e Update README.md 2019-12-13 13:52:59 -07:00
size-plugin[bot]andGitHub 9e81e44da3 ☺️ 👨🏿‍🦳 update sizes-es.json 👍 2019-12-13 08:02:58 +00:00
size-plugin[bot]andGitHub acd6ac5d14 🤹🏽 🏋🏾 update sizes-es.json 👍 2019-12-13 08:00:27 +00:00
size-plugin[bot]andGitHub 78634585e7 🍒 👨🏼‍🍳 update sizes-es.json 👍 2019-12-13 07:55:23 +00:00
Tanner Linsley c8d2180e5b Create sandbox.config.json 2019-12-13 00:52:32 -07:00
Tanner Linsley 0575c1b36d Update examples.md 2019-12-13 00:50:11 -07:00
68 changed files with 21716 additions and 598 deletions
+25 -25
View File
@@ -1,13 +1,32 @@
{
"dist/index.js": {
"bundled": 104720,
"minified": 48438,
"gzipped": 13005
"bundled": 108756,
"minified": 50398,
"gzipped": 13421
},
"dist/index.es.js": {
"bundled": 103833,
"minified": 47648,
"gzipped": 12849,
"bundled": 107845,
"minified": 49586,
"gzipped": 13253,
"treeshaked": {
"rollup": {
"code": 80,
"import_statements": 21
},
"webpack": {
"code": 8168
}
}
},
"dist\\index.js": {
"bundled": 104977,
"minified": 48560,
"gzipped": 13057
},
"dist\\index.es.js": {
"bundled": 104090,
"minified": 47770,
"gzipped": 12900,
"treeshaked": {
"rollup": {
"code": 80,
@@ -17,24 +36,5 @@
"code": 8227
}
}
},
"dist\\index.js": {
"bundled": 105386,
"minified": 49565,
"gzipped": 13008
},
"dist\\index.es.js": {
"bundled": 104543,
"minified": 48815,
"gzipped": 12856,
"treeshaked": {
"rollup": {
"code": 80,
"import_statements": 21
},
"webpack": {
"code": 8444
}
}
}
}
+21
View File
@@ -1,3 +1,24 @@
## 7.0.0-rc.14
- Changed the function signature for all propGetter hooks to accept a single object of named meta properties instead of a variable length of meta arguments. The user props object has also been added as a property to all prop getters. For example, `hooks.getRowProps.push((props, instance, row) => [...])` is now written `hooks.getRowProps.push((props, { instance, row, userProps }) => [...])`
- Changed the function signature for all reduceHooks accept a single object of named meta properties instead of a variable length of meta arguments. For example, `hooks.flatColumns.push((flatColumns, instance) => flatColumns)` is now written `hooks.flatColumns.push((flatColumns, { instance }) => flatColumns)`
- Changed the function signature for all loopHooks accept a single object of named meta properties instead of a variable length of meta arguments. For example, `hooks.prepareRow.push((row, instance) => void)` is now written `hooks.prepareRow.push((row { instance }) => void)`
## 7.0.0-rc.13
- Added the `useControlledState` hook for plugins to manipulate the final state of the table similar to how users can
- Fixed an issue where column hiding wasn't working properly.
## 7.0.0-rc.12
- Fixed an issue where removing a grouped column would result in a crash
## 7.0.0-rc.11
- Fixed an issue where plugins using the `columns` hook were not getting decorated properly
- Added back a new rendition of the `useFlexLayout` plugin and accompanying example.
- Fixed all reset actions to use the initial state passed into the table, then fall back to the default initial state for the hook
## 7.0.0-rc.10
- Optimizations made to make accessors, prop getters and other internals much faster. 10x in some cases!
+1
View File
@@ -183,6 +183,7 @@ This library is being built and maintained by me, @tannerlinsley and I am always
<li>Pekka Tapani</li>
<li>Eric Lanehart (@pushred)</li>
<li>Anish P Patel (@anishpatelyaadada)</li>
<li>Alin Porumb (@alinporumb)</li>
</ul>
</td>
<td>
+1
View File
@@ -20,6 +20,7 @@ React Table is essentially a compatible collection of **custom React hooks**:
- Layout Hooks
- [`useBlockLayout`](./useBlockLayout.md)
- [`useAbsoluteLayout`](./useAbsoluteLayout.md)
- [`useFlexLayout`](./useFlexLayout.md)
- [`useResizeColumns`](./useResizeColumns.md)
- 3rd Party Plugin Hooks
- Want your custom plugin hook listed here? [Submit a PR!](https://github.com/tannerlinsley/react-table/compare)
+6
View File
@@ -25,6 +25,12 @@
- **Usage Required**
- This core prop getter is required to to enable absolute layout for rows cells
### HeaderGroup Properties
- `getHeaderGroupProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for headers
### Header Properties
- `getHeaderProps`
+6
View File
@@ -19,6 +19,12 @@
- **Usage Required**
- This core prop getter is required to to enable absolute layout for rows cells
### HeaderGroup Properties
- `getHeaderGroupProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for headers
### Header Properties
- `getHeaderProps`
+43
View File
@@ -0,0 +1,43 @@
# `useFlexLayout`
- Plugin Hook
- Optional
`useFlexLayout` is a plugin hook that adds support for headers and cells to be rendered as `inline-block` `div`s (or other non-table elements) with `width` being used as the flex-basis and flex-grow. This hook becomes useful when implementing both virtualized and resizable tables that must also be able to stretch to fill all available space.
**NOTE:** Although no additional options are needed for this plugin to work, the core column options `width`, `minWidth` and `maxWidth` are used to calculate column and cell widths and must be set:
- `minWidth` is only used to limit column resizing. It does not define the minimum width for a column.
- `width` is used as both the `flex-basis` and `flex-grow`. This means that it essentially acts as both the minimum width and flex-ratio of the column.
- `maxWidth` is only used to limit column resizing. It does not define the maximum width for a column.
[See Column Options](#column-options) for more information on these options.
### Row Properties
- `getRowProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for rows
### Cell Properties
- `getCellProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for rows cells
### HeaderGroup Properties
- `getHeaderGroupProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for headers
### Header Properties
- `getHeaderProps`
- **Usage Required**
- This core prop getter is required to to enable absolute layout for headers
### Example (Full Width Resizable Table)
- [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)
+1 -1
View File
@@ -25,7 +25,7 @@ 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
- `reducer: Function(newState, action, prevState) => newState`
- `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.
- It is passed the `newState`, `action`, and `prevState` and is expected to either return the `newState` or a modified version of the `newState`
+9
View File
@@ -16,6 +16,9 @@
- 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)
@@ -46,6 +49,12 @@
- 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)
+4 -2
View File
@@ -71,8 +71,10 @@ function Table({ columns, data }) {
</div>
{flatColumns.map(column => (
<div key={column.id}>
<input type="checkbox" {...column.getToggleHiddenProps()} />{' '}
{column.id}
<label>
<input type="checkbox" {...column.getToggleHiddenProps()} />{' '}
{column.id}
</label>
</div>
))}
<br />
+4
View File
@@ -0,0 +1,4 @@
{
"presets": ["react-app"],
"plugins": ["styled-components"]
}
+1
View File
@@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true
+7
View File
@@ -0,0 +1,7 @@
{
"extends": ["react-app", "prettier"],
"rules": {
// "eqeqeq": 0,
// "jsx-a11y/anchor-is-valid": 0
}
}
+23
View File
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+29
View File
@@ -0,0 +1,29 @@
const path = require('path')
const resolveFrom = require('resolve-from')
const fixLinkedDependencies = config => {
config.resolve = {
...config.resolve,
alias: {
...config.resolve.alias,
react$: resolveFrom(path.resolve('node_modules'), 'react'),
'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'),
},
}
return config
}
const includeSrcDirectory = config => {
config.resolve = {
...config.resolve,
modules: [path.resolve('src'), ...config.resolve.modules],
}
return config
}
module.exports = [
['use-babel-config', '.babelrc'],
['use-eslint-config', '.eslintrc'],
fixLinkedDependencies,
// includeSrcDirectory,
]
+4
View File
@@ -0,0 +1,4 @@
# Full Width Resizable Table (via useFlexLayout)
- [Open this example in a new CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/full-width-resizable-table)
- `yarn` and `yarn start` to run and edit the example
+35
View File
@@ -0,0 +1,35 @@
{
"private": true,
"scripts": {
"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",
"eject": "rescripts eject"
},
"dependencies": {
"namor": "^1.1.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"react-table": "latest",
"styled-components": "^4.3.2"
},
"devDependencies": {
"@rescripts/cli": "^0.0.11",
"@rescripts/rescript-use-babel-config": "^0.0.8",
"@rescripts/rescript-use-eslint-config": "^0.0.9",
"babel-eslint": "10.0.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
+15
View File
@@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
{
"infiniteLoopProtection": false
}
+193
View File
@@ -0,0 +1,193 @@
import React from 'react'
import styled from 'styled-components'
import { useTable, useResizeColumns, useFlexLayout } from 'react-table'
import makeData from './makeData'
const Styles = styled.div`
padding: 1rem;
.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;
.thead {
${'' /* These styles are required for a scrollable body to align with the header properly */}
overflow-y: auto;
overflow-x: hidden;
}
.tbody {
${'' /* These styles are required for a scrollable table body */}
overflow-y: scroll;
overflow-x: hidden;
height: 250px;
}
.tr {
:last-child {
.td {
border-bottom: 0;
}
}
}
.th,
.td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
${'' /* In this example we use an absolutely position resizer,
so this is required. */}
position: relative;
:last-child {
border-right: 0;
}
.resizer {
display: inline-block;
background: blue;
width: 10px;
height: 100%;
position: absolute;
right: 0;
top: 0;
z-index: 1;
${'' /* prevents from scrolling while dragging on touch devices */}
touch-action:none;
&.isResizing {
background: red;
}
}
}
}
`
function Table({ columns, data }) {
const defaultColumn = React.useMemo(
() => ({
// When using the useFlexLayout:
minWidth: 30, // minWidth is only used as a limit for resizing
width: 150, // width is used for both the flex-basis and flex-grow
maxWidth: 200, // maxWidth is only used as a limit for resizing
}),
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable(
{
columns,
data,
defaultColumn,
},
useResizeColumns,
useFlexLayout
)
return (
<div {...getTableProps()} className="table">
<div>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
{/* Use column.getResizerProps to hook up the events correctly */}
<div
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? 'isResizing' : ''}`}
/>
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()} className="tbody">
{rows.map((row, i) => {
prepareRow(row)
return (
<div {...row.getRowProps()} className="tr">
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
})}
</div>
</div>
)
}
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',
width: 50,
},
{
Header: 'Visits',
accessor: 'visits',
width: 50,
},
{
Header: 'Status',
accessor: 'status',
},
{
Header: 'Profile Progress',
accessor: 'progress',
},
],
},
],
[]
)
const data = React.useMemo(() => makeData(20), [])
return (
<Styles>
<Table columns={columns} data={data} />
</Styles>
)
}
export default App
+9
View File
@@ -0,0 +1,9 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(<App />, div)
ReactDOM.unmountComponentAtNode(div)
})
+13
View File
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
+6
View File
@@ -0,0 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
ReactDOM.render(<App />, document.getElementById('root'))
+40
View File
@@ -0,0 +1,40 @@
import namor from 'namor'
const range = len => {
const arr = []
for (let i = 0; i < len; i++) {
arr.push(i)
}
return arr
}
const newPerson = () => {
const statusChance = Math.random()
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100),
progress: Math.floor(Math.random() * 100),
status:
statusChance > 0.66
? 'relationship'
: statusChance > 0.33
? 'complicated'
: 'single',
}
}
export default function makeData(...lens) {
const makeDataLevel = (depth = 0) => {
const len = lens[depth]
return range(len).map(d => {
return {
...newPerson(),
subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
}
})
}
return makeDataLevel()
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,3 @@
{
"infiniteLoopProtection": false
}
+19 -4
View File
@@ -33,6 +33,20 @@ const Styles = styled.div`
}
`
function useControlledState(state, { instance }) {
return React.useMemo(() => {
if (state.groupBy.length) {
return {
...state,
hiddenColumns: [...state.hiddenColumns, ...state.groupBy].filter(
(d, i, all) => all.indexOf(d) === i
),
}
}
return state
}, [state])
}
function Table({ columns, data }) {
const {
getTableProps,
@@ -40,7 +54,7 @@ function Table({ columns, data }) {
headerGroups,
rows,
prepareRow,
state: { groupBy, expanded },
state,
} = useTable(
{
columns,
@@ -50,7 +64,8 @@ function Table({ columns, data }) {
useExpanded,
// Our custom plugin to add the expander column
hooks => {
hooks.flatColumns.push((columns, instance) => {
hooks.useControlledState.push(useControlledState)
hooks.flatColumns.push((columns, { instance }) => {
if (!instance.state.groupBy.length) {
return columns
}
@@ -100,7 +115,7 @@ function Table({ columns, data }) {
return null
},
},
...columns.map(d => ({ ...d, isVisible: !d.isGrouped })),
...columns,
]
})
}
@@ -113,7 +128,7 @@ function Table({ columns, data }) {
return (
<>
<pre>
<code>{JSON.stringify({ groupBy, expanded: expanded }, null, 2)}</code>
<code>{JSON.stringify({ state }, null, 2)}</code>
</pre>
<Legend />
<table {...getTableProps()}>
+4
View File
@@ -0,0 +1,4 @@
{
"presets": ["react-app"],
"plugins": ["styled-components"]
}
+1
View File
@@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true
+7
View File
@@ -0,0 +1,7 @@
{
"extends": ["react-app", "prettier"],
"rules": {
// "eqeqeq": 0,
// "jsx-a11y/anchor-is-valid": 0
}
}
+23
View File
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+29
View File
@@ -0,0 +1,29 @@
const path = require('path')
const resolveFrom = require('resolve-from')
const fixLinkedDependencies = config => {
config.resolve = {
...config.resolve,
alias: {
...config.resolve.alias,
react$: resolveFrom(path.resolve('node_modules'), 'react'),
'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'),
},
}
return config
}
const includeSrcDirectory = config => {
config.resolve = {
...config.resolve,
modules: [path.resolve('src'), ...config.resolve.modules],
}
return config
}
module.exports = [
['use-babel-config', '.babelrc'],
['use-eslint-config', '.eslintrc'],
fixLinkedDependencies,
// includeSrcDirectory,
]
+6
View File
@@ -0,0 +1,6 @@
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app) and Rescripts.
You can:
- [Open this example in a new CodeSandbox](https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/streaming-rows)
- `yarn` and `yarn start` to run and edit the example
+36
View File
@@ -0,0 +1,36 @@
{
"private": true,
"scripts": {
"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",
"eject": "rescripts eject"
},
"dependencies": {
"namor": "^1.1.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"react-table": "latest",
"react-window": "^1.8.5",
"styled-components": "^4.3.2"
},
"devDependencies": {
"@rescripts/cli": "^0.0.11",
"@rescripts/rescript-use-babel-config": "^0.0.8",
"@rescripts/rescript-use-eslint-config": "^0.0.9",
"babel-eslint": "10.0.1"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+38
View File
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
@@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
@@ -0,0 +1,5 @@
{
"infiniteLoopProtection": false,
"hardReloadOnChange": false,
"view": "browser"
}
+217
View File
@@ -0,0 +1,217 @@
import React from 'react'
import styled from 'styled-components'
import { useTable, useBlockLayout, useRowSelect } from 'react-table'
const Styles = styled.div`
padding: 1rem;
.table {
display: inline-block;
border-spacing: 0;
border: 1px solid black;
.tr {
:last-child {
.td {
border-bottom: 0;
}
}
}
.th,
.td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`
let sourceGridData = []
const updateRateMS = 16
function Table({ columns }) {
// Use the state and functions returned from useTable to build your UI
const [data, setData] = React.useState([])
const timerRunning = React.useRef()
if (!timerRunning.current) {
timerRunning.current = true
setInterval(() => {
sourceGridData.push(makeRow(sourceGridData.length))
let newData = [...sourceGridData]
setData(newData)
}, updateRateMS)
}
const defaultColumn = React.useMemo(
() => ({
width: 150,
}),
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
toggleAllRowsSelected,
prepareRow,
state,
} = useTable(
{
autoResetSelectedRows: false,
columns,
data,
defaultColumn,
},
useBlockLayout,
useRowSelect
)
// Render the UI for your table
return (
<>
<div {...getTableProps()} className="table">
<div className="thead">
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()}>
{rows.slice(0, 10).map(row => {
prepareRow(row)
return (
<div
{...row.getRowProps({
style: {
backgroundColor: row.isSelected ? 'green' : '',
},
onClick: e => {
toggleAllRowsSelected(false)
row.toggleRowSelected()
},
})}
className="tr"
>
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
})}
</div>
</div>
<pre>
<code>{JSON.stringify(state, null, 2)}</code>
</pre>
</>
)
}
function App() {
const columns = React.useMemo(
() => [
{
Header: 'ID',
accessor: 'id',
},
{
Header: 'Name',
accessor: 'name',
},
{
Header: 'age',
accessor: 'age',
},
{
Header: 'gender',
accessor: 'gender',
},
{
Header: 'height',
accessor: 'height',
},
{
Header: 'color',
accessor: 'col',
},
{
Header: 'dob',
accessor: 'dob',
},
],
[]
)
return (
<Styles>
<Table columns={columns} />
</Styles>
)
}
function makeRow(id) {
let r = Math.floor(Math.random() * 3) + 1
if (r === 0) {
return {
Id: id,
name: 'Billy Bob',
age: 12,
gender: 'male',
height: 95,
col: 'red',
dob: '14/05/2010',
}
} else if (r === 1) {
return {
Id: id,
name: 'Jenny Jane',
age: 42,
gender: 'female',
height: 142,
col: 'blue',
dob: '30/07/1954',
}
} else if (r === 2) {
return {
Id: id,
name: 'Steve McAlistaire',
age: 35,
gender: 'male',
height: 176,
col: 'green',
dob: '04/11/1982',
}
} else if (r === 3) {
return {
Id: id,
name: 'Jeff Joe',
age: 35,
gender: 'male',
height: 176,
col: 'green',
dob: '04/11/1982',
}
}
}
export default App
+9
View File
@@ -0,0 +1,9 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
it('renders without crashing', () => {
const div = document.createElement('div')
ReactDOM.render(<App />, div)
ReactDOM.unmountComponentAtNode(div)
})
+13
View File
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
+6
View File
@@ -0,0 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
ReactDOM.render(<App />, document.getElementById('root'))
+40
View File
@@ -0,0 +1,40 @@
import namor from 'namor'
const range = len => {
const arr = []
for (let i = 0; i < len; i++) {
arr.push(i)
}
return arr
}
const newPerson = () => {
const statusChance = Math.random()
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100),
progress: Math.floor(Math.random() * 100),
status:
statusChance > 0.66
? 'relationship'
: statusChance > 0.33
? 'complicated'
: 'single',
}
}
export default function makeData(...lens) {
const makeDataLevel = (depth = 0) => {
const len = lens[depth]
return range(len).map(d => {
return {
...newPerson(),
subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
}
})
}
return makeDataLevel()
}
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -74,8 +74,8 @@ function Table({ columns: userColumns, data, renderRowSubComponent }) {
prepareRow(row)
return (
// Use a React.Fragment here so the table markup is still valid
<>
<tr {...row.getRowProps()}>
<React.Fragment {...row.getRowProps()}>
<tr>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
@@ -100,7 +100,7 @@ function Table({ columns: userColumns, data, renderRowSubComponent }) {
</td>
</tr>
) : null}
</>
</React.Fragment>
)
})}
</tbody>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "7.0.0-rc.10",
"version": "7.0.0-rc.14",
"description": "Hooks for building lightweight, fast and extendable datagrids for React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
+3 -213
View File
@@ -1,221 +1,11 @@
[
{
"timestamp": 1576222078852,
"timestamp": 1576690899177,
"files": [
{
"filename": "index.js",
"size": 22042,
"delta": -647
}
]
},
{
"timestamp": 1576165979638,
"files": [
{
"filename": "index.js",
"size": 22689,
"delta": 135
}
]
},
{
"timestamp": 1576044489324,
"files": [
{
"filename": "index.js",
"size": 22554,
"delta": -79
}
]
},
{
"timestamp": 1576020969676,
"files": [
{
"filename": "index.js",
"size": 22633,
"delta": -10
}
]
},
{
"timestamp": 1576007021431,
"files": [
{
"filename": "index.js",
"size": 22643,
"delta": -7
}
]
},
{
"timestamp": 1576004320856,
"files": [
{
"filename": "index.js",
"size": 22650,
"delta": 30
}
]
},
{
"timestamp": 1576003432935,
"files": [
{
"filename": "index.js",
"size": 22620,
"delta": 652
}
]
},
{
"timestamp": 1575985310396,
"files": [
{
"filename": "index.js",
"size": 21968,
"delta": 323
}
]
},
{
"timestamp": 1575910923566,
"files": [
{
"filename": "index.js",
"size": 21645,
"delta": 56
}
]
},
{
"timestamp": 1575859193604,
"files": [
{
"filename": "index.js",
"size": 21589,
"delta": 563
}
]
},
{
"timestamp": 1575690248030,
"files": [
{
"filename": "index.js",
"size": 21026,
"delta": 1
}
]
},
{
"timestamp": 1575675308812,
"files": [
{
"filename": "index.js",
"size": 21025,
"delta": -421
}
]
},
{
"timestamp": 1575620433902,
"files": [
{
"filename": "index.js",
"size": 21446,
"delta": -1
}
]
},
{
"timestamp": 1575607054721,
"files": [
{
"filename": "index.js",
"size": 21447,
"delta": 26
}
]
},
{
"timestamp": 1575605755429,
"files": [
{
"filename": "index.js",
"size": 21421,
"delta": 170
}
]
},
{
"timestamp": 1575579354616,
"files": [
{
"filename": "index.js",
"size": 21251,
"delta": 6
}
]
},
{
"timestamp": 1575578830463,
"files": [
{
"filename": "index.js",
"size": 21245,
"delta": 652
}
]
},
{
"timestamp": 1575555421868,
"files": [
{
"filename": "index.js",
"size": 20593,
"delta": 24
}
]
},
{
"timestamp": 1575517726476,
"files": [
{
"filename": "index.js",
"size": 20569,
"delta": 58
}
]
},
{
"timestamp": 1575391465436,
"files": [
{
"filename": "index.js",
"size": 20511,
"delta": 1
}
]
},
{
"timestamp": 1575345020328,
"files": [
{
"filename": "index.js",
"size": 20510,
"delta": 5
}
]
},
{
"timestamp": 1575331661254,
"files": [
{
"filename": "index.js",
"size": 20505,
"delta": 20505
"size": 22438,
"delta": 35
}
]
}
+3 -203
View File
@@ -1,211 +1,11 @@
[
{
"timestamp": 1576222088784,
"timestamp": 1576690906689,
"files": [
{
"filename": "index.es.js",
"size": 21847,
"delta": -668
}
]
},
{
"timestamp": 1576165986389,
"files": [
{
"filename": "index.es.js",
"size": 22515,
"delta": 140
}
]
},
{
"timestamp": 1576044496748,
"files": [
{
"filename": "index.es.js",
"size": 22375,
"delta": -76
}
]
},
{
"timestamp": 1576020979047,
"files": [
{
"filename": "index.es.js",
"size": 22451,
"delta": -10
}
]
},
{
"timestamp": 1576007027792,
"files": [
{
"filename": "index.es.js",
"size": 22461,
"delta": -7
}
]
},
{
"timestamp": 1576004327554,
"files": [
{
"filename": "index.es.js",
"size": 22468,
"delta": 30
}
]
},
{
"timestamp": 1576003439933,
"files": [
{
"filename": "index.es.js",
"size": 22438,
"delta": 656
}
]
},
{
"timestamp": 1575985317929,
"files": [
{
"filename": "index.es.js",
"size": 21782,
"delta": 324
}
]
},
{
"timestamp": 1575910931774,
"files": [
{
"filename": "index.es.js",
"size": 21458,
"delta": 55
}
]
},
{
"timestamp": 1575859200604,
"files": [
{
"filename": "index.es.js",
"size": 21403,
"delta": 561
}
]
},
{
"timestamp": 1575675317538,
"files": [
{
"filename": "index.es.js",
"size": 20842,
"delta": -383
}
]
},
{
"timestamp": 1575620442742,
"files": [
{
"filename": "index.es.js",
"size": 21225,
"delta": -1
}
]
},
{
"timestamp": 1575607059725,
"files": [
{
"filename": "index.es.js",
"size": 21226,
"delta": 26
}
]
},
{
"timestamp": 1575605764195,
"files": [
{
"filename": "index.es.js",
"size": 21200,
"delta": 170
}
]
},
{
"timestamp": 1575579366180,
"files": [
{
"filename": "index.es.js",
"size": 21030,
"delta": 7
}
]
},
{
"timestamp": 1575578837727,
"files": [
{
"filename": "index.es.js",
"size": 21023,
"delta": 575
}
]
},
{
"timestamp": 1575555429414,
"files": [
{
"filename": "index.es.js",
"size": 20448,
"delta": 21
}
]
},
{
"timestamp": 1575517715056,
"files": [
{
"filename": "index.es.js",
"size": 20427,
"delta": 59
}
]
},
{
"timestamp": 1575391457318,
"files": [
{
"filename": "index.es.js",
"size": 20368,
"delta": -1
}
]
},
{
"timestamp": 1575345027852,
"files": [
{
"filename": "index.es.js",
"size": 20369,
"delta": 4
}
]
},
{
"timestamp": 1575331668355,
"files": [
{
"filename": "index.es.js",
"size": 20365,
"delta": 20365
"size": 22235,
"delta": 33
}
]
}
+14 -18
View File
@@ -19,7 +19,7 @@ export const useColumnVisibility = hooks => {
hooks.stateReducers.push(reducer)
hooks.useInstanceBeforeDimensions.push(useInstanceBeforeDimensions)
hooks.headerGroupsDeps.push((deps, instance) => [
hooks.headerGroupsDeps.push((deps, { instance }) => [
...deps,
instance.state.hiddenColumns,
])
@@ -28,7 +28,7 @@ export const useColumnVisibility = hooks => {
useColumnVisibility.pluginName = 'useColumnVisibility'
const defaultGetToggleHiddenProps = (props, instance, column) => [
const defaultGetToggleHiddenProps = (props, { column }) => [
props,
{
onChange: e => {
@@ -42,7 +42,7 @@ const defaultGetToggleHiddenProps = (props, instance, column) => [
},
]
const defaultGetToggleHideAllColumnsProps = (props, instance) => [
const defaultGetToggleHideAllColumnsProps = (props, { instance }) => [
props,
{
onChange: e => {
@@ -58,7 +58,7 @@ const defaultGetToggleHideAllColumnsProps = (props, instance) => [
},
]
function reducer(state, action, previousState, instanceRef) {
function reducer(state, action, previousState, instance) {
if (action.type === actions.init) {
return {
hiddenColumns: [],
@@ -69,7 +69,7 @@ function reducer(state, action, previousState, instanceRef) {
if (action.type === actions.resetHiddenColumns) {
return {
...state,
hiddenColumns: [],
hiddenColumns: instance.initialState.hiddenColumns || [],
}
}
@@ -79,6 +79,8 @@ function reducer(state, action, previousState, instanceRef) {
? action.value
: !state.hiddenColumns.includes(action.columnId)
console.log(action, should)
const hiddenColumns = should
? [...state.hiddenColumns, action.columnId]
: state.hiddenColumns.filter(d => d !== action.columnId)
@@ -104,9 +106,7 @@ function reducer(state, action, previousState, instanceRef) {
return {
...state,
hiddenColumns: shouldAll
? instanceRef.current.flatColumns.map(d => d.id)
: [],
hiddenColumns: shouldAll ? instance.flatColumns.map(d => d.id) : [],
}
}
}
@@ -123,10 +123,7 @@ function useInstanceBeforeDimensions(instance) {
}
const handleColumn = (column, parentVisible) => {
column.isVisible =
typeof column.isVisible !== 'undefined'
? column.isVisible
: parentVisible && !hiddenColumns.includes(column.id)
column.isVisible = parentVisible && !hiddenColumns.includes(column.id)
let totalVisibleHeaderCount = 0
@@ -187,7 +184,7 @@ function useInstance(instance) {
const getToggleHideAllColumnsProps = makePropGetter(
getToggleHideAllColumnsPropsHooks(),
getInstance()
{ instance: getInstance() }
)
// Snapshot hook and disallow more from being added
@@ -205,11 +202,10 @@ function useInstance(instance) {
})
}
column.getToggleHiddenProps = makePropGetter(
getToggleHiddenPropsHooks(),
getInstance(),
column
)
column.getToggleHiddenProps = makePropGetter(getToggleHiddenPropsHooks(), {
instance: getInstance(),
column,
})
})
Object.assign(instance, {
+75 -49
View File
@@ -133,8 +133,18 @@ export const useTable = (props, ...plugins) => {
reducer(initialState, { type: actions.init })
)
// Snapshot hook and disallow more from being added
const getUseControlledStateHooks = useConsumeHookGetter(
getInstance().hooks,
'useControlledState'
)
// Allow the user to control the final state with hooks
const state = useControlledState(reducerState)
const state = reduceHooks(
[...getUseControlledStateHooks(), useControlledState],
reducerState,
{ instance: getInstance() }
)
Object.assign(getInstance(), {
state,
@@ -153,10 +163,11 @@ export const useTable = (props, ...plugins) => {
// Decorate All the columns
let columns = React.useMemo(
() =>
reduceHooks(
getColumnsHooks(),
decorateColumnTree(userColumns, defaultColumn),
getInstance()
decorateColumnTree(
reduceHooks(getColumnsHooks(), userColumns, {
instance: getInstance(),
}),
defaultColumn
),
[
defaultColumn,
@@ -164,7 +175,7 @@ export const useTable = (props, ...plugins) => {
getInstance,
userColumns,
// eslint-disable-next-line react-hooks/exhaustive-deps
...reduceHooks(getColumnsDepsHooks(), [], getInstance()),
...reduceHooks(getColumnsDepsHooks(), [], { instance: getInstance() }),
]
)
@@ -254,13 +265,14 @@ export const useTable = (props, ...plugins) => {
// have been access, and allow hooks to decorate
// those columns (and trigger this memoization via deps)
flatColumns = React.useMemo(
() => reduceHooks(flatColumnsHooks(), flatColumns, getInstance()),
() =>
reduceHooks(flatColumnsHooks(), flatColumns, { instance: getInstance() }),
[
flatColumns,
flatColumnsHooks,
getInstance,
// eslint-disable-next-line react-hooks/exhaustive-deps
...reduceHooks(flatColumnsDepsHooks(), [], getInstance()),
...reduceHooks(flatColumnsDepsHooks(), [], { instance: getInstance() }),
]
)
@@ -292,7 +304,7 @@ export const useTable = (props, ...plugins) => {
getHeaderGroups,
getInstance,
// eslint-disable-next-line react-hooks/exhaustive-deps
...reduceHooks(getHeaderGroupsDeps(), [], getInstance()),
...reduceHooks(getHeaderGroupsDeps(), [], { instance: getInstance() }),
]
)
@@ -320,7 +332,15 @@ export const useTable = (props, ...plugins) => {
loopHooks(getUseInstanceBeforeDimensions(), getInstance())
// Header Visibility is needed by this point
getInstance().totalColumnsWidth = calculateHeaderWidths(headers)
const [
totalColumnsMinWidth,
totalColumnsWidth,
totalColumnsMaxWidth,
] = calculateHeaderWidths(headers)
getInstance().totalColumnsMinWidth = totalColumnsMinWidth
getInstance().totalColumnsWidth = totalColumnsWidth
getInstance().totalColumnsMaxWidth = totalColumnsMaxWidth
// Snapshot hook and disallow more from being added
const getUseInstance = useConsumeHookGetter(
@@ -350,18 +370,16 @@ export const useTable = (props, ...plugins) => {
column.render = makeRenderer(getInstance(), column)
// Give columns/headers a default getHeaderProps
column.getHeaderProps = makePropGetter(
getHeaderPropsHooks(),
getInstance(),
column
)
column.getHeaderProps = makePropGetter(getHeaderPropsHooks(), {
instance: getInstance(),
column,
})
// Give columns/headers a default getFooterProps
column.getFooterProps = makePropGetter(
getFooterPropsHooks(),
getInstance(),
column
)
column.getFooterProps = makePropGetter(getFooterPropsHooks(), {
instance: getInstance(),
column,
})
}
)
@@ -398,16 +416,12 @@ export const useTable = (props, ...plugins) => {
if (headerGroup.headers.length) {
headerGroup.getHeaderGroupProps = makePropGetter(
getHeaderGroupPropsHooks(),
getInstance(),
headerGroup,
i
{ instance: getInstance(), headerGroup, index: i }
)
headerGroup.getFooterGroupProps = makePropGetter(
getFooterGroupPropsHooks(),
getInstance(),
headerGroup,
i
{ instance: getInstance(), headerGroup, index: i }
)
return true
@@ -424,11 +438,9 @@ export const useTable = (props, ...plugins) => {
// Snapshot hook and disallow more from being added
const getUseRowsHooks = useConsumeHookGetter(getInstance().hooks, 'useRows')
getInstance().rows = reduceHooks(
getUseRowsHooks(),
getInstance().rows,
getInstance()
)
getInstance().rows = reduceHooks(getUseRowsHooks(), getInstance().rows, {
instance: getInstance(),
})
// The prepareRow function is absolutely necessary and MUST be called on
// any rows the user wishes to be displayed.
@@ -456,7 +468,10 @@ export const useTable = (props, ...plugins) => {
getInstance().prepareRow = React.useCallback(
row => {
row.getRowProps = makePropGetter(getRowPropsHooks(), getInstance(), row)
row.getRowProps = makePropGetter(getRowPropsHooks(), {
instance: getInstance(),
row,
})
// Build the visible cells for each row
row.allCells = flatColumns.map(column => {
@@ -467,11 +482,10 @@ export const useTable = (props, ...plugins) => {
}
// Give each cell a getCellProps base
cell.getCellProps = makePropGetter(
getCellPropsHooks(),
getInstance(),
cell
)
cell.getCellProps = makePropGetter(getCellPropsHooks(), {
instance: getInstance(),
cell,
})
// Give each cell a renderer function (supports multiple renderers)
cell.render = makeRenderer(getInstance(), column, {
@@ -482,10 +496,12 @@ export const useTable = (props, ...plugins) => {
return cell
})
row.cells = reduceHooks(cellsHooks(), row.allCells, getInstance())
row.cells = reduceHooks(cellsHooks(), row.allCells, {
instance: getInstance(),
})
// need to apply any row specific hooks (useExpanded requires this)
loopHooks(getPrepareRowHooks(), row, getInstance())
loopHooks(getPrepareRowHooks(), row, { instance: getInstance() })
},
[
getRowPropsHooks,
@@ -503,10 +519,9 @@ export const useTable = (props, ...plugins) => {
'getTableProps'
)
getInstance().getTableProps = makePropGetter(
getTablePropsHooks(),
getInstance()
)
getInstance().getTableProps = makePropGetter(getTablePropsHooks(), {
instance: getInstance(),
})
// Snapshot hook and disallow more from being added
const getTableBodyPropsHooks = useConsumeHookGetter(
@@ -514,10 +529,9 @@ export const useTable = (props, ...plugins) => {
'getTableBodyProps'
)
getInstance().getTableBodyProps = makePropGetter(
getTableBodyPropsHooks(),
getInstance()
)
getInstance().getTableBodyProps = makePropGetter(getTableBodyPropsHooks(), {
instance: getInstance(),
})
// Snapshot hook and disallow more from being added
const getUseFinalInstanceHooks = useConsumeHookGetter(
@@ -531,7 +545,9 @@ export const useTable = (props, ...plugins) => {
}
function calculateHeaderWidths(headers, left = 0) {
let sumTotalMinWidth = 0
let sumTotalWidth = 0
let sumTotalMaxWidth = 0
headers.forEach(header => {
let { headers: subHeaders } = header
@@ -539,18 +555,28 @@ function calculateHeaderWidths(headers, left = 0) {
header.totalLeft = left
if (subHeaders && subHeaders.length) {
header.totalWidth = calculateHeaderWidths(subHeaders, left)
const [totalMinWidth, totalWidth, totalMaxWidth] = calculateHeaderWidths(
subHeaders,
left
)
header.totalMinWidth = totalMinWidth
header.totalWidth = totalWidth
header.totalMaxWidth = totalMaxWidth
} else {
header.totalMinWidth = header.minWidth
header.totalWidth = Math.min(
Math.max(header.minWidth, header.width),
header.maxWidth
)
header.totalMaxWidth = header.maxWidth
}
if (header.isVisible) {
left += header.totalWidth
sumTotalMinWidth += header.totalMinWidth
sumTotalWidth += header.totalWidth
sumTotalMaxWidth += header.totalMaxWidth
}
})
return sumTotalWidth
return [sumTotalMinWidth, sumTotalWidth, sumTotalMaxWidth]
}
+1
View File
@@ -11,3 +11,4 @@ export { useColumnOrder } from './plugin-hooks/useColumnOrder'
export { useResizeColumns } from './plugin-hooks/useResizeColumns'
export { useAbsoluteLayout } from './plugin-hooks/useAbsoluteLayout'
export { useBlockLayout } from './plugin-hooks/useBlockLayout'
export { useFlexLayout } from './plugin-hooks/useFlexLayout'
+7 -6
View File
@@ -1,33 +1,33 @@
const defaultCells = cell => cell.filter(d => d.column.isVisible)
const defaultGetHeaderProps = (props, instance, column) => ({
const defaultGetHeaderProps = (props, { column }) => ({
key: `header_${column.id}`,
colSpan: column.totalVisibleHeaderCount,
...props,
})
const defaultGetFooterProps = (props, instance, column) => ({
const defaultGetFooterProps = (props, { column }) => ({
key: `footer_${column.id}`,
colSpan: column.totalVisibleHeaderCount,
...props,
})
const defaultGetHeaderGroupProps = (props, instance, headerGroup, index) => ({
const defaultGetHeaderGroupProps = (props, { index }) => ({
key: `headerGroup_${index}`,
...props,
})
const defaultGetFooterGroupProps = (props, instance, headerGroup, index) => ({
const defaultGetFooterGroupProps = (props, { index }) => ({
key: `footerGroup_${index}`,
...props,
})
const defaultGetRowProps = (props, instance, row) => ({
const defaultGetRowProps = (props, { row }) => ({
key: `row_${row.id}`,
...props,
})
const defaultGetCellProps = (props, instance, cell) => ({
const defaultGetCellProps = (props, { cell }) => ({
...props,
key: `cell_${cell.row.id}_${cell.column.id}`,
})
@@ -36,6 +36,7 @@ export default function makeDefaultPluginHooks() {
return {
useOptions: [],
stateReducers: [],
useControlledState: [],
columns: [],
columnsDeps: [],
flatColumns: [],
@@ -64,6 +64,9 @@ function Table({ columns, data }) {
columns,
data,
defaultColumn,
initialState: {
groupBy: ["Column Doesn't Exist"],
},
},
useGroupBy,
useExpanded
+5 -5
View File
@@ -11,18 +11,18 @@ export const useAbsoluteLayout = hooks => {
hooks.getHeaderGroupProps.push(getRowStyles)
hooks.useInstance.push(useInstance)
hooks.getHeaderProps.push((props, instance, header) => [
hooks.getHeaderProps.push((props, { column }) => [
props,
{
style: {
...cellStyles,
left: `${header.totalLeft}px`,
width: `${header.totalWidth}px`,
left: `${column.totalLeft}px`,
width: `${column.totalWidth}px`,
},
},
])
hooks.getCellProps.push((props, instance, cell) => [
hooks.getCellProps.push((props, { cell }) => [
props,
{
style: {
@@ -36,7 +36,7 @@ export const useAbsoluteLayout = hooks => {
useAbsoluteLayout.pluginName = 'useAbsoluteLayout'
const getRowStyles = (props, instance) => [
const getRowStyles = (props, { instance }) => [
props,
{
style: {
+4 -4
View File
@@ -3,7 +3,7 @@ const cellStyles = {
boxSizing: 'border-box',
}
const getRowStyles = (props, instance) => [
const getRowStyles = (props, { instance }) => [
props,
{
style: {
@@ -17,17 +17,17 @@ export const useBlockLayout = hooks => {
hooks.getRowProps.push(getRowStyles)
hooks.getHeaderGroupProps.push(getRowStyles)
hooks.getHeaderProps.push((props, instance, header) => [
hooks.getHeaderProps.push((props, { column }) => [
props,
{
style: {
...cellStyles,
width: `${header.totalWidth}px`,
width: `${column.totalWidth}px`,
},
},
])
hooks.getCellProps.push((props, instance, cell) => [
hooks.getCellProps.push((props, { cell }) => [
props,
{
style: {
+11 -8
View File
@@ -8,7 +8,7 @@ actions.setColumnOrder = 'setColumnOrder'
export const useColumnOrder = hooks => {
hooks.stateReducers.push(reducer)
hooks.flatColumnsDeps.push((deps, instance) => {
hooks.flatColumnsDeps.push((deps, { instance }) => {
return [...deps, instance.state.columnOrder]
})
hooks.flatColumns.push(flatColumns)
@@ -17,7 +17,7 @@ export const useColumnOrder = hooks => {
useColumnOrder.pluginName = 'useColumnOrder'
function reducer(state, action) {
function reducer(state, action, previousState, instance) {
if (action.type === actions.init) {
return {
columnOrder: [],
@@ -28,7 +28,7 @@ function reducer(state, action) {
if (action.type === actions.resetColumnOrder) {
return {
...state,
columnOrder: [],
columnOrder: instance.initialState.columnOrder || [],
}
}
@@ -40,11 +40,14 @@ function reducer(state, action) {
}
}
function flatColumns(columns, instance) {
const {
state: { columnOrder },
} = instance
function flatColumns(
columns,
{
instance: {
state: { columnOrder },
},
}
) {
// If there is no order, return the normal columns
if (!columnOrder || !columnOrder.length) {
return columns
+7 -8
View File
@@ -23,7 +23,7 @@ export const useExpanded = hooks => {
useExpanded.pluginName = 'useExpanded'
const defaultGetExpandedToggleProps = (props, instance, row) => [
const defaultGetExpandedToggleProps = (props, { row }) => [
props,
{
onClick: e => {
@@ -38,7 +38,7 @@ const defaultGetExpandedToggleProps = (props, instance, row) => [
]
// Reducer
function reducer(state, action) {
function reducer(state, action, previousState, instance) {
if (action.type === actions.init) {
return {
expanded: {},
@@ -49,7 +49,7 @@ function reducer(state, action) {
if (action.type === actions.resetExpanded) {
return {
...state,
expanded: {},
expanded: instance.initialState.expanded || {},
}
}
@@ -124,11 +124,10 @@ function useInstance(instance) {
hooks.prepareRow.push(row => {
row.toggleExpanded = set => instance.toggleExpanded(row.id, set)
row.getExpandedToggleProps = makePropGetter(
getExpandedTogglePropsHooks(),
getInstance(),
row
)
row.getExpandedToggleProps = makePropGetter(getExpandedTogglePropsHooks(), {
instance: getInstance(),
row,
})
})
const expandedRows = React.useMemo(() => {
+1 -1
View File
@@ -33,7 +33,7 @@ function reducer(state, action, previousState, instance) {
if (action.type === actions.resetFilters) {
return {
...state,
filters: [],
filters: instance.initialState.filters || [],
}
}
+53
View File
@@ -0,0 +1,53 @@
export function useFlexLayout(hooks) {
hooks.getTableBodyProps.push(getTableBodyProps)
hooks.getRowProps.push(getRowStyles)
hooks.getHeaderGroupProps.push(getRowStyles)
hooks.getHeaderProps.push(getHeaderProps)
hooks.getCellProps.push(getCellProps)
}
useFlexLayout.pluginName = 'useFlexLayout'
const getTableBodyProps = (props, { instance }) => [
props,
{
style: {
minWidth: `${instance.totalColumnsWidth}px`,
},
},
]
const getRowStyles = (props, { instance }) => [
props,
{
style: {
display: 'flex',
flex: '1 0 auto',
minWidth: `${instance.totalColumnsMinWidth}px`,
},
},
]
const getHeaderProps = (props, { column }) => [
props,
{
style: {
boxSizing: 'border-box',
flex: `${column.totalWidth} 0 auto`,
minWidth: `${column.totalMinWidth}px`,
width: `${column.totalWidth}px`,
},
},
]
const getCellProps = (props, { cell }) => [
props,
{
style: {
boxSizing: 'border-box',
flex: `${cell.column.totalWidth} 0 auto`,
minWidth: `${cell.column.totalMinWidth}px`,
width: `${cell.column.totalWidth}px`,
},
},
]
+28 -12
View File
@@ -19,7 +19,7 @@ actions.toggleGroupBy = 'toggleGroupBy'
export const useGroupBy = hooks => {
hooks.getGroupByToggleProps = [defaultGetGroupByToggleProps]
hooks.stateReducers.push(reducer)
hooks.flatColumnsDeps.push((deps, instance) => [
hooks.flatColumnsDeps.push((deps, { instance }) => [
...deps,
instance.state.groupBy,
])
@@ -29,7 +29,7 @@ export const useGroupBy = hooks => {
useGroupBy.pluginName = 'useGroupBy'
const defaultGetGroupByToggleProps = (props, instance, header) => [
const defaultGetGroupByToggleProps = (props, { header }) => [
props,
{
onClick: header.canGroupBy
@@ -46,7 +46,7 @@ const defaultGetGroupByToggleProps = (props, instance, header) => [
]
// Reducer
function reducer(state, action) {
function reducer(state, action, previousState, instance) {
if (action.type === actions.init) {
return {
groupBy: [],
@@ -57,7 +57,7 @@ function reducer(state, action) {
if (action.type === actions.resetGroupBy) {
return {
...state,
groupBy: [],
groupBy: instance.initialState.groupBy || [],
}
}
@@ -81,11 +81,20 @@ function reducer(state, action) {
}
}
function flatColumns(flatColumns, { state: { groupBy } }) {
function flatColumns(
flatColumns,
{
instance: {
state: { groupBy },
},
}
) {
// Sort grouped columns to the start of the column list
// before the headers are built
const groupByColumns = groupBy.map(g => flatColumns.find(col => col.id === g))
const groupByColumns = groupBy
.map(g => flatColumns.find(col => col.id === g))
.filter(col => !!col)
const nonGroupByColumns = flatColumns.filter(col => !groupBy.includes(col.id))
flatColumns = [...groupByColumns, ...nonGroupByColumns]
@@ -158,8 +167,7 @@ function useInstance(instance) {
flatHeaders.forEach(header => {
header.getGroupByToggleProps = makePropGetter(
getGroupByTogglePropsHooks(),
getInstance(),
header
{ instance: getInstance(), header }
)
})
@@ -180,6 +188,11 @@ function useInstance(instance) {
return [rows, flatRows]
}
// Ensure that the list of filtered columns exist
const existingGroupBy = groupBy.filter(g =>
flatColumns.find(col => col.id === g)
)
// Find the columns that can or are aggregating
// Uses each column to aggregate rows into a single value
const aggregateRowsToValues = (rows, isAggregated) => {
@@ -187,7 +200,7 @@ function useInstance(instance) {
flatColumns.forEach(column => {
// Don't aggregate columns that are in the groupBy
if (groupBy.includes(column.id)) {
if (existingGroupBy.includes(column.id)) {
values[column.id] = rows[0] ? rows[0].values[column.id] : null
return
}
@@ -234,11 +247,11 @@ function useInstance(instance) {
// Recursively group the data
const groupRecursively = (rows, depth = 0, parentId) => {
// This is the last level, just return the rows
if (depth === groupBy.length) {
if (depth === existingGroupBy.length) {
return rows
}
const columnId = groupBy[depth]
const columnId = existingGroupBy[depth]
// Group the rows together for this level
let groupedRows = groupByFn(rows, columnId)
@@ -251,7 +264,10 @@ function useInstance(instance) {
subRows = groupRecursively(subRows, depth + 1, id)
const values = aggregateRowsToValues(subRows, depth < groupBy.length)
const values = aggregateRowsToValues(
subRows,
depth < existingGroupBy.length
)
const row = {
id,
+1 -1
View File
@@ -37,7 +37,7 @@ function reducer(state, action, previousState, instance) {
if (action.type === actions.resetPage) {
return {
...state,
pageIndex: 0,
pageIndex: instance.initialState.pageIndex || 0,
}
}
+5 -6
View File
@@ -26,7 +26,7 @@ export const useResizeColumns = hooks => {
hooks.useInstanceBeforeDimensions.push(useInstanceBeforeDimensions)
}
const defaultGetResizerProps = (props, instance, header) => {
const defaultGetResizerProps = (props, { instance, header }) => {
const { dispatch } = instance
const onResizeStart = (e, header) => {
@@ -215,11 +215,10 @@ const useInstanceBeforeDimensions = instance => {
header.isResizing = columnResizing.isResizingColumn === header.id
if (canResize) {
header.getResizerProps = makePropGetter(
getResizerPropsHooks(),
getInstance(),
header
)
header.getResizerProps = makePropGetter(getResizerPropsHooks(), {
instance: getInstance(),
header,
})
}
})
}
+10 -11
View File
@@ -26,7 +26,7 @@ export const useRowSelect = hooks => {
useRowSelect.pluginName = pluginName
const defaultGetToggleRowSelectedProps = (props, instance, row) => {
const defaultGetToggleRowSelectedProps = (props, { instance, row }) => {
const { manualRowSelectedKey = 'isSelected' } = instance
let checked = false
@@ -52,7 +52,7 @@ const defaultGetToggleRowSelectedProps = (props, instance, row) => {
]
}
const defaultGetToggleAllRowsSelectedProps = (props, instance) => [
const defaultGetToggleAllRowsSelectedProps = (props, { instance }) => [
props,
{
onChange: e => {
@@ -81,7 +81,7 @@ function reducer(state, action, previousState, instance) {
if (action.type === actions.resetSelectedRows) {
return {
...state,
selectedRowIds: {},
selectedRowIds: instance.initialState.selectedRowIds || {},
}
}
@@ -126,16 +126,16 @@ function reducer(state, action, previousState, instance) {
return state
}
let newSelectedRowPaths = { ...state.selectedRowIds }
let newSelectedRowIds = { ...state.selectedRowIds }
const handleRowById = id => {
const row = flatGroupedRowsById[id]
if (!row.isGrouped) {
if (!isSelected && shouldExist) {
newSelectedRowPaths[id] = true
newSelectedRowIds[id] = true
} else if (isSelected && !shouldExist) {
delete newSelectedRowPaths[id]
delete newSelectedRowIds[id]
}
}
@@ -148,12 +148,12 @@ function reducer(state, action, previousState, instance) {
return {
...state,
selectedRowIds: newSelectedRowPaths,
selectedRowIds: newSelectedRowIds,
}
}
}
function useRows(rows, instance) {
function useRows(rows, { instance }) {
const {
state: { selectedRowIds },
} = instance
@@ -242,7 +242,7 @@ function useInstance(instance) {
const getToggleAllRowsSelectedProps = makePropGetter(
getToggleAllRowsSelectedPropsHooks(),
getInstance()
{ instance: getInstance() }
)
const getToggleRowSelectedPropsHooks = useConsumeHookGetter(
@@ -255,8 +255,7 @@ function useInstance(instance) {
row.getToggleRowSelectedProps = makePropGetter(
getToggleRowSelectedPropsHooks(),
getInstance(),
row
{ instance: getInstance(), row }
)
})
+2 -2
View File
@@ -18,7 +18,7 @@ export const useRowState = hooks => {
useRowState.pluginName = 'useRowState'
function reducer(state, action) {
function reducer(state, action, previousState, instance) {
if (action.type === actions.init) {
return {
rowState: {},
@@ -29,7 +29,7 @@ function reducer(state, action) {
if (action.type === actions.resetRowState) {
return {
...state,
rowState: {},
rowState: instance.initialState.rowState || {},
}
}
+6 -7
View File
@@ -31,7 +31,7 @@ export const useSortBy = hooks => {
useSortBy.pluginName = 'useSortBy'
const defaultGetSortByToggleProps = (props, instance, column) => {
const defaultGetSortByToggleProps = (props, { instance, column }) => {
const { isMultiSortEvent = e => e.shiftKey } = instance
return [
@@ -66,7 +66,7 @@ function reducer(state, action, previousState, instance) {
if (action.type === actions.resetSortBy) {
return {
...state,
sortBy: [],
sortBy: instance.initialState.sortBy || [],
}
}
@@ -237,11 +237,10 @@ function useInstance(instance) {
}
}
column.getSortByToggleProps = makePropGetter(
getSortByTogglePropsHooks(),
getInstance(),
column
)
column.getSortByToggleProps = makePropGetter(getSortByTogglePropsHooks(), {
instance: getInstance(),
column,
})
const columnSort = sortBy.find(d => d.id === id)
column.isSorted = !!columnSort
+12 -8
View File
@@ -67,10 +67,10 @@ function mergeProps(...propList) {
}, {})
}
function handlePropGetter(prevProps, userProps, ...meta) {
function handlePropGetter(prevProps, userProps, meta) {
// Handle a lambda, pass it the previous props
if (typeof userProps === 'function') {
return handlePropGetter({}, userProps(prevProps, ...meta))
return handlePropGetter({}, userProps(prevProps, meta))
}
// Handle an array, merge each item as separate props
@@ -82,17 +82,21 @@ function handlePropGetter(prevProps, userProps, ...meta) {
return mergeProps(prevProps, userProps)
}
export const makePropGetter = (hooks, ...meta) => {
export const makePropGetter = (hooks, meta = {}) => {
return (userProps = {}) =>
[...hooks, userProps].reduce(
(prev, next) => handlePropGetter(prev, next, ...meta),
(prev, next) =>
handlePropGetter(prev, next, {
...meta,
userProps,
}),
{}
)
}
export const reduceHooks = (hooks, initial, ...args) =>
export const reduceHooks = (hooks, initial, meta = {}) =>
hooks.reduce((prev, next) => {
const nextValue = next(prev, ...args)
const nextValue = next(prev, meta)
if (process.env.NODE_ENV !== 'production') {
if (typeof nextValue === 'undefined') {
console.info(next)
@@ -104,9 +108,9 @@ export const reduceHooks = (hooks, initial, ...args) =>
return nextValue
}, initial)
export const loopHooks = (hooks, ...args) =>
export const loopHooks = (hooks, meta = {}) =>
hooks.forEach(hook => {
const nextValue = hook(...args)
const nextValue = hook(meta)
if (process.env.NODE_ENV !== 'production') {
if (typeof nextValue !== 'undefined') {
console.info(hook, nextValue)