mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-31 06:10:19 +00:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b02701058b | ||
|
|
d18f1ba4d8 | ||
|
|
63d54b1e87 | ||
|
|
6e853a3cff | ||
|
|
30a40aa0a2 | ||
|
|
a8e1b33284 | ||
|
|
67ce7d8f0b | ||
|
|
4e08fd500e | ||
|
|
cb59098685 | ||
|
|
d7b6e69c5f | ||
|
|
b69e300b00 | ||
|
|
04e1309ed7 | ||
|
|
4ed950d990 | ||
|
|
fdc3b22e54 | ||
|
|
4e013632dd | ||
|
|
80ceeee83f | ||
|
|
b3771502f8 | ||
|
|
0df8cc5088 | ||
|
|
7cebab7fb6 | ||
|
|
717ea7b211 | ||
|
|
823d93946b | ||
|
|
b01749c5c7 | ||
|
|
b48cddb92b | ||
|
|
f48ef14975 | ||
|
|
eeee14830d | ||
|
|
f2776d0005 | ||
|
|
ee18cf4b89 | ||
|
|
632ea28c4b | ||
|
|
506a22062e | ||
|
|
9e81e44da3 | ||
|
|
acd6ac5d14 | ||
|
|
78634585e7 | ||
|
|
c8d2180e5b | ||
|
|
0575c1b36d |
+25
-25
@@ -1,13 +1,32 @@
|
||||
{
|
||||
"dist/index.js": {
|
||||
"bundled": 104720,
|
||||
"minified": 48438,
|
||||
"gzipped": 13005
|
||||
"bundled": 112754,
|
||||
"minified": 52324,
|
||||
"gzipped": 13765
|
||||
},
|
||||
"dist/index.es.js": {
|
||||
"bundled": 103833,
|
||||
"minified": 47648,
|
||||
"gzipped": 12849,
|
||||
"bundled": 111817,
|
||||
"minified": 51488,
|
||||
"gzipped": 13599,
|
||||
"treeshaked": {
|
||||
"rollup": {
|
||||
"code": 80,
|
||||
"import_statements": 21
|
||||
},
|
||||
"webpack": {
|
||||
"code": 8484
|
||||
}
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
## 7.0.0-rc.15
|
||||
|
||||
- Added `useGlobalFilter` hook for performing table-wide filtering
|
||||
- Filter function signature has changed to supply an array of column IDs (to support both the tranditional single column style and the new multi-column search style introduced with `useGlobalFilter`).
|
||||
- Removed the `column` parameter from the filter function signature as it was unused and no longer made sense with the array of IDs change above.
|
||||
- Updated the `filtering` example to use a global filter in addition to the column filters
|
||||
|
||||
## 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!
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- Plugin Hook
|
||||
- Optional
|
||||
|
||||
`useFilters` is the hook that implements **row filtering**.
|
||||
`useFilters` is the hook that implements **row filtering** and can even be used in conjunction with `useGlobalFilter`. It's also important to note that this hook can be used either **before or after** `useGlobalFilter`, depending on the performance characteristics you want to code for.
|
||||
|
||||
### Table Options
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -0,0 +1,52 @@
|
||||
# `useGlobalFilter`
|
||||
|
||||
- Plugin Hook
|
||||
- Optional
|
||||
|
||||
`useGlobalFilter` is the hook that implements **global row filtering** and can even be used in conjunction with `useFilters`. It's also important to note that this hook can be used either **before or after** `useFilters`, depending on the performance characteristics you want to code for.
|
||||
|
||||
### Table Options
|
||||
|
||||
The following options are supported via the main options object passed to `useTable(options)`
|
||||
|
||||
- `initialState.globalFilter: any`
|
||||
- Must be **memoized**
|
||||
- An array of objects containing columnId's and their corresponding filter values. This information is stored in state since the table is allowed to manipulate the filter through user interaction.
|
||||
- `globalFilter: String | Function`
|
||||
- Optional
|
||||
- Defaults to `text`
|
||||
- The resolved function from the this string/function will be used to filter the table's data.
|
||||
- If a `string` is passed, the function with that name located on either the custom `filterTypes` option or the built-in filtering types object will be used. If
|
||||
- If a `function` is passed, it will be used directly.
|
||||
- For more information on filter types, see Filtering
|
||||
- If a **function** is passed, it must be **memoized**
|
||||
- `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)
|
||||
- `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.
|
||||
- For more information on filter types, see Filtering
|
||||
- `autoResetGlobalFilter: Boolean`
|
||||
- Defaults to `true`
|
||||
- When `true`, the `globalFilter` 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)
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following values are provided to the table `instance`:
|
||||
|
||||
- `rows: Array<Row>`
|
||||
- An array of **filtered** rows.
|
||||
- `preGlobalFilteredRows: Array<Row>`
|
||||
- The array of rows **used right before filtering**.
|
||||
- Among many other use-cases, these rows are directly useful for building option lists in filters, since the resulting filtered `rows` do not contain every possible option.
|
||||
- `setGlobalFilter: Function(columnId, filterValue) => void`
|
||||
- An instance-level function used to update the filter value for a specific column.
|
||||
|
||||
### Example
|
||||
|
||||
- [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)
|
||||
@@ -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`
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { useTable, useFilters } from 'react-table'
|
||||
import { useTable, useFilters, useGlobalFilter } from 'react-table'
|
||||
// A great library for fuzzy filtering/sorting items
|
||||
import matchSorter from 'match-sorter'
|
||||
|
||||
@@ -35,6 +35,32 @@ const Styles = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
// Define a default UI for filtering
|
||||
function GlobalFilter({
|
||||
preGlobalFilteredRows,
|
||||
globalFilter,
|
||||
setGlobalFilter,
|
||||
}) {
|
||||
const count = preGlobalFilteredRows.length
|
||||
|
||||
return (
|
||||
<span>
|
||||
Search:{' '}
|
||||
<input
|
||||
value={globalFilter || ''}
|
||||
onChange={e => {
|
||||
setGlobalFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
|
||||
}}
|
||||
placeholder={`${count} records...`}
|
||||
style={{
|
||||
fontSize: '1.1rem',
|
||||
border: '0',
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
// Define a default UI for filtering
|
||||
function DefaultColumnFilter({
|
||||
column: { filterValue, preFilteredRows, setFilter },
|
||||
@@ -217,6 +243,9 @@ function Table({ columns, data }) {
|
||||
rows,
|
||||
prepareRow,
|
||||
state,
|
||||
flatColumns,
|
||||
preGlobalFilteredRows,
|
||||
setGlobalFilter,
|
||||
} = useTable(
|
||||
{
|
||||
columns,
|
||||
@@ -224,7 +253,8 @@ function Table({ columns, data }) {
|
||||
defaultColumn, // Be sure to pass the defaultColumn option
|
||||
filterTypes,
|
||||
},
|
||||
useFilters // useFilters!
|
||||
useFilters, // useFilters!
|
||||
useGlobalFilter // useGlobalFilter!
|
||||
)
|
||||
|
||||
// We don't want to render all of the rows for this example, so cap
|
||||
@@ -233,11 +263,6 @@ function Table({ columns, data }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<pre>
|
||||
<code>{JSON.stringify(state.filters, null, 2)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<table {...getTableProps()}>
|
||||
<thead>
|
||||
{headerGroups.map(headerGroup => (
|
||||
@@ -251,25 +276,41 @@ function Table({ columns, data }) {
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
<tr>
|
||||
<th
|
||||
colSpan={flatColumns.length}
|
||||
style={{
|
||||
textAlign: 'left',
|
||||
}}
|
||||
>
|
||||
<GlobalFilter
|
||||
preGlobalFilteredRows={preGlobalFilteredRows}
|
||||
globalFilter={state.globalFilter}
|
||||
setGlobalFilter={setGlobalFilter}
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody {...getTableBodyProps()}>
|
||||
{firstPageRows.map(
|
||||
(row, i) => {
|
||||
prepareRow(row);
|
||||
return (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map(cell => {
|
||||
return (
|
||||
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
)}
|
||||
)}
|
||||
{firstPageRows.map((row, i) => {
|
||||
prepareRow(row)
|
||||
return (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map(cell => {
|
||||
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<div>Showing the first 20 results of {rows.length} rows</div>
|
||||
<div>
|
||||
<pre>
|
||||
<code>{JSON.stringify(state.filters, null, 2)}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8094,10 +8094,10 @@ react-scripts@3.0.1:
|
||||
optionalDependencies:
|
||||
fsevents "2.0.6"
|
||||
|
||||
react-table@next:
|
||||
version "7.0.0-alpha.7"
|
||||
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-alpha.7.tgz#0cb6da6f32adb397e68505b7cdd4880d15d73017"
|
||||
integrity sha512-oXE9RRkE2CFk1OloNCSTPQ9qxOdujgkCoW5b/srbJsBog/ySkWuozBTQkxH1wGNmnSxGyTrTxJqXdXPQam7VAw==
|
||||
react-table@latest:
|
||||
version "7.0.0-rc.14"
|
||||
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-rc.14.tgz#bb4171fbdd56d78dd5f6b9e18694a36c00bd6261"
|
||||
integrity sha512-9NyzAE0kLH8HA+DK86ynxVDxniO5ZdggAqI7nDKauWXQGVYNFId8+JJSescJ2vwP9nR2JKyCEDG9c+CjIaLNkA==
|
||||
|
||||
react@^16.8.6:
|
||||
version "16.8.6"
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["react-app"],
|
||||
"plugins": ["styled-components"]
|
||||
}
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": ["react-app", "prettier"],
|
||||
"rules": {
|
||||
// "eqeqeq": 0,
|
||||
// "jsx-a11y/anchor-is-valid": 0
|
||||
}
|
||||
}
|
||||
+23
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
+38
@@ -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,3 @@
|
||||
{
|
||||
"infiniteLoopProtection": false
|
||||
}
|
||||
+193
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
@@ -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()}>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ["react-app"],
|
||||
"plugins": ["styled-components"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": ["react-app", "prettier"],
|
||||
"rules": {
|
||||
// "eqeqeq": 0,
|
||||
// "jsx-a11y/anchor-is-valid": 0
|
||||
}
|
||||
}
|
||||
@@ -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*
|
||||
@@ -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,
|
||||
]
|
||||
@@ -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
|
||||
@@ -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 |
@@ -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"
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
})
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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'))
|
||||
@@ -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
@@ -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
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "7.0.0-rc.10",
|
||||
"version": "7.0.0-rc.15",
|
||||
"description": "Hooks for building lightweight, fast and extendable datagrids for React",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/tannerlinsley/react-table#readme",
|
||||
|
||||
+3
-213
@@ -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
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+51
-35
@@ -1,79 +1,93 @@
|
||||
export const text = (rows, id, filterValue) => {
|
||||
export const text = (rows, ids, filterValue) => {
|
||||
rows = rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return String(rowValue)
|
||||
.toLowerCase()
|
||||
.includes(String(filterValue).toLowerCase())
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return String(rowValue)
|
||||
.toLowerCase()
|
||||
.includes(String(filterValue).toLowerCase())
|
||||
})
|
||||
})
|
||||
return rows
|
||||
}
|
||||
|
||||
text.autoRemove = val => !val
|
||||
|
||||
export const exactText = (rows, id, filterValue) => {
|
||||
export const exactText = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue !== undefined
|
||||
? String(rowValue).toLowerCase() === String(filterValue).toLowerCase()
|
||||
: true
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue !== undefined
|
||||
? String(rowValue).toLowerCase() === String(filterValue).toLowerCase()
|
||||
: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exactText.autoRemove = val => !val
|
||||
|
||||
export const exactTextCase = (rows, id, filterValue) => {
|
||||
export const exactTextCase = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue !== undefined
|
||||
? String(rowValue) === String(filterValue)
|
||||
: true
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue !== undefined
|
||||
? String(rowValue) === String(filterValue)
|
||||
: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exactTextCase.autoRemove = val => !val
|
||||
|
||||
export const includes = (rows, id, filterValue) => {
|
||||
export const includes = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return filterValue.includes(rowValue)
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return filterValue.includes(rowValue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
includes.autoRemove = val => !val || !val.length
|
||||
|
||||
export const includesAll = (rows, id, filterValue) => {
|
||||
export const includesAll = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return (
|
||||
rowValue &&
|
||||
rowValue.length &&
|
||||
filterValue.every(val => rowValue.includes(val))
|
||||
)
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return (
|
||||
rowValue &&
|
||||
rowValue.length &&
|
||||
filterValue.every(val => rowValue.includes(val))
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
includesAll.autoRemove = val => !val || !val.length
|
||||
|
||||
export const exact = (rows, id, filterValue) => {
|
||||
export const exact = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue === filterValue
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue === filterValue
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
exact.autoRemove = val => typeof val === 'undefined'
|
||||
|
||||
export const equals = (rows, id, filterValue) => {
|
||||
export const equals = (rows, ids, filterValue) => {
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
// eslint-disable-next-line eqeqeq
|
||||
return rowValue == filterValue
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
// eslint-disable-next-line eqeqeq
|
||||
return rowValue == filterValue
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
equals.autoRemove = val => val == null
|
||||
|
||||
export const between = (rows, id, filterValue) => {
|
||||
export const between = (rows, ids, filterValue) => {
|
||||
let [min, max] = filterValue || []
|
||||
|
||||
min = typeof min === 'number' ? min : -Infinity
|
||||
@@ -86,8 +100,10 @@ export const between = (rows, id, filterValue) => {
|
||||
}
|
||||
|
||||
return rows.filter(row => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue >= min && rowValue <= max
|
||||
return ids.some(id => {
|
||||
const rowValue = row.values[id]
|
||||
return rowValue >= min && rowValue <= max
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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 || [],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,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 +121,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 +182,7 @@ function useInstance(instance) {
|
||||
|
||||
const getToggleHideAllColumnsProps = makePropGetter(
|
||||
getToggleHideAllColumnsPropsHooks(),
|
||||
getInstance()
|
||||
{ instance: getInstance() }
|
||||
)
|
||||
|
||||
// Snapshot hook and disallow more from being added
|
||||
@@ -205,11 +200,10 @@ function useInstance(instance) {
|
||||
})
|
||||
}
|
||||
|
||||
column.getToggleHiddenProps = makePropGetter(
|
||||
getToggleHiddenPropsHooks(),
|
||||
getInstance(),
|
||||
column
|
||||
)
|
||||
column.getToggleHiddenProps = makePropGetter(getToggleHiddenPropsHooks(), {
|
||||
instance: getInstance(),
|
||||
column,
|
||||
})
|
||||
})
|
||||
|
||||
Object.assign(instance, {
|
||||
|
||||
+75
-49
@@ -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]
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from './publicUtils'
|
||||
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 { usePagination } from './plugin-hooks/usePagination'
|
||||
@@ -11,3 +12,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'
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -1,151 +1,766 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders a filterable table 1`] = `
|
||||
Snapshot Diff:
|
||||
- First value
|
||||
+ Second value
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<DocumentFragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
colspan="2"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
colspan="4"
|
||||
>
|
||||
Info
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
First Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Age
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Visits
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Status
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Profile Progress
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="6"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
placeholder="Search..."
|
||||
- value=""
|
||||
+ value="l"
|
||||
placeholder="Global search..."
|
||||
style="font-size: 1.1rem; border: 0px;"
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
@@ -87,50 +87,10 @@
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 50
|
||||
- </td>
|
||||
- </tr>
|
||||
- <tr>
|
||||
- <td>
|
||||
- firstName: derek
|
||||
- </td>
|
||||
- <td>
|
||||
- lastName: perkins
|
||||
- </td>
|
||||
- <td>
|
||||
- age: 40
|
||||
- </td>
|
||||
- <td>
|
||||
- visits: 40
|
||||
- </td>
|
||||
- <td>
|
||||
- status: Single
|
||||
- </td>
|
||||
- <td>
|
||||
- progress: 80
|
||||
- </td>
|
||||
- </tr>
|
||||
- <tr>
|
||||
- <td>
|
||||
- firstName: joe
|
||||
- </td>
|
||||
- <td>
|
||||
- lastName: bergevin
|
||||
- </td>
|
||||
- <td>
|
||||
- age: 45
|
||||
- </td>
|
||||
- <td>
|
||||
- visits: 20
|
||||
- </td>
|
||||
- <td>
|
||||
- status: Complicated
|
||||
- </td>
|
||||
- <td>
|
||||
- progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: jaylen
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: tanner
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 29
|
||||
</td>
|
||||
<td>
|
||||
visits: 100
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 50
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: derek
|
||||
</td>
|
||||
<td>
|
||||
lastName: perkins
|
||||
</td>
|
||||
<td>
|
||||
age: 40
|
||||
</td>
|
||||
<td>
|
||||
visits: 40
|
||||
</td>
|
||||
<td>
|
||||
status: Single
|
||||
</td>
|
||||
<td>
|
||||
progress: 80
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: joe
|
||||
</td>
|
||||
<td>
|
||||
lastName: bergevin
|
||||
</td>
|
||||
<td>
|
||||
age: 45
|
||||
</td>
|
||||
<td>
|
||||
visits: 20
|
||||
</td>
|
||||
<td>
|
||||
status: Complicated
|
||||
</td>
|
||||
<td>
|
||||
progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: jaylen
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 26
|
||||
</td>
|
||||
<td>
|
||||
visits: 99
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 70
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`renders a filterable table 2`] = `
|
||||
Snapshot Diff:
|
||||
- First value
|
||||
+ Second value
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<DocumentFragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
colspan="2"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
colspan="4"
|
||||
>
|
||||
Info
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
First Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value="l"
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Age
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Visits
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Status
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Profile Progress
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="6"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
placeholder="Search..."
|
||||
- value="l"
|
||||
+ value="er"
|
||||
placeholder="Global search..."
|
||||
style="font-size: 1.1rem; border: 0px;"
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
@@ -71,46 +71,46 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
- firstName: tanner
|
||||
+ firstName: derek
|
||||
</td>
|
||||
<td>
|
||||
- lastName: linsley
|
||||
+ lastName: perkins
|
||||
</td>
|
||||
<td>
|
||||
- age: 29
|
||||
+ age: 40
|
||||
</td>
|
||||
<td>
|
||||
- visits: 100
|
||||
+ visits: 40
|
||||
</td>
|
||||
<td>
|
||||
- status: In Relationship
|
||||
+ status: Single
|
||||
</td>
|
||||
<td>
|
||||
- progress: 50
|
||||
+ progress: 80
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
- firstName: jaylen
|
||||
+ firstName: joe
|
||||
</td>
|
||||
<td>
|
||||
- lastName: linsley
|
||||
+ lastName: bergevin
|
||||
</td>
|
||||
<td>
|
||||
- age: 26
|
||||
+ age: 45
|
||||
</td>
|
||||
<td>
|
||||
- visits: 99
|
||||
+ visits: 20
|
||||
</td>
|
||||
<td>
|
||||
- status: In Relationship
|
||||
+ status: Complicated
|
||||
</td>
|
||||
<td>
|
||||
- progress: 70
|
||||
+ progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: tanner
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 29
|
||||
</td>
|
||||
<td>
|
||||
visits: 100
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 50
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: jaylen
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 26
|
||||
</td>
|
||||
<td>
|
||||
visits: 99
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 70
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`renders a filterable table 3`] = `
|
||||
<DocumentFragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
colspan="2"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
colspan="4"
|
||||
>
|
||||
Info
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
First Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value="er"
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Age
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Visits
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Status
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Profile Progress
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="6"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
placeholder="Global search..."
|
||||
style="font-size: 1.1rem; border: 0px;"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: derek
|
||||
</td>
|
||||
<td>
|
||||
lastName: perkins
|
||||
</td>
|
||||
<td>
|
||||
age: 40
|
||||
</td>
|
||||
<td>
|
||||
visits: 40
|
||||
</td>
|
||||
<td>
|
||||
status: Single
|
||||
</td>
|
||||
<td>
|
||||
progress: 80
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: joe
|
||||
</td>
|
||||
<td>
|
||||
lastName: bergevin
|
||||
</td>
|
||||
<td>
|
||||
age: 45
|
||||
</td>
|
||||
<td>
|
||||
visits: 20
|
||||
</td>
|
||||
<td>
|
||||
status: Complicated
|
||||
</td>
|
||||
<td>
|
||||
progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`renders a filterable table 4`] = `
|
||||
<DocumentFragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
colspan="2"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
colspan="4"
|
||||
>
|
||||
Info
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
First Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Age
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Visits
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Status
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Profile Progress
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="6"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
placeholder="Global search..."
|
||||
style="font-size: 1.1rem; border: 0px;"
|
||||
value=""
|
||||
/>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: tanner
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 29
|
||||
</td>
|
||||
<td>
|
||||
visits: 100
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 50
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: derek
|
||||
</td>
|
||||
<td>
|
||||
lastName: perkins
|
||||
</td>
|
||||
<td>
|
||||
age: 40
|
||||
</td>
|
||||
<td>
|
||||
visits: 40
|
||||
</td>
|
||||
<td>
|
||||
status: Single
|
||||
</td>
|
||||
<td>
|
||||
progress: 80
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: joe
|
||||
</td>
|
||||
<td>
|
||||
lastName: bergevin
|
||||
</td>
|
||||
<td>
|
||||
age: 45
|
||||
</td>
|
||||
<td>
|
||||
visits: 20
|
||||
</td>
|
||||
<td>
|
||||
status: Complicated
|
||||
</td>
|
||||
<td>
|
||||
progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: jaylen
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 26
|
||||
</td>
|
||||
<td>
|
||||
visits: 99
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 70
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`renders a filterable table 5`] = `
|
||||
<DocumentFragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
colspan="2"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
colspan="4"
|
||||
>
|
||||
Info
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
First Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Last Name
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Age
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Visits
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Status
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
colspan="1"
|
||||
>
|
||||
Profile Progress
|
||||
<input
|
||||
placeholder="Search..."
|
||||
value=""
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th
|
||||
colspan="6"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
placeholder="Global search..."
|
||||
style="font-size: 1.1rem; border: 0px;"
|
||||
value="li"
|
||||
/>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: tanner
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 29
|
||||
</td>
|
||||
<td>
|
||||
visits: 100
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 50
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: joe
|
||||
</td>
|
||||
<td>
|
||||
lastName: bergevin
|
||||
</td>
|
||||
<td>
|
||||
age: 45
|
||||
</td>
|
||||
<td>
|
||||
visits: 20
|
||||
</td>
|
||||
<td>
|
||||
status: Complicated
|
||||
</td>
|
||||
<td>
|
||||
progress: 10
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
firstName: jaylen
|
||||
</td>
|
||||
<td>
|
||||
lastName: linsley
|
||||
</td>
|
||||
<td>
|
||||
age: 26
|
||||
</td>
|
||||
<td>
|
||||
visits: 99
|
||||
</td>
|
||||
<td>
|
||||
status: In Relationship
|
||||
</td>
|
||||
<td>
|
||||
progress: 70
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react'
|
||||
import { render, fireEvent } from '@testing-library/react'
|
||||
import { useTable } from '../../hooks/useTable'
|
||||
import { useFilters } from '../useFilters'
|
||||
import { useGlobalFilter } from '../useGlobalFilter'
|
||||
|
||||
const data = [
|
||||
{
|
||||
@@ -58,13 +59,17 @@ function Table({ columns, data }) {
|
||||
headerGroups,
|
||||
rows,
|
||||
prepareRow,
|
||||
flatColumns,
|
||||
state,
|
||||
setGlobalFilter,
|
||||
} = useTable(
|
||||
{
|
||||
columns,
|
||||
data,
|
||||
defaultColumn,
|
||||
},
|
||||
useFilters
|
||||
useFilters,
|
||||
useGlobalFilter
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -80,6 +85,28 @@ function Table({ columns, data }) {
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
<tr>
|
||||
<th
|
||||
colSpan={flatColumns.length}
|
||||
style={{
|
||||
textAlign: 'left',
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<input
|
||||
value={state.globalFilter || ''}
|
||||
onChange={e => {
|
||||
setGlobalFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
|
||||
}}
|
||||
placeholder={`Global search...`}
|
||||
style={{
|
||||
fontSize: '1.1rem',
|
||||
border: '0',
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody {...getTableBodyProps()}>
|
||||
{rows.map(
|
||||
@@ -142,8 +169,11 @@ function App() {
|
||||
}
|
||||
|
||||
test('renders a filterable table', () => {
|
||||
const { getAllByPlaceholderText, asFragment } = render(<App />)
|
||||
const { getAllByPlaceholderText, getByPlaceholderText, asFragment } = render(
|
||||
<App />
|
||||
)
|
||||
|
||||
const globalFilterInput = getByPlaceholderText('Global search...')
|
||||
const filterInputs = getAllByPlaceholderText('Search...')
|
||||
|
||||
const beforeFilter = asFragment()
|
||||
@@ -156,6 +186,17 @@ test('renders a filterable table', () => {
|
||||
|
||||
const afterFilter2 = asFragment()
|
||||
|
||||
expect(beforeFilter).toMatchDiffSnapshot(afterFilter1)
|
||||
expect(afterFilter1).toMatchDiffSnapshot(afterFilter2)
|
||||
fireEvent.change(filterInputs[1], { target: { value: '' } })
|
||||
|
||||
const afterFilter3 = asFragment()
|
||||
|
||||
fireEvent.change(globalFilterInput, { target: { value: 'li' } })
|
||||
|
||||
const afterFilter4 = asFragment()
|
||||
|
||||
expect(beforeFilter).toMatchSnapshot()
|
||||
expect(afterFilter1).toMatchSnapshot()
|
||||
expect(afterFilter2).toMatchSnapshot()
|
||||
expect(afterFilter3).toMatchSnapshot()
|
||||
expect(afterFilter4).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@@ -64,6 +64,9 @@ function Table({ columns, data }) {
|
||||
columns,
|
||||
data,
|
||||
defaultColumn,
|
||||
initialState: {
|
||||
groupBy: ["Column Doesn't Exist"],
|
||||
},
|
||||
},
|
||||
useGroupBy,
|
||||
useExpanded
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -3,10 +3,11 @@ import React from 'react'
|
||||
import {
|
||||
actions,
|
||||
getFirstDefined,
|
||||
isFunction,
|
||||
getFilterMethod,
|
||||
useMountedLayoutEffect,
|
||||
functionalUpdate,
|
||||
useGetLatest,
|
||||
shouldAutoRemoveFilter,
|
||||
} from '../utils'
|
||||
import * as filterTypes from '../filterTypes'
|
||||
|
||||
@@ -33,7 +34,7 @@ function reducer(state, action, previousState, instance) {
|
||||
if (action.type === actions.resetFilters) {
|
||||
return {
|
||||
...state,
|
||||
filters: [],
|
||||
filters: instance.initialState.filters || [],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ function reducer(state, action, previousState, instance) {
|
||||
)
|
||||
|
||||
//
|
||||
if (shouldAutoRemove(filterMethod.autoRemove, newFilter)) {
|
||||
if (shouldAutoRemoveFilter(filterMethod.autoRemove, newFilter)) {
|
||||
return {
|
||||
...state,
|
||||
filters: state.filters.filter(d => d.id !== columnId),
|
||||
@@ -103,7 +104,7 @@ function reducer(state, action, previousState, instance) {
|
||||
filterTypes
|
||||
)
|
||||
|
||||
if (shouldAutoRemove(filterMethod.autoRemove, filter.value)) {
|
||||
if (shouldAutoRemoveFilter(filterMethod.autoRemove, filter.value)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -164,17 +165,9 @@ function useInstance(instance) {
|
||||
column.filterValue = found && found.value
|
||||
})
|
||||
|
||||
// TODO: Create a filter cache for incremental high speed multi-filtering
|
||||
// This gets pretty complicated pretty fast, since you have to maintain a
|
||||
// cache for each row group (top-level rows, and each row's recursive subrows)
|
||||
// This would make multi-filtering a lot faster though. Too far?
|
||||
|
||||
const { filteredRows, filteredFlatRows } = React.useMemo(() => {
|
||||
const [filteredRows, filteredFlatRows] = React.useMemo(() => {
|
||||
if (manualFilters || !filters.length) {
|
||||
return {
|
||||
filteredRows: rows,
|
||||
filteredFlatRows: flatRows,
|
||||
}
|
||||
return [rows, flatRows]
|
||||
}
|
||||
|
||||
const filteredFlatRows = []
|
||||
@@ -213,9 +206,8 @@ function useInstance(instance) {
|
||||
// to get the filtered rows back
|
||||
column.filteredRows = filterMethod(
|
||||
filteredSoFar,
|
||||
columnId,
|
||||
filterValue,
|
||||
column
|
||||
[columnId],
|
||||
filterValue
|
||||
)
|
||||
|
||||
return column.filteredRows
|
||||
@@ -244,10 +236,7 @@ function useInstance(instance) {
|
||||
return filteredRows
|
||||
}
|
||||
|
||||
return {
|
||||
filteredRows: filterRows(rows),
|
||||
filteredFlatRows,
|
||||
}
|
||||
return [filterRows(rows), filteredFlatRows]
|
||||
}, [manualFilters, filters, rows, flatRows, flatColumns, userFilterTypes])
|
||||
|
||||
React.useMemo(() => {
|
||||
@@ -284,16 +273,3 @@ function useInstance(instance) {
|
||||
setAllFilters,
|
||||
})
|
||||
}
|
||||
|
||||
function shouldAutoRemove(autoRemove, value) {
|
||||
return autoRemove ? autoRemove(value) : typeof value === 'undefined'
|
||||
}
|
||||
|
||||
function getFilterMethod(filter, userFilterTypes, filterTypes) {
|
||||
return (
|
||||
isFunction(filter) ||
|
||||
userFilterTypes[filter] ||
|
||||
filterTypes[filter] ||
|
||||
filterTypes.text
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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`,
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,152 @@
|
||||
import React from 'react'
|
||||
|
||||
import {
|
||||
actions,
|
||||
getFilterMethod,
|
||||
useMountedLayoutEffect,
|
||||
functionalUpdate,
|
||||
useGetLatest,
|
||||
shouldAutoRemoveFilter,
|
||||
ensurePluginOrder,
|
||||
} from '../utils'
|
||||
import * as filterTypes from '../filterTypes'
|
||||
|
||||
// Actions
|
||||
actions.resetGlobalFilter = 'resetGlobalFilter'
|
||||
actions.setGlobalFilter = 'setGlobalFilter'
|
||||
|
||||
export const useGlobalFilter = hooks => {
|
||||
hooks.stateReducers.push(reducer)
|
||||
hooks.useInstance.push(useInstance)
|
||||
}
|
||||
|
||||
useGlobalFilter.pluginName = 'useGlobalFilter'
|
||||
|
||||
function reducer(state, action, previousState, instance) {
|
||||
if (action.type === actions.resetGlobalFilter) {
|
||||
return {
|
||||
...state,
|
||||
globalFilter: instance.initialState.globalFilter || undefined,
|
||||
}
|
||||
}
|
||||
|
||||
if (action.type === actions.setGlobalFilter) {
|
||||
const { filterValue } = action
|
||||
const { userFilterTypes } = instance
|
||||
|
||||
const filterMethod = getFilterMethod(
|
||||
instance.globalFilter,
|
||||
userFilterTypes || {},
|
||||
filterTypes
|
||||
)
|
||||
|
||||
const newFilter = functionalUpdate(filterValue, state.globalFilter)
|
||||
|
||||
//
|
||||
if (shouldAutoRemoveFilter(filterMethod.autoRemove, newFilter)) {
|
||||
const { globalFilter, ...stateWithoutGlobalFilter } = state
|
||||
return stateWithoutGlobalFilter
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
globalFilter: newFilter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function useInstance(instance) {
|
||||
const {
|
||||
data,
|
||||
rows,
|
||||
flatRows,
|
||||
flatColumns,
|
||||
filterTypes: userFilterTypes,
|
||||
globalFilter,
|
||||
manualGlobalFilter,
|
||||
state: { globalFilter: globalFilterValue },
|
||||
dispatch,
|
||||
autoResetGlobalFilters = true,
|
||||
plugins,
|
||||
} = instance
|
||||
|
||||
ensurePluginOrder(plugins, [], 'useGlobalFilter', [
|
||||
'useSortBy',
|
||||
'useExpanded',
|
||||
])
|
||||
|
||||
const setGlobalFilter = filterValue => {
|
||||
dispatch({ type: actions.setGlobalFilter, filterValue })
|
||||
}
|
||||
|
||||
// TODO: Create a filter cache for incremental high speed multi-filtering
|
||||
// This gets pretty complicated pretty fast, since you have to maintain a
|
||||
// cache for each row group (top-level rows, and each row's recursive subrows)
|
||||
// This would make multi-filtering a lot faster though. Too far?
|
||||
|
||||
const [globalFilteredRows, globalFilteredFlatRows] = React.useMemo(() => {
|
||||
if (manualGlobalFilter || typeof globalFilterValue === 'undefined') {
|
||||
return [rows, flatRows]
|
||||
}
|
||||
|
||||
const filteredFlatRows = []
|
||||
|
||||
const filterMethod = getFilterMethod(
|
||||
globalFilter,
|
||||
userFilterTypes || {},
|
||||
filterTypes
|
||||
)
|
||||
|
||||
if (!filterMethod) {
|
||||
console.warn(`Could not find a valid 'globalFilter' option.`)
|
||||
return rows
|
||||
}
|
||||
|
||||
// Filters top level and nested rows
|
||||
const filterRows = filteredRows => {
|
||||
return filterMethod(
|
||||
filteredRows,
|
||||
flatColumns.map(d => d.id),
|
||||
globalFilterValue
|
||||
).map(row => {
|
||||
filteredFlatRows.push(row)
|
||||
|
||||
return {
|
||||
...row,
|
||||
subRows:
|
||||
row.subRows && row.subRows.length
|
||||
? filterRows(row.subRows)
|
||||
: row.subRows,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return [filterRows(rows), filteredFlatRows]
|
||||
}, [
|
||||
manualGlobalFilter,
|
||||
globalFilter,
|
||||
userFilterTypes,
|
||||
rows,
|
||||
flatRows,
|
||||
flatColumns,
|
||||
globalFilterValue,
|
||||
])
|
||||
|
||||
const getAutoResetGlobalFilters = useGetLatest(autoResetGlobalFilters)
|
||||
|
||||
useMountedLayoutEffect(() => {
|
||||
if (getAutoResetGlobalFilters()) {
|
||||
dispatch({ type: actions.resetGlobalFilter })
|
||||
}
|
||||
}, [dispatch, manualGlobalFilter ? null : data])
|
||||
|
||||
Object.assign(instance, {
|
||||
preGlobalFilteredRows: rows,
|
||||
preGlobalFilteredFlatRows: flatRows,
|
||||
globalFilteredRows,
|
||||
globalFilteredFlatRows,
|
||||
rows: globalFilteredRows,
|
||||
flatRows: globalFilteredFlatRows,
|
||||
setGlobalFilter,
|
||||
})
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -37,7 +37,7 @@ function reducer(state, action, previousState, instance) {
|
||||
if (action.type === actions.resetPage) {
|
||||
return {
|
||||
...state,
|
||||
pageIndex: 0,
|
||||
pageIndex: instance.initialState.pageIndex || 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -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 || {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -267,6 +267,19 @@ export function expandRows(
|
||||
return expandedRows
|
||||
}
|
||||
|
||||
export function getFilterMethod(filter, userFilterTypes, filterTypes) {
|
||||
return (
|
||||
isFunction(filter) ||
|
||||
userFilterTypes[filter] ||
|
||||
filterTypes[filter] ||
|
||||
filterTypes.text
|
||||
)
|
||||
}
|
||||
|
||||
export function shouldAutoRemoveFilter(autoRemove, value) {
|
||||
return autoRemove ? autoRemove(value) : typeof value === 'undefined'
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
const reOpenBracket = /\[/g
|
||||
|
||||
Reference in New Issue
Block a user