mirror of
https://github.com/gosticks/react-table.git
synced 2025-10-16 11:55:36 +00:00
Normalize API method names and row modesl, add expandAll functionality including prop getter
This commit is contained in:
parent
2bf99aaea0
commit
083e81dc81
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"dist/index.js": {
|
"dist/index.js": {
|
||||||
"bundled": 113244,
|
"bundled": 131178,
|
||||||
"minified": 52531,
|
"minified": 61448,
|
||||||
"gzipped": 13840
|
"gzipped": 15699
|
||||||
},
|
},
|
||||||
"dist/index.es.js": {
|
"dist/index.es.js": {
|
||||||
"bundled": 112307,
|
"bundled": 130236,
|
||||||
"minified": 51695,
|
"minified": 60607,
|
||||||
"gzipped": 13674,
|
"gzipped": 15525,
|
||||||
"treeshaked": {
|
"treeshaked": {
|
||||||
"rollup": {
|
"rollup": {
|
||||||
"code": 80,
|
"code": 80,
|
||||||
"import_statements": 21
|
"import_statements": 21
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"code": 8471
|
"code": 8457
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
16
CHANGELOG.md
16
CHANGELOG.md
@ -7,7 +7,7 @@
|
|||||||
- Renamed `instance.flatColumns` to `instance.allColumns` which now accumulates ALL columns created for the table, visible or not.
|
- Renamed `instance.flatColumns` to `instance.allColumns` which now accumulates ALL columns created for the table, visible or not.
|
||||||
- Added the `instance.visibleColumns` object
|
- Added the `instance.visibleColumns` object
|
||||||
- Fix an issue where `useAsyncDebounce` would crash when passed arguments
|
- Fix an issue where `useAsyncDebounce` would crash when passed arguments
|
||||||
- Started development on the `usePivotColumns` plugin, which can be tested currently using the `_UNSTABLE_usePivoteColumns` export.
|
- Started development on the `usePivotColumns` plugin, which can be tested currently using the `_UNSTABLE_usePivotColumns` export.
|
||||||
- Renamed `cell.isRepeatedValue` to `cell.isPlaceholder`
|
- Renamed `cell.isRepeatedValue` to `cell.isPlaceholder`
|
||||||
- Removed `useConsumeHookGetter` as it was inefficient most of the time and noisy
|
- Removed `useConsumeHookGetter` as it was inefficient most of the time and noisy
|
||||||
- All hooks are now "consumed" right after main plugin functions are run. This means that any attempt to add a plugin after that will result in a runtime error (for good reason, since using hook points should not be a conditional or async operation)
|
- All hooks are now "consumed" right after main plugin functions are run. This means that any attempt to add a plugin after that will result in a runtime error (for good reason, since using hook points should not be a conditional or async operation)
|
||||||
@ -25,6 +25,20 @@
|
|||||||
- Fixed an issue where `useGlobalFilter` could be placed after `usePagination`
|
- Fixed an issue where `useGlobalFilter` could be placed after `usePagination`
|
||||||
- Added the sort order direction as a parameter to the sortMethod function
|
- Added the sort order direction as a parameter to the sortMethod function
|
||||||
- Fixed an issue where user filter types were not being referenced correctly
|
- Fixed an issue where user filter types were not being referenced correctly
|
||||||
|
- Renamed the `row.getExpandedToggleProps` to `row.getToggleRowExpandedProps`
|
||||||
|
- Renamed the `row.toggleExpanded` method to `row.toggleRowExpanded`
|
||||||
|
- Added the `instance.toggleRowExpanded` and `instance.toggleAllRowsExpanded` methods
|
||||||
|
- Added the `instance.getToggleAllRowsExpandedProps` prop getter
|
||||||
|
- Added the `instance.filteredRowsById` property
|
||||||
|
- Added the `instance.preFilteredRowsById` property
|
||||||
|
- useFilters now properly updates the `instance.rowsById` property
|
||||||
|
- Added the `instance.globalFilteredRowsById` property
|
||||||
|
- Added the `instance.preGlobalFilteredRowsById` property
|
||||||
|
- useGlobalFilter now properly updates the `instance.rowsById` property
|
||||||
|
- Added the `instance.nonGroupedFlatRows` property
|
||||||
|
- Added the `instance.nonGroupedRowsById` property
|
||||||
|
- Added the `instance.onlyGroupedFlatRows` property
|
||||||
|
- Added the `instance.onlyGroupedRowsById` property
|
||||||
|
|
||||||
## 7.0.0-rc.15
|
## 7.0.0-rc.15
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,13 @@ The following properties are available on the table instance returned from `useT
|
|||||||
|
|
||||||
- `rows: Array<Row>`
|
- `rows: Array<Row>`
|
||||||
- An array of **expanded** rows.
|
- An array of **expanded** rows.
|
||||||
|
- `toggleRowExpanded: Function(rowId, isExpanded?)`
|
||||||
|
- A function to toggle whether a row is expanded or not. The `isExpanded` boolean is optional, otherwise it will be a true toggle action
|
||||||
|
- `toggleAllRowsExpanded: Function(isExpanded?)`
|
||||||
|
- A function to toggle whether all of the rows in the table are expanded or not. The `isExpanded` boolean is optional, otherwise it will be a true toggle action
|
||||||
|
- `isAllRowsExpanded`
|
||||||
|
- `getToggleAllRowsExpandedProps: Function(userProps) => props`
|
||||||
|
- A prop getter function that returns all necessary props for an element to be clicked and toggle all of the rows expanded or not.
|
||||||
|
|
||||||
### Row Properties
|
### Row Properties
|
||||||
|
|
||||||
@ -48,7 +55,7 @@ The following additional properties are available on every `row` object returned
|
|||||||
|
|
||||||
- `isExpanded: Bool`
|
- `isExpanded: Bool`
|
||||||
- If `true`, this row is in an expanded state.
|
- If `true`, this row is in an expanded state.
|
||||||
- `toggleExpanded: Function(?isExpanded: Bool) => void`
|
- `toggleRowExpanded: Function(?isExpanded: Bool) => void`
|
||||||
- This function will toggle the expanded state of a row between `true` and `false` or, if an `isExpanded` boolean is passed to the function, it will be set as the new `isExpanded` value.
|
- This function will toggle the expanded state of a row between `true` and `false` or, if an `isExpanded` boolean is passed to the function, it will be set as the new `isExpanded` value.
|
||||||
- Rows with a hard-coded `manualExpandedKey` (defaults to `expanded`) set to `true` are not affected by this function or the internal expanded state.
|
- Rows with a hard-coded `manualExpandedKey` (defaults to `expanded`) set to `true` are not affected by this function or the internal expanded state.
|
||||||
|
|
||||||
|
|||||||
@ -93,11 +93,6 @@ The following options are supported on any column object you can pass to `column
|
|||||||
- Receives the table instance and cell model as props
|
- Receives the table instance and cell model as props
|
||||||
- Must return valid JSX
|
- Must return valid JSX
|
||||||
- This function (or component) is primarily used for formatting the column value, eg. If your column accessor returns a date object, you can use a `Cell` function to format that date to a readable format.
|
- This function (or component) is primarily used for formatting the column value, eg. If your column accessor returns a date object, you can use a `Cell` function to format that date to a readable format.
|
||||||
- `show: Bool`
|
|
||||||
- Optional
|
|
||||||
- Defaults to `undefined`
|
|
||||||
- If set to `true`, will take priority over any state in `hiddenColumns` and force this column to be visible at all times.
|
|
||||||
- If set to `false` will take priority over any state in `hiddenColumns` and force this column to be hidden at all times.
|
|
||||||
- `width: Int`
|
- `width: Int`
|
||||||
- Optional
|
- Optional
|
||||||
- Defaults to `150`
|
- Defaults to `150`
|
||||||
|
|||||||
@ -88,14 +88,18 @@ function App() {
|
|||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
// Build our expander column
|
// Build our expander column
|
||||||
Header: () => null, // No header, please
|
|
||||||
id: 'expander', // Make sure it has an ID
|
id: 'expander', // Make sure it has an ID
|
||||||
|
Header: ({ getToggleAllRowsExpandedProps, isAllRowsExpanded }) => (
|
||||||
|
<span {...getToggleAllRowsExpandedProps()}>
|
||||||
|
{isAllRowsExpanded ? '👇' : '👉'}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
Cell: ({ row }) =>
|
Cell: ({ row }) =>
|
||||||
// Use the row.canExpand and row.getExpandedToggleProps prop getter
|
// Use the row.canExpand and row.getToggleRowExpandedProps prop getter
|
||||||
// to build the toggle for expanding a row
|
// to build the toggle for expanding a row
|
||||||
row.canExpand ? (
|
row.canExpand ? (
|
||||||
<span
|
<span
|
||||||
{...row.getExpandedToggleProps({
|
{...row.getToggleRowExpandedProps({
|
||||||
style: {
|
style: {
|
||||||
// We can even use the row.depth property
|
// We can even use the row.depth property
|
||||||
// and paddingLeft to indicate the depth
|
// and paddingLeft to indicate the depth
|
||||||
|
|||||||
@ -97,7 +97,7 @@ function Table({ columns, data }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
{...row.getExpandedToggleProps({
|
{...row.getToggleRowExpandedProps({
|
||||||
style: {
|
style: {
|
||||||
// We can even use the row.depth property
|
// We can even use the row.depth property
|
||||||
// and paddingLeft to indicate the depth
|
// and paddingLeft to indicate the depth
|
||||||
|
|||||||
@ -103,7 +103,7 @@ function Table({ columns, data }) {
|
|||||||
{cell.isGrouped ? (
|
{cell.isGrouped ? (
|
||||||
// If it's a grouped cell, add an expander and row count
|
// If it's a grouped cell, add an expander and row count
|
||||||
<>
|
<>
|
||||||
<span {...row.getExpandedToggleProps()}>
|
<span {...row.getToggleRowExpandedProps()}>
|
||||||
{row.isExpanded ? '👇' : '👉'}
|
{row.isExpanded ? '👇' : '👉'}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
{cell.render('Cell')} ({row.subRows.length})
|
{cell.render('Cell')} ({row.subRows.length})
|
||||||
|
|||||||
@ -378,7 +378,7 @@ function Table({ columns, data, updateMyData, skipPageReset }) {
|
|||||||
{cell.isGrouped ? (
|
{cell.isGrouped ? (
|
||||||
// If it's a grouped cell, add an expander and row count
|
// If it's a grouped cell, add an expander and row count
|
||||||
<>
|
<>
|
||||||
<span {...row.getExpandedToggleProps()}>
|
<span {...row.getToggleRowExpandedProps()}>
|
||||||
{row.isExpanded ? '👇' : '👉'}
|
{row.isExpanded ? '👇' : '👉'}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
{cell.render('Cell', { editable: false })} (
|
{cell.render('Cell', { editable: false })} (
|
||||||
|
|||||||
@ -8095,10 +8095,10 @@ react-scripts@3.0.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "2.0.6"
|
fsevents "2.0.6"
|
||||||
|
|
||||||
react-table@next:
|
react-table@latest:
|
||||||
version "7.0.0-alpha.7"
|
version "7.0.0-rc.15"
|
||||||
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-alpha.7.tgz#0cb6da6f32adb397e68505b7cdd4880d15d73017"
|
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-rc.15.tgz#bb855e4e2abbb4aaf0ed2334404a41f3ada8e13a"
|
||||||
integrity sha512-oXE9RRkE2CFk1OloNCSTPQ9qxOdujgkCoW5b/srbJsBog/ySkWuozBTQkxH1wGNmnSxGyTrTxJqXdXPQam7VAw==
|
integrity sha512-ofMOlgrioHhhvHjvjsQkxvfQzU98cqwy6BjPGNwhLN1vhgXeWi0mUGreaCPvRenEbTiXsQbMl4k3Xmx3Mut8Rw==
|
||||||
|
|
||||||
react@^16.8.6:
|
react@^16.8.6:
|
||||||
version "16.8.6"
|
version "16.8.6"
|
||||||
|
|||||||
@ -380,7 +380,7 @@ function Table({ columns, data, updateMyData, skipReset }) {
|
|||||||
{cell.isGrouped ? (
|
{cell.isGrouped ? (
|
||||||
// If it's a grouped cell, add an expander and row count
|
// If it's a grouped cell, add an expander and row count
|
||||||
<>
|
<>
|
||||||
<span {...row.getExpandedToggleProps()}>
|
<span {...row.getToggleRowExpandedProps()}>
|
||||||
{row.isExpanded ? '👇' : '👉'}
|
{row.isExpanded ? '👇' : '👉'}
|
||||||
</span>{' '}
|
</span>{' '}
|
||||||
{cell.render('Cell', { editable: false })} (
|
{cell.render('Cell', { editable: false })} (
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import {
|
|||||||
useTable,
|
useTable,
|
||||||
useGroupBy,
|
useGroupBy,
|
||||||
useExpanded,
|
useExpanded,
|
||||||
_UNSTABLE_usePivoteColumns,
|
_UNSTABLE_usePivotColumns,
|
||||||
} from 'react-table'
|
} from 'react-table'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import localizedFormat from 'dayjs/plugin/localizedFormat'
|
import localizedFormat from 'dayjs/plugin/localizedFormat'
|
||||||
@ -98,8 +98,8 @@ function Table({ columns, data }) {
|
|||||||
data,
|
data,
|
||||||
},
|
},
|
||||||
useGroupBy,
|
useGroupBy,
|
||||||
_UNSTABLE_usePivoteColumns,
|
_UNSTABLE_usePivotColumns,
|
||||||
useExpanded // useGroupBy and _UNSTABLE_usePivoteColumns would be pretty useless without useExpanded ;)
|
useExpanded // useGroupBy and _UNSTABLE_usePivotColumns would be pretty useless without useExpanded ;)
|
||||||
)
|
)
|
||||||
|
|
||||||
// We don't want to render all of the rows for this example, so cap
|
// We don't want to render all of the rows for this example, so cap
|
||||||
@ -197,7 +197,7 @@ function Table({ columns, data }) {
|
|||||||
<td {...cell.getCellProps()}>
|
<td {...cell.getCellProps()}>
|
||||||
{cell.isGrouped ? (
|
{cell.isGrouped ? (
|
||||||
<>
|
<>
|
||||||
<span {...row.getExpandedToggleProps()}>
|
<span {...row.getToggleRowExpandedProps()}>
|
||||||
{row.isExpanded ? '👇' : '👉'} {cell.render('Cell')}{' '}
|
{row.isExpanded ? '👇' : '👉'} {cell.render('Cell')}{' '}
|
||||||
({row.subRows.length})
|
({row.subRows.length})
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -120,9 +120,9 @@ function App() {
|
|||||||
id: 'expander', // It needs an ID
|
id: 'expander', // It needs an ID
|
||||||
Cell: ({ row }) => (
|
Cell: ({ row }) => (
|
||||||
// Use Cell to render an expander for each row.
|
// Use Cell to render an expander for each row.
|
||||||
// We can use the getExpandedToggleProps prop-getter
|
// We can use the getToggleRowExpandedProps prop-getter
|
||||||
// to build the expander.
|
// to build the expander.
|
||||||
<span {...row.getExpandedToggleProps()}>
|
<span {...row.getToggleRowExpandedProps()}>
|
||||||
{row.isExpanded ? '👇' : '👉'}
|
{row.isExpanded ? '👇' : '👉'}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
import {
|
import {
|
||||||
linkColumnStructure,
|
linkColumnStructure,
|
||||||
flattenColumns,
|
flattenColumns,
|
||||||
assignColumnAccessor,
|
assignColumnAccessor,
|
||||||
accessRowsForColumn,
|
unpreparedAccessWarning,
|
||||||
makeHeaderGroups,
|
makeHeaderGroups,
|
||||||
decorateColumn,
|
decorateColumn,
|
||||||
dedupeBy,
|
dedupeBy,
|
||||||
@ -488,10 +489,12 @@ function calculateHeaderWidths(headers, left = 0) {
|
|||||||
header.totalLeft = left
|
header.totalLeft = left
|
||||||
|
|
||||||
if (subHeaders && subHeaders.length) {
|
if (subHeaders && subHeaders.length) {
|
||||||
const [totalMinWidth, totalWidth, totalMaxWidth, totalFlexWidth] = calculateHeaderWidths(
|
const [
|
||||||
subHeaders,
|
totalMinWidth,
|
||||||
left
|
totalWidth,
|
||||||
)
|
totalMaxWidth,
|
||||||
|
totalFlexWidth,
|
||||||
|
] = calculateHeaderWidths(subHeaders, left)
|
||||||
header.totalMinWidth = totalMinWidth
|
header.totalMinWidth = totalMinWidth
|
||||||
header.totalWidth = totalWidth
|
header.totalWidth = totalWidth
|
||||||
header.totalMaxWidth = totalMaxWidth
|
header.totalMaxWidth = totalMaxWidth
|
||||||
@ -516,3 +519,94 @@ function calculateHeaderWidths(headers, left = 0) {
|
|||||||
|
|
||||||
return [sumTotalMinWidth, sumTotalWidth, sumTotalMaxWidth, sumTotalFlexWidth]
|
return [sumTotalMinWidth, sumTotalWidth, sumTotalMaxWidth, sumTotalFlexWidth]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function accessRowsForColumn({
|
||||||
|
data,
|
||||||
|
rows,
|
||||||
|
flatRows,
|
||||||
|
rowsById,
|
||||||
|
column,
|
||||||
|
getRowId,
|
||||||
|
getSubRows,
|
||||||
|
accessValueHooks,
|
||||||
|
getInstance,
|
||||||
|
}) {
|
||||||
|
// Access the row's data column-by-column
|
||||||
|
// We do it this way so we can incrementally add materialized
|
||||||
|
// columns after the first pass and avoid excessive looping
|
||||||
|
const accessRow = (originalRow, rowIndex, depth = 0, parent, parentRows) => {
|
||||||
|
// Keep the original reference around
|
||||||
|
const original = originalRow
|
||||||
|
|
||||||
|
const id = getRowId(originalRow, rowIndex, parent)
|
||||||
|
|
||||||
|
let row = rowsById[id]
|
||||||
|
|
||||||
|
// If the row hasn't been created, let's make it
|
||||||
|
if (!row) {
|
||||||
|
row = {
|
||||||
|
id,
|
||||||
|
original,
|
||||||
|
index: rowIndex,
|
||||||
|
depth,
|
||||||
|
cells: [{}], // This is a dummy cell
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override common array functions (and the dummy cell's getCellProps function)
|
||||||
|
// to show an error if it is accessed without calling prepareRow
|
||||||
|
row.cells.map = unpreparedAccessWarning
|
||||||
|
row.cells.filter = unpreparedAccessWarning
|
||||||
|
row.cells.forEach = unpreparedAccessWarning
|
||||||
|
row.cells[0].getCellProps = unpreparedAccessWarning
|
||||||
|
|
||||||
|
// Create the cells and values
|
||||||
|
row.values = {}
|
||||||
|
|
||||||
|
// Push this row into the parentRows array
|
||||||
|
parentRows.push(row)
|
||||||
|
// Keep track of every row in a flat array
|
||||||
|
flatRows.push(row)
|
||||||
|
// Also keep track of every row by its ID
|
||||||
|
rowsById[id] = row
|
||||||
|
|
||||||
|
// Get the original subrows
|
||||||
|
row.originalSubRows = getSubRows(originalRow, rowIndex)
|
||||||
|
|
||||||
|
// Then recursively access them
|
||||||
|
if (row.originalSubRows) {
|
||||||
|
const subRows = []
|
||||||
|
row.originalSubRows.forEach((d, i) =>
|
||||||
|
accessRow(d, i, depth + 1, row, subRows)
|
||||||
|
)
|
||||||
|
// Keep the new subRows array on the row
|
||||||
|
row.subRows = subRows
|
||||||
|
}
|
||||||
|
} else if (row.subRows) {
|
||||||
|
// If the row exists, then it's already been accessed
|
||||||
|
// Keep recursing, but don't worry about passing the
|
||||||
|
// accumlator array (those rows already exist)
|
||||||
|
row.originalSubRows.forEach((d, i) => accessRow(d, i, depth + 1, row))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the column has an accessor, use it to get a value
|
||||||
|
if (column.accessor) {
|
||||||
|
row.values[column.id] = column.accessor(originalRow, rowIndex, row)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow plugins to manipulate the column value
|
||||||
|
row.values[column.id] = reduceHooks(
|
||||||
|
accessValueHooks,
|
||||||
|
row.values[column.id],
|
||||||
|
{
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
instance: getInstance(),
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.forEach((originalRow, rowIndex) =>
|
||||||
|
accessRow(originalRow, rowIndex, 0, undefined, rows)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ export { useGlobalFilter } from './plugin-hooks/useGlobalFilter'
|
|||||||
export { useGroupBy } from './plugin-hooks/useGroupBy'
|
export { useGroupBy } from './plugin-hooks/useGroupBy'
|
||||||
export { useSortBy } from './plugin-hooks/useSortBy'
|
export { useSortBy } from './plugin-hooks/useSortBy'
|
||||||
export { usePagination } from './plugin-hooks/usePagination'
|
export { usePagination } from './plugin-hooks/usePagination'
|
||||||
export { usePivotColumns as _UNSTABLE_usePivoteColumns } from './plugin-hooks/usePivotColumns'
|
export { _UNSTABLE_usePivotColumns } from './plugin-hooks/_UNSTABLE_usePivotColumns'
|
||||||
export { useRowSelect } from './plugin-hooks/useRowSelect'
|
export { useRowSelect } from './plugin-hooks/useRowSelect'
|
||||||
export { useRowState } from './plugin-hooks/useRowState'
|
export { useRowState } from './plugin-hooks/useRowState'
|
||||||
export { useColumnOrder } from './plugin-hooks/useColumnOrder'
|
export { useColumnOrder } from './plugin-hooks/useColumnOrder'
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { flattenColumns, getFirstDefined } from '../utils'
|
|||||||
actions.resetPivot = 'resetPivot'
|
actions.resetPivot = 'resetPivot'
|
||||||
actions.togglePivot = 'togglePivot'
|
actions.togglePivot = 'togglePivot'
|
||||||
|
|
||||||
export const usePivotColumns = hooks => {
|
export const _UNSTABLE_usePivotColumns = hooks => {
|
||||||
hooks.getPivotToggleProps = [defaultGetPivotToggleProps]
|
hooks.getPivotToggleProps = [defaultGetPivotToggleProps]
|
||||||
hooks.stateReducers.push(reducer)
|
hooks.stateReducers.push(reducer)
|
||||||
hooks.useInstanceAfterData.push(useInstanceAfterData)
|
hooks.useInstanceAfterData.push(useInstanceAfterData)
|
||||||
@ -28,7 +28,7 @@ export const usePivotColumns = hooks => {
|
|||||||
hooks.prepareRow.push(prepareRow)
|
hooks.prepareRow.push(prepareRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
usePivotColumns.pluginName = 'usePivotColumns'
|
_UNSTABLE_usePivotColumns.pluginName = 'usePivotColumns'
|
||||||
|
|
||||||
const defaultPivotColumns = []
|
const defaultPivotColumns = []
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ function App() {
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
paddingLeft: `${row.depth * 2}rem`,
|
paddingLeft: `${row.depth * 2}rem`,
|
||||||
}}
|
}}
|
||||||
onClick={() => row.toggleExpanded()}
|
onClick={() => row.toggleRowExpanded()}
|
||||||
>
|
>
|
||||||
{row.isExpanded ? 'Collapse' : 'Expand'} Row {row.id}
|
{row.isExpanded ? 'Collapse' : 'Expand'} Row {row.id}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -113,7 +113,7 @@ function Table({ columns, data }) {
|
|||||||
style={{
|
style={{
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
}}
|
}}
|
||||||
onClick={() => row.toggleExpanded()}
|
onClick={() => row.toggleRowExpanded()}
|
||||||
>
|
>
|
||||||
{row.isExpanded ? '👇' : '👉'}
|
{row.isExpanded ? '👇' : '👉'}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import React from 'react'
|
|||||||
import { render, fireEvent } from '../../../test-utils/react-testing'
|
import { render, fireEvent } from '../../../test-utils/react-testing'
|
||||||
import { useTable } from '../../hooks/useTable'
|
import { useTable } from '../../hooks/useTable'
|
||||||
import { useRowState } from '../useRowState'
|
import { useRowState } from '../useRowState'
|
||||||
import { useGlobalFilter } from '../useGlobalFilter'
|
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{
|
{
|
||||||
@ -67,8 +66,7 @@ function Table({ columns, data }) {
|
|||||||
initialRowStateAccessor: () => ({ count: 0 }),
|
initialRowStateAccessor: () => ({ count: 0 }),
|
||||||
initialCellStateAccessor: () => ({ count: 0 }),
|
initialCellStateAccessor: () => ({ count: 0 }),
|
||||||
},
|
},
|
||||||
useRowState,
|
useRowState
|
||||||
useGlobalFilter
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -5,19 +5,18 @@ import { expandRows } from '../utils'
|
|||||||
import {
|
import {
|
||||||
useGetLatest,
|
useGetLatest,
|
||||||
actions,
|
actions,
|
||||||
functionalUpdate,
|
|
||||||
useMountedLayoutEffect,
|
useMountedLayoutEffect,
|
||||||
makePropGetter,
|
makePropGetter,
|
||||||
} from '../publicUtils'
|
} from '../publicUtils'
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
actions.toggleExpanded = 'toggleExpanded'
|
|
||||||
actions.toggleAllExpanded = 'toggleAllExpanded'
|
|
||||||
actions.setExpanded = 'setExpanded'
|
|
||||||
actions.resetExpanded = 'resetExpanded'
|
actions.resetExpanded = 'resetExpanded'
|
||||||
|
actions.toggleRowExpanded = 'toggleRowExpanded'
|
||||||
|
actions.toggleAllRowsExpanded = 'toggleAllRowsExpanded'
|
||||||
|
|
||||||
export const useExpanded = hooks => {
|
export const useExpanded = hooks => {
|
||||||
hooks.getExpandedToggleProps = [defaultGetExpandedToggleProps]
|
hooks.getToggleAllRowsExpandedProps = [defaultGetToggleAllRowsExpandedProps]
|
||||||
|
hooks.getToggleRowExpandedProps = [defaultGetToggleRowExpandedProps]
|
||||||
hooks.stateReducers.push(reducer)
|
hooks.stateReducers.push(reducer)
|
||||||
hooks.useInstance.push(useInstance)
|
hooks.useInstance.push(useInstance)
|
||||||
hooks.prepareRow.push(prepareRow)
|
hooks.prepareRow.push(prepareRow)
|
||||||
@ -25,17 +24,29 @@ export const useExpanded = hooks => {
|
|||||||
|
|
||||||
useExpanded.pluginName = 'useExpanded'
|
useExpanded.pluginName = 'useExpanded'
|
||||||
|
|
||||||
const defaultGetExpandedToggleProps = (props, { row }) => [
|
const defaultGetToggleAllRowsExpandedProps = (props, { instance }) => [
|
||||||
props,
|
props,
|
||||||
{
|
{
|
||||||
onClick: e => {
|
onClick: e => {
|
||||||
e.persist()
|
instance.toggleAllRowsExpanded()
|
||||||
row.toggleExpanded()
|
|
||||||
},
|
},
|
||||||
style: {
|
style: {
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
},
|
},
|
||||||
title: 'Toggle Expanded',
|
title: 'Toggle All Rows Expanded',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const defaultGetToggleRowExpandedProps = (props, { row }) => [
|
||||||
|
props,
|
||||||
|
{
|
||||||
|
onClick: () => {
|
||||||
|
row.toggleRowExpanded()
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
title: 'Toggle Row Expanded',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -55,14 +66,32 @@ function reducer(state, action, previousState, instance) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === actions.setExpanded) {
|
if (action.type === actions.toggleAllRowsExpanded) {
|
||||||
|
const { value } = action
|
||||||
|
const { isAllRowsExpanded, rowsById } = instance
|
||||||
|
|
||||||
|
const expandAll = typeof value !== 'undefined' ? value : !isAllRowsExpanded
|
||||||
|
|
||||||
|
if (expandAll) {
|
||||||
|
const expanded = {}
|
||||||
|
|
||||||
|
Object.keys(rowsById).forEach(rowId => {
|
||||||
|
expanded[rowId] = true
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
expanded,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
expanded: functionalUpdate(action.expanded, state.expanded),
|
expanded: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === actions.toggleExpanded) {
|
if (action.type === actions.toggleRowExpanded) {
|
||||||
const { id, value: setExpanded } = action
|
const { id, value: setExpanded } = action
|
||||||
const exists = state.expanded[id]
|
const exists = state.expanded[id]
|
||||||
|
|
||||||
@ -93,16 +122,28 @@ function useInstance(instance) {
|
|||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
rows,
|
rows,
|
||||||
|
rowsById,
|
||||||
manualExpandedKey = 'expanded',
|
manualExpandedKey = 'expanded',
|
||||||
paginateExpandedRows = true,
|
paginateExpandedRows = true,
|
||||||
expandSubRows = true,
|
expandSubRows = true,
|
||||||
autoResetExpanded = true,
|
autoResetExpanded = true,
|
||||||
|
getHooks,
|
||||||
state: { expanded },
|
state: { expanded },
|
||||||
dispatch,
|
dispatch,
|
||||||
} = instance
|
} = instance
|
||||||
|
|
||||||
const getAutoResetExpanded = useGetLatest(autoResetExpanded)
|
const getAutoResetExpanded = useGetLatest(autoResetExpanded)
|
||||||
|
|
||||||
|
let isAllRowsExpanded = Boolean(
|
||||||
|
Object.keys(rowsById).length && Object.keys(expanded).length
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isAllRowsExpanded) {
|
||||||
|
if (Object.keys(rowsById).some(id => !expanded[id])) {
|
||||||
|
isAllRowsExpanded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bypass any effects from firing when this changes
|
// Bypass any effects from firing when this changes
|
||||||
useMountedLayoutEffect(() => {
|
useMountedLayoutEffect(() => {
|
||||||
if (getAutoResetExpanded()) {
|
if (getAutoResetExpanded()) {
|
||||||
@ -110,13 +151,18 @@ function useInstance(instance) {
|
|||||||
}
|
}
|
||||||
}, [dispatch, data])
|
}, [dispatch, data])
|
||||||
|
|
||||||
const toggleExpanded = React.useCallback(
|
const toggleRowExpanded = React.useCallback(
|
||||||
(id, value) => {
|
(id, value) => {
|
||||||
dispatch({ type: actions.toggleExpanded, id, value })
|
dispatch({ type: actions.toggleRowExpanded, id, value })
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const toggleAllRowsExpanded = React.useCallback(
|
||||||
|
value => dispatch({ type: actions.toggleAllRowsExpanded, value }),
|
||||||
|
[dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const expandedRows = React.useMemo(() => {
|
const expandedRows = React.useMemo(() => {
|
||||||
if (paginateExpandedRows) {
|
if (paginateExpandedRows) {
|
||||||
return expandRows(rows, { manualExpandedKey, expanded, expandSubRows })
|
return expandRows(rows, { manualExpandedKey, expanded, expandSubRows })
|
||||||
@ -129,20 +175,30 @@ function useInstance(instance) {
|
|||||||
expanded,
|
expanded,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const getInstance = useGetLatest(instance)
|
||||||
|
|
||||||
|
const getToggleAllRowsExpandedProps = makePropGetter(
|
||||||
|
getHooks().getToggleAllRowsExpandedProps,
|
||||||
|
{ instance: getInstance() }
|
||||||
|
)
|
||||||
|
|
||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
preExpandedRows: rows,
|
preExpandedRows: rows,
|
||||||
expandedRows,
|
expandedRows,
|
||||||
rows: expandedRows,
|
rows: expandedRows,
|
||||||
toggleExpanded,
|
|
||||||
expandedDepth,
|
expandedDepth,
|
||||||
|
isAllRowsExpanded,
|
||||||
|
toggleRowExpanded,
|
||||||
|
toggleAllRowsExpanded,
|
||||||
|
getToggleAllRowsExpandedProps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareRow(row, { instance: { getHooks }, instance }) {
|
function prepareRow(row, { instance: { getHooks }, instance }) {
|
||||||
row.toggleExpanded = set => instance.toggleExpanded(row.id, set)
|
row.toggleRowExpanded = set => instance.toggleRowExpanded(row.id, set)
|
||||||
|
|
||||||
row.getExpandedToggleProps = makePropGetter(
|
row.getToggleRowExpandedProps = makePropGetter(
|
||||||
getHooks().getExpandedToggleProps,
|
getHooks().getToggleRowExpandedProps,
|
||||||
{
|
{
|
||||||
instance,
|
instance,
|
||||||
row,
|
row,
|
||||||
|
|||||||
@ -108,7 +108,9 @@ function reducer(state, action, previousState, instance) {
|
|||||||
filterTypes
|
filterTypes
|
||||||
)
|
)
|
||||||
|
|
||||||
if (shouldAutoRemoveFilter(filterMethod.autoRemove, filter.value, column)) {
|
if (
|
||||||
|
shouldAutoRemoveFilter(filterMethod.autoRemove, filter.value, column)
|
||||||
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -122,6 +124,7 @@ function useInstance(instance) {
|
|||||||
data,
|
data,
|
||||||
rows,
|
rows,
|
||||||
flatRows,
|
flatRows,
|
||||||
|
rowsById,
|
||||||
allColumns,
|
allColumns,
|
||||||
filterTypes: userFilterTypes,
|
filterTypes: userFilterTypes,
|
||||||
manualFilters,
|
manualFilters,
|
||||||
@ -175,12 +178,17 @@ function useInstance(instance) {
|
|||||||
column.filterValue = found && found.value
|
column.filterValue = found && found.value
|
||||||
})
|
})
|
||||||
|
|
||||||
const [filteredRows, filteredFlatRows] = React.useMemo(() => {
|
const [
|
||||||
|
filteredRows,
|
||||||
|
filteredFlatRows,
|
||||||
|
filteredRowsById,
|
||||||
|
] = React.useMemo(() => {
|
||||||
if (manualFilters || !filters.length) {
|
if (manualFilters || !filters.length) {
|
||||||
return [rows, flatRows]
|
return [rows, flatRows, rowsById]
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredFlatRows = []
|
const filteredFlatRows = []
|
||||||
|
const filteredRowsById = {}
|
||||||
|
|
||||||
// Filters top level and nested rows
|
// Filters top level and nested rows
|
||||||
const filterRows = (rows, depth = 0) => {
|
const filterRows = (rows, depth = 0) => {
|
||||||
@ -231,6 +239,7 @@ function useInstance(instance) {
|
|||||||
// would be required to do that recursion in some scenarios
|
// would be required to do that recursion in some scenarios
|
||||||
filteredRows = filteredRows.map(row => {
|
filteredRows = filteredRows.map(row => {
|
||||||
filteredFlatRows.push(row)
|
filteredFlatRows.push(row)
|
||||||
|
filteredRowsById[row.id] = row
|
||||||
if (!row.subRows) {
|
if (!row.subRows) {
|
||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
@ -246,8 +255,16 @@ function useInstance(instance) {
|
|||||||
return filteredRows
|
return filteredRows
|
||||||
}
|
}
|
||||||
|
|
||||||
return [filterRows(rows), filteredFlatRows]
|
return [filterRows(rows), filteredFlatRows, filteredRowsById]
|
||||||
}, [manualFilters, filters, rows, flatRows, allColumns, userFilterTypes])
|
}, [
|
||||||
|
manualFilters,
|
||||||
|
filters,
|
||||||
|
rows,
|
||||||
|
flatRows,
|
||||||
|
rowsById,
|
||||||
|
allColumns,
|
||||||
|
userFilterTypes,
|
||||||
|
])
|
||||||
|
|
||||||
React.useMemo(() => {
|
React.useMemo(() => {
|
||||||
// Now that each filtered column has it's partially filtered rows,
|
// Now that each filtered column has it's partially filtered rows,
|
||||||
@ -275,10 +292,13 @@ function useInstance(instance) {
|
|||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
preFilteredRows: rows,
|
preFilteredRows: rows,
|
||||||
preFilteredFlatRows: flatRows,
|
preFilteredFlatRows: flatRows,
|
||||||
|
preFilteredRowsById: rowsById,
|
||||||
filteredRows,
|
filteredRows,
|
||||||
filteredFlatRows,
|
filteredFlatRows,
|
||||||
|
filteredRowsById,
|
||||||
rows: filteredRows,
|
rows: filteredRows,
|
||||||
flatRows: filteredFlatRows,
|
flatRows: filteredFlatRows,
|
||||||
|
rowsById: filteredRowsById,
|
||||||
setFilter,
|
setFilter,
|
||||||
setAllFilters,
|
setAllFilters,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -61,6 +61,7 @@ function useInstance(instance) {
|
|||||||
data,
|
data,
|
||||||
rows,
|
rows,
|
||||||
flatRows,
|
flatRows,
|
||||||
|
rowsById,
|
||||||
allColumns,
|
allColumns,
|
||||||
filterTypes: userFilterTypes,
|
filterTypes: userFilterTypes,
|
||||||
globalFilter,
|
globalFilter,
|
||||||
@ -88,12 +89,17 @@ function useInstance(instance) {
|
|||||||
// cache for each row group (top-level rows, and each row's recursive subrows)
|
// 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?
|
// This would make multi-filtering a lot faster though. Too far?
|
||||||
|
|
||||||
const [globalFilteredRows, globalFilteredFlatRows] = React.useMemo(() => {
|
const [
|
||||||
|
globalFilteredRows,
|
||||||
|
globalFilteredFlatRows,
|
||||||
|
globalFilteredRowsById,
|
||||||
|
] = React.useMemo(() => {
|
||||||
if (manualGlobalFilter || typeof globalFilterValue === 'undefined') {
|
if (manualGlobalFilter || typeof globalFilterValue === 'undefined') {
|
||||||
return [rows, flatRows]
|
return [rows, flatRows, rowsById]
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredFlatRows = []
|
const filteredFlatRows = []
|
||||||
|
const filteredRowsById = {}
|
||||||
|
|
||||||
const filterMethod = getFilterMethod(
|
const filterMethod = getFilterMethod(
|
||||||
globalFilter,
|
globalFilter,
|
||||||
@ -114,6 +120,7 @@ function useInstance(instance) {
|
|||||||
globalFilterValue
|
globalFilterValue
|
||||||
).map(row => {
|
).map(row => {
|
||||||
filteredFlatRows.push(row)
|
filteredFlatRows.push(row)
|
||||||
|
filteredRowsById[row.id] = row
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...row,
|
...row,
|
||||||
@ -125,15 +132,16 @@ function useInstance(instance) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return [filterRows(rows), filteredFlatRows]
|
return [filterRows(rows), filteredFlatRows, filteredRowsById]
|
||||||
}, [
|
}, [
|
||||||
manualGlobalFilter,
|
manualGlobalFilter,
|
||||||
|
globalFilterValue,
|
||||||
globalFilter,
|
globalFilter,
|
||||||
userFilterTypes,
|
userFilterTypes,
|
||||||
rows,
|
rows,
|
||||||
flatRows,
|
flatRows,
|
||||||
|
rowsById,
|
||||||
allColumns,
|
allColumns,
|
||||||
globalFilterValue,
|
|
||||||
])
|
])
|
||||||
|
|
||||||
const getAutoResetGlobalFilter = useGetLatest(autoResetGlobalFilter)
|
const getAutoResetGlobalFilter = useGetLatest(autoResetGlobalFilter)
|
||||||
@ -147,10 +155,13 @@ function useInstance(instance) {
|
|||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
preGlobalFilteredRows: rows,
|
preGlobalFilteredRows: rows,
|
||||||
preGlobalFilteredFlatRows: flatRows,
|
preGlobalFilteredFlatRows: flatRows,
|
||||||
|
preGlobalFilteredRowsById: rowsById,
|
||||||
globalFilteredRows,
|
globalFilteredRows,
|
||||||
globalFilteredFlatRows,
|
globalFilteredFlatRows,
|
||||||
|
globalFilteredRowsById,
|
||||||
rows: globalFilteredRows,
|
rows: globalFilteredRows,
|
||||||
flatRows: globalFilteredFlatRows,
|
flatRows: globalFilteredFlatRows,
|
||||||
|
rowsById: globalFilteredRowsById,
|
||||||
setGlobalFilter,
|
setGlobalFilter,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,9 @@ import {
|
|||||||
useGetLatest,
|
useGetLatest,
|
||||||
} from '../publicUtils'
|
} from '../publicUtils'
|
||||||
|
|
||||||
|
const emptyArray = []
|
||||||
|
const emptyObject = {}
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
actions.resetGroupBy = 'resetGroupBy'
|
actions.resetGroupBy = 'resetGroupBy'
|
||||||
actions.toggleGroupBy = 'toggleGroupBy'
|
actions.toggleGroupBy = 'toggleGroupBy'
|
||||||
@ -119,6 +122,7 @@ function useInstance(instance) {
|
|||||||
data,
|
data,
|
||||||
rows,
|
rows,
|
||||||
flatRows,
|
flatRows,
|
||||||
|
rowsById,
|
||||||
allColumns,
|
allColumns,
|
||||||
flatHeaders,
|
flatHeaders,
|
||||||
groupByFn = defaultGroupByFn,
|
groupByFn = defaultGroupByFn,
|
||||||
@ -179,9 +183,25 @@ function useInstance(instance) {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [groupedRows, groupedFlatRows] = React.useMemo(() => {
|
const [
|
||||||
|
groupedRows,
|
||||||
|
groupedFlatRows,
|
||||||
|
groupedRowsById,
|
||||||
|
onlyGroupedFlatRows,
|
||||||
|
onlyGroupedRowsById,
|
||||||
|
nonGroupedFlatRows,
|
||||||
|
nonGroupedRowsById,
|
||||||
|
] = React.useMemo(() => {
|
||||||
if (manualGroupBy || !groupBy.length) {
|
if (manualGroupBy || !groupBy.length) {
|
||||||
return [rows, flatRows]
|
return [
|
||||||
|
rows,
|
||||||
|
flatRows,
|
||||||
|
rowsById,
|
||||||
|
emptyArray,
|
||||||
|
emptyObject,
|
||||||
|
flatRows,
|
||||||
|
rowsById,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the list of filtered columns exist
|
// Ensure that the list of filtered columns exist
|
||||||
@ -252,6 +272,11 @@ function useInstance(instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let groupedFlatRows = []
|
let groupedFlatRows = []
|
||||||
|
const groupedRowsById = {}
|
||||||
|
const onlyGroupedFlatRows = []
|
||||||
|
const onlyGroupedRowsById = {}
|
||||||
|
const nonGroupedFlatRows = []
|
||||||
|
const nonGroupedRowsById = {}
|
||||||
|
|
||||||
// Recursively group the data
|
// Recursively group the data
|
||||||
const groupUpRecursively = (rows, depth = 0, parentId) => {
|
const groupUpRecursively = (rows, depth = 0, parentId) => {
|
||||||
@ -293,7 +318,17 @@ function useInstance(instance) {
|
|||||||
index,
|
index,
|
||||||
}
|
}
|
||||||
|
|
||||||
groupedFlatRows.push(row, ...subRows)
|
subRows.forEach(subRow => {
|
||||||
|
groupedFlatRows.push(subRow)
|
||||||
|
groupedRowsById[subRow.id] = subRow
|
||||||
|
if (subRow.isGrouped) {
|
||||||
|
onlyGroupedFlatRows.push(subRow)
|
||||||
|
onlyGroupedRowsById[subRow.id] = subRow
|
||||||
|
} else {
|
||||||
|
nonGroupedFlatRows.push(subRow)
|
||||||
|
nonGroupedRowsById[subRow.id] = subRow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
@ -304,13 +339,34 @@ function useInstance(instance) {
|
|||||||
|
|
||||||
const groupedRows = groupUpRecursively(rows)
|
const groupedRows = groupUpRecursively(rows)
|
||||||
|
|
||||||
|
groupedRows.forEach(subRow => {
|
||||||
|
groupedFlatRows.push(subRow)
|
||||||
|
groupedRowsById[subRow.id] = subRow
|
||||||
|
if (subRow.isGrouped) {
|
||||||
|
onlyGroupedFlatRows.push(subRow)
|
||||||
|
onlyGroupedRowsById[subRow.id] = subRow
|
||||||
|
} else {
|
||||||
|
nonGroupedFlatRows.push(subRow)
|
||||||
|
nonGroupedRowsById[subRow.id] = subRow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Assign the new data
|
// Assign the new data
|
||||||
return [groupedRows, groupedFlatRows]
|
return [
|
||||||
|
groupedRows,
|
||||||
|
groupedFlatRows,
|
||||||
|
groupedRowsById,
|
||||||
|
onlyGroupedFlatRows,
|
||||||
|
onlyGroupedRowsById,
|
||||||
|
nonGroupedFlatRows,
|
||||||
|
nonGroupedRowsById,
|
||||||
|
]
|
||||||
}, [
|
}, [
|
||||||
manualGroupBy,
|
manualGroupBy,
|
||||||
groupBy,
|
groupBy,
|
||||||
rows,
|
rows,
|
||||||
flatRows,
|
flatRows,
|
||||||
|
rowsById,
|
||||||
allColumns,
|
allColumns,
|
||||||
userAggregations,
|
userAggregations,
|
||||||
groupByFn,
|
groupByFn,
|
||||||
@ -327,10 +383,17 @@ function useInstance(instance) {
|
|||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
preGroupedRows: rows,
|
preGroupedRows: rows,
|
||||||
preGroupedFlatRow: flatRows,
|
preGroupedFlatRow: flatRows,
|
||||||
|
preGroupedRowsById: rowsById,
|
||||||
groupedRows,
|
groupedRows,
|
||||||
groupedFlatRows,
|
groupedFlatRows,
|
||||||
|
groupedRowsById,
|
||||||
|
onlyGroupedFlatRows,
|
||||||
|
onlyGroupedRowsById,
|
||||||
|
nonGroupedFlatRows,
|
||||||
|
nonGroupedRowsById,
|
||||||
rows: groupedRows,
|
rows: groupedRows,
|
||||||
flatRows: groupedFlatRows,
|
flatRows: groupedFlatRows,
|
||||||
|
rowsById: groupedRowsById,
|
||||||
toggleGroupBy,
|
toggleGroupBy,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,7 +77,15 @@ function useInstance(instance) {
|
|||||||
pageCount: userPageCount,
|
pageCount: userPageCount,
|
||||||
paginateExpandedRows = true,
|
paginateExpandedRows = true,
|
||||||
expandSubRows = true,
|
expandSubRows = true,
|
||||||
state: { pageSize, pageIndex, expanded, globalFilter, filters, groupBy, sortBy },
|
state: {
|
||||||
|
pageSize,
|
||||||
|
pageIndex,
|
||||||
|
expanded,
|
||||||
|
globalFilter,
|
||||||
|
filters,
|
||||||
|
groupBy,
|
||||||
|
sortBy,
|
||||||
|
},
|
||||||
dispatch,
|
dispatch,
|
||||||
data,
|
data,
|
||||||
manualPagination,
|
manualPagination,
|
||||||
@ -103,10 +111,10 @@ function useInstance(instance) {
|
|||||||
}, [
|
}, [
|
||||||
dispatch,
|
dispatch,
|
||||||
manualPagination ? null : data,
|
manualPagination ? null : data,
|
||||||
manualPagination || manualGlobalFilter ? null : globalFilter,
|
manualGlobalFilter ? null : globalFilter,
|
||||||
manualPagination || manualFilters ? null : filters,
|
manualFilters ? null : filters,
|
||||||
manualPagination || manualGroupBy ? null : groupBy,
|
manualGroupBy ? null : groupBy,
|
||||||
manualPagination || manualSortBy ? null : sortBy,
|
manualSortBy ? null : sortBy,
|
||||||
])
|
])
|
||||||
|
|
||||||
const pageCount = manualPagination
|
const pageCount = manualPagination
|
||||||
|
|||||||
@ -86,7 +86,11 @@ function reducer(state, action, previousState, instance) {
|
|||||||
|
|
||||||
if (action.type === actions.toggleAllRowsSelected) {
|
if (action.type === actions.toggleAllRowsSelected) {
|
||||||
const { value: setSelected } = action
|
const { value: setSelected } = action
|
||||||
const { isAllRowsSelected, flatRowsById } = instance
|
const {
|
||||||
|
isAllRowsSelected,
|
||||||
|
rowsById,
|
||||||
|
nonGroupedRowsById = rowsById,
|
||||||
|
} = instance
|
||||||
|
|
||||||
const selectAll =
|
const selectAll =
|
||||||
typeof setSelected !== 'undefined' ? setSelected : !isAllRowsSelected
|
typeof setSelected !== 'undefined' ? setSelected : !isAllRowsSelected
|
||||||
@ -94,7 +98,7 @@ function reducer(state, action, previousState, instance) {
|
|||||||
if (selectAll) {
|
if (selectAll) {
|
||||||
const selectedRowIds = {}
|
const selectedRowIds = {}
|
||||||
|
|
||||||
Object.keys(flatRowsById).forEach(rowId => {
|
Object.keys(nonGroupedRowsById).forEach(rowId => {
|
||||||
selectedRowIds[rowId] = true
|
selectedRowIds[rowId] = true
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -112,12 +116,12 @@ function reducer(state, action, previousState, instance) {
|
|||||||
|
|
||||||
if (action.type === actions.toggleRowSelected) {
|
if (action.type === actions.toggleRowSelected) {
|
||||||
const { id, value: setSelected } = action
|
const { id, value: setSelected } = action
|
||||||
const { flatGroupedRowsById, selectSubRows = true } = instance
|
const { rowsById, selectSubRows = true } = instance
|
||||||
|
|
||||||
// Join the ids of deep rows
|
// Join the ids of deep rows
|
||||||
// to make a key, then manage all of the keys
|
// to make a key, then manage all of the keys
|
||||||
// in a flat object
|
// in a flat object
|
||||||
const row = flatGroupedRowsById[id]
|
const row = rowsById[id]
|
||||||
const isSelected = row.isSelected
|
const isSelected = row.isSelected
|
||||||
const shouldExist =
|
const shouldExist =
|
||||||
typeof setSelected !== 'undefined' ? setSelected : !isSelected
|
typeof setSelected !== 'undefined' ? setSelected : !isSelected
|
||||||
@ -129,7 +133,7 @@ function reducer(state, action, previousState, instance) {
|
|||||||
let newSelectedRowIds = { ...state.selectedRowIds }
|
let newSelectedRowIds = { ...state.selectedRowIds }
|
||||||
|
|
||||||
const handleRowById = id => {
|
const handleRowById = id => {
|
||||||
const row = flatGroupedRowsById[id]
|
const row = rowsById[id]
|
||||||
|
|
||||||
if (!row.isGrouped) {
|
if (!row.isGrouped) {
|
||||||
if (!isSelected && shouldExist) {
|
if (!isSelected && shouldExist) {
|
||||||
@ -159,7 +163,8 @@ function useInstance(instance) {
|
|||||||
rows,
|
rows,
|
||||||
getHooks,
|
getHooks,
|
||||||
plugins,
|
plugins,
|
||||||
flatRows,
|
rowsById,
|
||||||
|
nonGroupedRowsById = rowsById,
|
||||||
autoResetSelectedRows = true,
|
autoResetSelectedRows = true,
|
||||||
state: { selectedRowIds },
|
state: { selectedRowIds },
|
||||||
selectSubRows = true,
|
selectSubRows = true,
|
||||||
@ -173,20 +178,6 @@ function useInstance(instance) {
|
|||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
const [flatRowsById, flatGroupedRowsById] = React.useMemo(() => {
|
|
||||||
const all = {}
|
|
||||||
const grouped = {}
|
|
||||||
|
|
||||||
flatRows.forEach(row => {
|
|
||||||
if (!row.isGrouped) {
|
|
||||||
all[row.id] = row
|
|
||||||
}
|
|
||||||
grouped[row.id] = row
|
|
||||||
})
|
|
||||||
|
|
||||||
return [all, grouped]
|
|
||||||
}, [flatRows])
|
|
||||||
|
|
||||||
const selectedFlatRows = React.useMemo(() => {
|
const selectedFlatRows = React.useMemo(() => {
|
||||||
const selectedFlatRows = []
|
const selectedFlatRows = []
|
||||||
|
|
||||||
@ -206,11 +197,11 @@ function useInstance(instance) {
|
|||||||
}, [rows, selectSubRows, selectedRowIds])
|
}, [rows, selectSubRows, selectedRowIds])
|
||||||
|
|
||||||
let isAllRowsSelected = Boolean(
|
let isAllRowsSelected = Boolean(
|
||||||
Object.keys(flatRowsById).length && Object.keys(selectedRowIds).length
|
Object.keys(nonGroupedRowsById).length && Object.keys(selectedRowIds).length
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isAllRowsSelected) {
|
if (isAllRowsSelected) {
|
||||||
if (Object.keys(flatRowsById).some(id => !selectedRowIds[id])) {
|
if (Object.keys(nonGroupedRowsById).some(id => !selectedRowIds[id])) {
|
||||||
isAllRowsSelected = false
|
isAllRowsSelected = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,8 +220,7 @@ function useInstance(instance) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const toggleRowSelected = React.useCallback(
|
const toggleRowSelected = React.useCallback(
|
||||||
(id, value) =>
|
(id, value) => dispatch({ type: actions.toggleRowSelected, id, value }),
|
||||||
dispatch({ type: actions.toggleRowSelected, id, value }),
|
|
||||||
[dispatch]
|
[dispatch]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -242,13 +232,11 @@ function useInstance(instance) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
flatRowsById,
|
|
||||||
flatGroupedRowsById,
|
|
||||||
selectedFlatRows,
|
selectedFlatRows,
|
||||||
|
isAllRowsSelected,
|
||||||
toggleRowSelected,
|
toggleRowSelected,
|
||||||
toggleAllRowsSelected,
|
toggleAllRowsSelected,
|
||||||
getToggleAllRowsSelectedProps,
|
getToggleAllRowsSelectedProps,
|
||||||
isAllRowsSelected,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -180,6 +180,7 @@ function useInstance(instance) {
|
|||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
rows,
|
rows,
|
||||||
|
flatRows,
|
||||||
allColumns,
|
allColumns,
|
||||||
orderByFn = defaultOrderByFn,
|
orderByFn = defaultOrderByFn,
|
||||||
sortTypes: userSortTypes,
|
sortTypes: userSortTypes,
|
||||||
@ -194,7 +195,7 @@ function useInstance(instance) {
|
|||||||
autoResetSortBy = true,
|
autoResetSortBy = true,
|
||||||
} = instance
|
} = instance
|
||||||
|
|
||||||
ensurePluginOrder(plugins, ['useFilters'], 'useSortBy', [])
|
ensurePluginOrder(plugins, ['useFilters'], 'useSortBy', ['useExpanded'])
|
||||||
|
|
||||||
// Updates sorting based on a columnId, desc flag and multi flag
|
// Updates sorting based on a columnId, desc flag and multi flag
|
||||||
const toggleSortBy = React.useCallback(
|
const toggleSortBy = React.useCallback(
|
||||||
@ -249,11 +250,13 @@ function useInstance(instance) {
|
|||||||
column.isSortedDesc = column.isSorted ? columnSort.desc : undefined
|
column.isSortedDesc = column.isSorted ? columnSort.desc : undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
const sortedRows = React.useMemo(() => {
|
const [sortedRows, sortedFlatRows] = React.useMemo(() => {
|
||||||
if (manualSortBy || !sortBy.length) {
|
if (manualSortBy || !sortBy.length) {
|
||||||
return rows
|
return [rows, flatRows]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sortedFlatRows = []
|
||||||
|
|
||||||
// Filter out sortBys that correspond to non existing columns
|
// Filter out sortBys that correspond to non existing columns
|
||||||
const availableSortBy = sortBy.filter(sort =>
|
const availableSortBy = sortBy.filter(sort =>
|
||||||
allColumns.find(col => col.id === sort.id)
|
allColumns.find(col => col.id === sort.id)
|
||||||
@ -314,6 +317,7 @@ function useInstance(instance) {
|
|||||||
|
|
||||||
// If there are sub-rows, sort them
|
// If there are sub-rows, sort them
|
||||||
sortedData.forEach(row => {
|
sortedData.forEach(row => {
|
||||||
|
sortedFlatRows.push(row)
|
||||||
if (!row.subRows || row.subRows.length <= 1) {
|
if (!row.subRows || row.subRows.length <= 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -323,8 +327,16 @@ function useInstance(instance) {
|
|||||||
return sortedData
|
return sortedData
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortData(rows)
|
return [sortData(rows), sortedFlatRows]
|
||||||
}, [manualSortBy, sortBy, rows, allColumns, orderByFn, userSortTypes])
|
}, [
|
||||||
|
manualSortBy,
|
||||||
|
sortBy,
|
||||||
|
rows,
|
||||||
|
flatRows,
|
||||||
|
allColumns,
|
||||||
|
orderByFn,
|
||||||
|
userSortTypes,
|
||||||
|
])
|
||||||
|
|
||||||
const getAutoResetSortBy = useGetLatest(autoResetSortBy)
|
const getAutoResetSortBy = useGetLatest(autoResetSortBy)
|
||||||
|
|
||||||
@ -336,8 +348,11 @@ function useInstance(instance) {
|
|||||||
|
|
||||||
Object.assign(instance, {
|
Object.assign(instance, {
|
||||||
preSortedRows: rows,
|
preSortedRows: rows,
|
||||||
|
preSortedFlatRows: flatRows,
|
||||||
sortedRows,
|
sortedRows,
|
||||||
|
sortedFlatRows,
|
||||||
rows: sortedRows,
|
rows: sortedRows,
|
||||||
|
flatRows: sortedFlatRows,
|
||||||
toggleSortBy,
|
toggleSortBy,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
93
src/utils.js
93
src/utils.js
@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { defaultColumn, reduceHooks } from './publicUtils'
|
import { defaultColumn } from './publicUtils'
|
||||||
|
|
||||||
// Find the depth of the columns
|
// Find the depth of the columns
|
||||||
export function findMaxDepth(columns, depth = 0) {
|
export function findMaxDepth(columns, depth = 0) {
|
||||||
@ -88,97 +88,6 @@ export function decorateColumn(column, userDefaultColumn) {
|
|||||||
return column
|
return column
|
||||||
}
|
}
|
||||||
|
|
||||||
export function accessRowsForColumn({
|
|
||||||
data,
|
|
||||||
rows,
|
|
||||||
flatRows,
|
|
||||||
rowsById,
|
|
||||||
column,
|
|
||||||
getRowId,
|
|
||||||
getSubRows,
|
|
||||||
accessValueHooks,
|
|
||||||
getInstance,
|
|
||||||
}) {
|
|
||||||
// Access the row's data column-by-column
|
|
||||||
// We do it this way so we can incrementally add materialized
|
|
||||||
// columns after the first pass and avoid excessive looping
|
|
||||||
const accessRow = (originalRow, rowIndex, depth = 0, parent, parentRows) => {
|
|
||||||
// Keep the original reference around
|
|
||||||
const original = originalRow
|
|
||||||
|
|
||||||
const id = getRowId(originalRow, rowIndex, parent)
|
|
||||||
|
|
||||||
let row = rowsById[id]
|
|
||||||
|
|
||||||
// If the row hasn't been created, let's make it
|
|
||||||
if (!row) {
|
|
||||||
row = {
|
|
||||||
id,
|
|
||||||
original,
|
|
||||||
index: rowIndex,
|
|
||||||
depth,
|
|
||||||
cells: [{}], // This is a dummy cell
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override common array functions (and the dummy cell's getCellProps function)
|
|
||||||
// to show an error if it is accessed without calling prepareRow
|
|
||||||
row.cells.map = unpreparedAccessWarning
|
|
||||||
row.cells.filter = unpreparedAccessWarning
|
|
||||||
row.cells.forEach = unpreparedAccessWarning
|
|
||||||
row.cells[0].getCellProps = unpreparedAccessWarning
|
|
||||||
|
|
||||||
// Create the cells and values
|
|
||||||
row.values = {}
|
|
||||||
|
|
||||||
// Push this row into the parentRows array
|
|
||||||
parentRows.push(row)
|
|
||||||
// Keep track of every row in a flat array
|
|
||||||
flatRows.push(row)
|
|
||||||
// Also keep track of every row by its ID
|
|
||||||
rowsById[id] = row
|
|
||||||
|
|
||||||
// Get the original subrows
|
|
||||||
row.originalSubRows = getSubRows(originalRow, rowIndex)
|
|
||||||
|
|
||||||
// Then recursively access them
|
|
||||||
if (row.originalSubRows) {
|
|
||||||
const subRows = []
|
|
||||||
row.originalSubRows.forEach((d, i) =>
|
|
||||||
accessRow(d, i, depth + 1, row, subRows)
|
|
||||||
)
|
|
||||||
// Keep the new subRows array on the row
|
|
||||||
row.subRows = subRows
|
|
||||||
}
|
|
||||||
} else if (row.subRows) {
|
|
||||||
// If the row exists, then it's already been accessed
|
|
||||||
// Keep recursing, but don't worry about passing the
|
|
||||||
// accumlator array (those rows already exist)
|
|
||||||
row.originalSubRows.forEach((d, i) => accessRow(d, i, depth + 1, row))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the column has an accessor, use it to get a value
|
|
||||||
if (column.accessor) {
|
|
||||||
row.values[column.id] = column.accessor(originalRow, rowIndex, row)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow plugins to manipulate the column value
|
|
||||||
row.values[column.id] = reduceHooks(
|
|
||||||
accessValueHooks,
|
|
||||||
row.values[column.id],
|
|
||||||
{
|
|
||||||
row,
|
|
||||||
column,
|
|
||||||
instance: getInstance(),
|
|
||||||
},
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.forEach((originalRow, rowIndex) =>
|
|
||||||
accessRow(originalRow, rowIndex, 0, undefined, rows)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the header groups from the bottom up
|
// Build the header groups from the bottom up
|
||||||
export function makeHeaderGroups(allColumns, defaultColumn) {
|
export function makeHeaderGroups(allColumns, defaultColumn) {
|
||||||
const headerGroups = []
|
const headerGroups = []
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user