Compare commits

..
32 changed files with 5023 additions and 10161 deletions
+13 -20
View File
@@ -1,22 +1,15 @@
{ {
"parser": "babel-eslint", "parser": "babel-eslint",
"extends": ["react-app", "prettier"], "extends": ["standard", "standard-react"],
"plugins": [ "env": {
"react-hooks" "es6": true
], },
"env": { "plugins": ["react"],
"es6": true "parserOptions": {
}, "sourceType": "module"
"parserOptions": { },
"sourceType": "module" "rules": {
}, "space-before-function-paren": 0,
"rules": { "react/jsx-boolean-value": 0
"space-before-function-paren": 0, }
"react/jsx-boolean-value": 0
},
"settings": {
"react": {
"version": "latest"
}
}
} }
+4 -4
View File
@@ -1,7 +1,7 @@
node_modules node_modules/
lib lib/
dist dist/
es es/
docs/build docs/build
react-table.js react-table.js
react-table.min.js react-table.min.js
-5
View File
@@ -1,5 +0,0 @@
module.exports = {
hooks: {
'pre-commit': 'lint-staged',
},
}
-17
View File
@@ -1,17 +0,0 @@
const path = require('path');
module.exports = {
moduleDirectories: [
'node_modules',
/*
* make 'test/utils' available in tests, e.g.
*
* const {myModule} = require('utils/my-test-helper')
*/
__dirname,
],
rootDir: path.resolve(__dirname, '../..'),
roots: ['<rootDir>/src', __dirname],
};
-13
View File
@@ -1,13 +0,0 @@
const {rootDir} = require('./jest.common');
module.exports = {
rootDir,
displayName: 'lint',
runner: 'jest-runner-eslint',
testMatch: ['<rootDir>/src/**/*.js'],
testPathIgnorePatterns: ['node_modules', 'coverage', 'dist', '.test.js'],
};
-15
View File
@@ -1,15 +0,0 @@
const commonConfig = require('./jest.common');
module.exports = {
...commonConfig,
displayName: 'unit',
coverageDirectory: '../../coverage',
testMatch: ['<rootDir>/tests/**/*.js'],
transform: {
// '^.+\\.js$': '<rootDir>/node_modules/babel-jest',
},
};
View File
+2
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
BIN
View File
Binary file not shown.
-16
View File
@@ -1,16 +0,0 @@
const path = require('path');
const lintProject = require('./configs/tests/jest.lint');
const unitProject = require('./configs/tests/jest.unit');
module.exports = {
...require('./configs/tests/jest.common'),
projects: [lintProject, unitProject],
watchPlugins: [
'jest-watch-typeahead/filename',
'jest-watch-typeahead/testname',
'jest-watch-select-projects',
],
};
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
'*.js': ['prettier --write', 'git add'],
}
+4488 -6020
View File
File diff suppressed because it is too large Load Diff
+9 -23
View File
@@ -1,6 +1,6 @@
{ {
"name": "react-table", "name": "react-table",
"version": "7.0.0-alpha.7", "version": "7.0.0-alpha.2",
"description": "A fast, lightweight, opinionated table and datagrid built on React", "description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme", "homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -15,12 +15,11 @@
"datagrid" "datagrid"
], ],
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.es.js", "_module": "dist/index.es.js",
"jsnext:main": "dist/index.es.js", "_jsnext:main": "dist/index.es.js",
"scripts": { "scripts": {
"test": "is-ci 'test:ci' 'test:dev'", "test": "cross-env CI=1 react-scripts test --env=jsdom",
"test:dev": "jest --watch", "test:watch": "react-scripts test --env=jsdom",
"test:ci": "jest",
"build": "rollup -c", "build": "rollup -c",
"start": "rollup -c -w", "start": "rollup -c -w",
"prepare": "yarn build", "prepare": "yarn build",
@@ -47,30 +46,17 @@
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/runtime": "^7.2.0", "@babel/runtime": "^7.2.0",
"@svgr/rollup": "^4.1.0", "@svgr/rollup": "^4.1.0",
"@testing-library/react": "^8.0.4",
"babel-core": "7.0.0-bridge.0", "babel-core": "7.0.0-bridge.0",
"babel-eslint": "9.x", "babel-eslint": "^10.0.1",
"cross-env": "^5.1.4", "cross-env": "^5.1.4",
"eslint": "5.x", "eslint": "^5.10.0",
"eslint-config-prettier": "^4.3.0",
"eslint-config-react-app": "^4.0.1",
"eslint-config-standard": "^12.0.0", "eslint-config-standard": "^12.0.0",
"eslint-config-standard-react": "^7.0.2", "eslint-config-standard-react": "^7.0.2",
"eslint-plugin-flowtype": "2.x", "eslint-plugin-import": "^2.13.0",
"eslint-plugin-import": "2.x",
"eslint-plugin-jsx-a11y": "6.x",
"eslint-plugin-node": "^8.0.0", "eslint-plugin-node": "^8.0.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-promise": "^4.0.0", "eslint-plugin-promise": "^4.0.0",
"eslint-plugin-react": "7.x", "eslint-plugin-react": "^7.10.0",
"eslint-plugin-react-hooks": "1.5.0",
"eslint-plugin-standard": "^4.0.0", "eslint-plugin-standard": "^4.0.0",
"is-ci-cli": "^1.1.1",
"jest": "^24.8.0",
"jest-cli": "^24.8.0",
"jest-runner-eslint": "^0.7.4",
"jest-watch-select-projects": "^0.1.2",
"jest-watch-typeahead": "^0.3.1",
"rollup": "^0.68.0", "rollup": "^0.68.0",
"rollup-plugin-babel": "^4.1.0", "rollup-plugin-babel": "^4.1.0",
"rollup-plugin-commonjs": "^9.1.3", "rollup-plugin-commonjs": "^9.1.3",
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
trailingComma: 'es5',
tabWidth: 2,
semi: false,
singleQuote: true,
}
+21 -30
View File
@@ -6,36 +6,27 @@ import { uglify } from 'rollup-plugin-uglify'
import pkg from './package.json' import pkg from './package.json'
export default [ export default {
{ input: 'src/index.js',
input: 'src/index.js', output: [
output: { {
file: pkg.main, file: pkg.main,
format: 'cjs', format: 'cjs',
sourcemap: true sourcemap: true
}, }
plugins: [ // {
external(), // file: pkg.module,
babel({ // format: "es",
exclude: 'node_modules/**' // sourcemap: true
}), // }
resolve(), ],
commonjs(), plugins: [
uglify() external(),
] babel({
}, exclude: 'node_modules/**'
{ }),
input: 'src/index.js', resolve(),
external: Object.keys(pkg.peerDependencies), commonjs(),
output: { uglify()
file: pkg.module, ]
format: 'es', }
sourcemap: true
},
plugins: [
babel({
exclude: ['/**/node_modules/**']
})
]
}
]
+138 -138
View File
@@ -8,147 +8,16 @@ const propTypes = {
columns: PropTypes.arrayOf( columns: PropTypes.arrayOf(
PropTypes.shape({ PropTypes.shape({
Cell: PropTypes.any, Cell: PropTypes.any,
Header: PropTypes.any, Header: PropTypes.any
}) })
), )
}
// Find the depth of the columns
function findMaxDepth(columns, depth = 0) {
return columns.reduce((prev, curr) => {
if (curr.columns) {
return Math.max(prev, findMaxDepth(curr.columns, depth + 1))
}
return depth
}, 0)
}
function decorateColumn(column, parent) {
// First check for string accessor
let { id, accessor, Header } = column
if (typeof accessor === 'string') {
id = id || accessor
const accessorString = accessor
accessor = row => getBy(row, accessorString)
}
if (!id && typeof Header === 'string') {
id = Header
}
if (!id) {
// Accessor, but no column id? This is bad.
console.error(column)
throw new Error('A column id is required!')
}
column = {
Header: '',
Cell: cell => cell.value,
show: true,
...column,
id,
accessor,
parent,
}
return column
}
// Build the visible columns, headers and flat column list
function decorateColumnTree(columns, parent, depth = 0) {
return columns.map(column => {
column = decorateColumn(column, parent)
if (column.columns) {
column.columns = decorateColumnTree(column.columns, column, depth + 1)
}
return column
})
}
// Build the header groups from the bottom up
function makeHeaderGroups(columns, maxDepth) {
const headerGroups = []
const removeChildColumns = column => {
delete column.columns
if (column.parent) {
removeChildColumns(column.parent)
}
}
columns.forEach(removeChildColumns)
const buildGroup = (columns, depth = 0) => {
const headerGroup = {
headers: [],
}
const parentColumns = []
const hasParents = columns.some(col => col.parent)
columns.forEach(column => {
const isFirst = !parentColumns.length
let latestParentColumn = [...parentColumns].reverse()[0]
// If the column has a parent, add it if necessary
if (column.parent) {
if (isFirst || latestParentColumn.originalID !== column.parent.id) {
parentColumns.push({
...column.parent,
originalID: column.parent.id,
id: [column.parent.id, parentColumns.length].join('_'),
})
}
} else if (hasParents) {
// If other columns have parents, add a place holder if necessary
const placeholderColumn = decorateColumn({
originalID: [column.id, 'placeholder', maxDepth - depth].join('_'),
id: [
column.id,
'placeholder',
maxDepth - depth,
parentColumns.length,
].join('_'),
})
if (
isFirst ||
latestParentColumn.originalID !== placeholderColumn.originalID
) {
parentColumns.push(placeholderColumn)
}
}
// Establish the new columns[] relationship on the parent
if (column.parent || hasParents) {
latestParentColumn = [...parentColumns].reverse()[0]
latestParentColumn.columns = latestParentColumn.columns || []
if (!latestParentColumn.columns.includes(column)) {
latestParentColumn.columns.push(column)
}
}
headerGroup.headers.push(column)
})
headerGroups.push(headerGroup)
if (parentColumns.length) {
buildGroup(parentColumns)
}
}
buildGroup(columns)
return headerGroups.reverse()
} }
export const useColumns = props => { export const useColumns = props => {
const { const {
debug, debug,
columns: userColumns, columns: userColumns,
state: [{ groupBy }], state: [{ groupBy }]
} = props } = props
PropTypes.checkPropTypes(propTypes, props, 'property', 'useColumns') PropTypes.checkPropTypes(propTypes, props, 'property', 'useColumns')
@@ -164,7 +33,7 @@ export const useColumns = props => {
columns = [ columns = [
...groupBy.map(g => columns.find(col => col.id === g)), ...groupBy.map(g => columns.find(col => col.id === g)),
...columns.filter(col => !groupBy.includes(col.id)), ...columns.filter(col => !groupBy.includes(col.id))
] ]
// Get headerGroups // Get headerGroups
@@ -174,15 +43,69 @@ export const useColumns = props => {
return { return {
columns, columns,
headerGroups, headerGroups,
headers, headers
} }
}, [debug, groupBy, userColumns]) }, [groupBy, userColumns])
return { return {
...props, ...props,
columns, columns,
headerGroups, headerGroups,
headers, headers
}
// Find the depth of the columns
function findMaxDepth(columns, depth = 0) {
return columns.reduce((prev, curr) => {
if (curr.columns) {
return Math.max(prev, findMaxDepth(curr.columns, depth + 1))
}
return depth
}, 0)
}
function decorateColumn(column, parent) {
// First check for string accessor
let { id, accessor, Header } = column
if (typeof accessor === 'string') {
id = id || accessor
const accessorString = accessor
accessor = row => getBy(row, accessorString)
}
if (!id && typeof Header === 'string') {
id = Header
}
if (!id) {
// Accessor, but no column id? This is bad.
console.error(column)
throw new Error('A column id is required!')
}
column = {
Header: '',
Cell: cell => cell.value,
show: true,
...column,
id,
accessor,
parent
}
return column
}
// Build the visible columns, headers and flat column list
function decorateColumnTree(columns, parent, depth = 0) {
return columns.map(column => {
column = decorateColumn(column, parent)
if (column.columns) {
column.columns = decorateColumnTree(column.columns, column, depth + 1)
}
return column
})
} }
function flattenBy(columns, childKey) { function flattenBy(columns, childKey) {
@@ -202,4 +125,81 @@ export const useColumns = props => {
return flatColumns return flatColumns
} }
// Build the header groups from the bottom up
function makeHeaderGroups(columns, maxDepth) {
const headerGroups = []
const removeChildColumns = column => {
delete column.columns
if (column.parent) {
removeChildColumns(column.parent)
}
}
columns.forEach(removeChildColumns)
const buildGroup = (columns, depth = 0) => {
const headerGroup = {
headers: []
}
const parentColumns = []
const hasParents = columns.some(col => col.parent)
columns.forEach(column => {
const isFirst = !parentColumns.length
let latestParentColumn = [...parentColumns].reverse()[0]
// If the column has a parent, add it if necessary
if (column.parent) {
if (isFirst || latestParentColumn.originalID !== column.parent.id) {
parentColumns.push({
...column.parent,
originalID: column.parent.id,
id: [column.parent.id, parentColumns.length].join('_')
})
}
} else if (hasParents) {
// If other columns have parents, add a place holder if necessary
const placeholderColumn = decorateColumn({
originalID: [column.id, 'placeholder', maxDepth - depth].join('_'),
id: [
column.id,
'placeholder',
maxDepth - depth,
parentColumns.length
].join('_')
})
if (
isFirst ||
latestParentColumn.originalID !== placeholderColumn.originalID
) {
parentColumns.push(placeholderColumn)
}
}
// Establish the new columns[] relationship on the parent
if (column.parent || hasParents) {
latestParentColumn = [...parentColumns].reverse()[0]
latestParentColumn.columns = latestParentColumn.columns || []
if (!latestParentColumn.columns.includes(column)) {
latestParentColumn.columns.push(column)
}
}
headerGroup.headers.push(column)
})
headerGroups.push(headerGroup)
if (parentColumns.length) {
buildGroup(parentColumns)
}
}
buildGroup(columns)
return headerGroups.reverse()
}
} }
+8 -13
View File
@@ -9,12 +9,11 @@ defaultState.expanded = {}
addActions({ addActions({
toggleExpanded: '__toggleExpanded__', toggleExpanded: '__toggleExpanded__',
useExpanded: '__useExpanded__', useExpanded: '__useExpanded__'
}) })
const propTypes = { const propTypes = {
expandedKey: PropTypes.string, expandedKey: PropTypes.string
paginateSubRows: PropTypes.bool,
} }
export const useExpanded = props => { export const useExpanded = props => {
@@ -22,11 +21,11 @@ export const useExpanded = props => {
const { const {
debug, debug,
columns,
rows, rows,
expandedKey = 'expanded', expandedKey = 'expanded',
hooks, hooks,
state: [{ expanded }, setState], state: [{ expanded }, setState]
paginateSubRows = true,
} = props } = props
const toggleExpandedByPath = (path, set) => { const toggleExpandedByPath = (path, set) => {
@@ -36,7 +35,7 @@ export const useExpanded = props => {
set = getFirstDefined(set, !existing) set = getFirstDefined(set, !existing)
return { return {
...old, ...old,
expanded: setBy(expanded, path, set), expanded: setBy(expanded, path, set)
} }
}, actions.toggleExpanded) }, actions.toggleExpanded)
} }
@@ -63,21 +62,17 @@ export const useExpanded = props => {
row.isExpanded = row.isExpanded =
(row.original && row.original[expandedKey]) || getBy(expanded, path) (row.original && row.original[expandedKey]) || getBy(expanded, path)
if (paginateSubRows || (!paginateSubRows && row.depth === 0)) { expandedRows.push(row)
expandedRows.push(row)
}
if (row.isExpanded && row.subRows && row.subRows.length) { if (row.isExpanded && row.subRows && row.subRows.length) {
row.subRows.forEach((row, i) => handleRow(row, i, depth + 1, path)) row.subRows.forEach((row, i) => handleRow(row, i, depth + 1, path))
} }
return row
} }
rows.forEach((row, i) => handleRow(row, i)) rows.forEach((row, i) => handleRow(row, i))
return expandedRows return expandedRows
}, [debug, rows, expandedKey, expanded, paginateSubRows]) }, [rows, expanded, columns])
const expandedDepth = findExpandedDepth(expanded) const expandedDepth = findExpandedDepth(expanded)
@@ -85,7 +80,7 @@ export const useExpanded = props => {
...props, ...props,
toggleExpandedByPath, toggleExpandedByPath,
expandedDepth, expandedDepth,
rows: expandedRows, rows: expandedRows
} }
} }
+16 -16
View File
@@ -8,7 +8,7 @@ import { defaultState } from './useTableState'
defaultState.filters = {} defaultState.filters = {}
addActions({ addActions({
setFilter: '__setFilter__', setFilter: '__setFilter__',
setAllFilters: '__setAllFilters__', setAllFilters: '__setAllFilters__'
}) })
const propTypes = { const propTypes = {
@@ -18,12 +18,12 @@ const propTypes = {
filterFn: PropTypes.func, filterFn: PropTypes.func,
filterAll: PropTypes.bool, filterAll: PropTypes.bool,
canFilter: PropTypes.bool, canFilter: PropTypes.bool,
Filter: PropTypes.any, Filter: PropTypes.any
}) })
), ),
filterFn: PropTypes.func, filterFn: PropTypes.func,
manualFilters: PropTypes.bool, manualFilters: PropTypes.bool
} }
export const useFilters = props => { export const useFilters = props => {
@@ -37,17 +37,17 @@ export const useFilters = props => {
manualFilters, manualFilters,
disableFilters, disableFilters,
hooks, hooks,
state: [{ filters }, setState], state: [{ filters }, setState]
} = props } = props
columns.forEach(column => { columns.forEach(column => {
const { id, accessor, canFilter } = column const { id, accessor, canFilter } = column
column.canFilter = accessor column.canFilter = accessor
? getFirstDefined( ? getFirstDefined(
canFilter, canFilter,
disableFilters === true ? false : undefined, disableFilters === true ? false : undefined,
true true
) )
: false : false
// Was going to add this to the filter hook // Was going to add this to the filter hook
column.filterValue = filters[id] column.filterValue = filters[id]
@@ -60,8 +60,8 @@ export const useFilters = props => {
return { return {
...old, ...old,
filters: { filters: {
...rest, ...rest
}, }
} }
} }
@@ -69,8 +69,8 @@ export const useFilters = props => {
...old, ...old,
filters: { filters: {
...filters, ...filters,
[id]: val, [id]: val
}, }
} }
}, actions.setFilter) }, actions.setFilter)
} }
@@ -79,7 +79,7 @@ export const useFilters = props => {
return setState(old => { return setState(old => {
return { return {
...old, ...old,
filters, filters
} }
}, actions.setAllFilters) }, actions.setAllFilters)
} }
@@ -134,7 +134,7 @@ export const useFilters = props => {
} }
return { return {
...row, ...row,
subRows: filterRows(row.subRows), subRows: filterRows(row.subRows)
} }
}) })
@@ -150,12 +150,12 @@ export const useFilters = props => {
} }
return filterRows(rows) return filterRows(rows)
}, [manualFilters, filters, debug, rows, columns, filterFn]) }, [rows, filters, manualFilters])
return { return {
...props, ...props,
setFilter, setFilter,
setAllFilters, setAllFilters,
rows: filteredRows, rows: filteredRows
} }
} }
+18 -14
View File
@@ -5,7 +5,7 @@ import { getFirstDefined, sum } from '../utils'
export const actions = {} export const actions = {}
const propTypes = { const propTypes = {
defaultFlex: PropTypes.number, defaultFlex: PropTypes.number
} }
export const useFlexLayout = props => { export const useFlexLayout = props => {
@@ -18,12 +18,17 @@ export const useFlexLayout = props => {
getRowProps, getRowProps,
getHeaderRowProps, getHeaderRowProps,
getHeaderProps, getHeaderProps,
getCellProps, getCellProps
}, }
} = props } = props
columnsHooks.push((columns, api) => { columnsHooks.push((columns, api) => {
const visibleColumns = columns.filter(column => column.visible) const visibleColumns = columns.filter(column => {
column.visible =
typeof column.show === 'function' ? column.show(api) : !!column.show
return column.visible
})
const columnMeasurements = {} const columnMeasurements = {}
let sumWidth = 0 let sumWidth = 0
@@ -47,8 +52,8 @@ export const useFlexLayout = props => {
const rowStyles = { const rowStyles = {
style: { style: {
display: 'flex', display: 'flex',
minWidth: `${sumWidth}px`, minWidth: `${sumWidth}px`
}, }
} }
api.rowStyles = rowStyles api.rowStyles = rowStyles
@@ -59,8 +64,8 @@ export const useFlexLayout = props => {
getHeaderProps.push(column => ({ getHeaderProps.push(column => ({
style: { style: {
boxSizing: 'border-box', boxSizing: 'border-box',
...getStylesForColumn(column, columnMeasurements, defaultFlex, api), ...getStylesForColumn(column, columnMeasurements, defaultFlex, api)
}, }
// [refKey]: el => { // [refKey]: el => {
// renderedCellInfoRef.current[key] = { // renderedCellInfoRef.current[key] = {
// column, // column,
@@ -80,8 +85,8 @@ export const useFlexLayout = props => {
defaultFlex, defaultFlex,
undefined, undefined,
api api
), )
}, }
// [refKey]: el => { // [refKey]: el => {
// renderedCellInfoRef.current[columnPathStr] = { // renderedCellInfoRef.current[columnPathStr] = {
// column, // column,
@@ -110,7 +115,7 @@ function getStylesForColumn(column, columnMeasurements, defaultFlex, api) {
return { return {
flex: `${flex} 0 auto`, flex: `${flex} 0 auto`,
width: `${width}px`, width: `${width}px`,
maxWidth: `${maxWidth}px`, maxWidth: `${maxWidth}px`
} }
} }
@@ -122,7 +127,6 @@ function getSizesForColumn(
) { ) {
if (columns) { if (columns) {
columns = columns columns = columns
.filter(col => col.show || col.visible)
.map(column => .map(column =>
getSizesForColumn(column, columnMeasurements, defaultFlex, api) getSizesForColumn(column, columnMeasurements, defaultFlex, api)
) )
@@ -139,7 +143,7 @@ function getSizesForColumn(
return { return {
flex, flex,
width, width,
maxWidth, maxWidth
} }
} }
@@ -149,7 +153,7 @@ function getSizesForColumn(
width === 'auto' width === 'auto'
? columnMeasurements[id] || defaultFlex ? columnMeasurements[id] || defaultFlex
: getFirstDefined(width, minWidth, defaultFlex), : getFirstDefined(width, minWidth, defaultFlex),
maxWidth, maxWidth
} }
} }
+19 -27
View File
@@ -8,13 +8,13 @@ import {
mergeProps, mergeProps,
applyPropHooks, applyPropHooks,
defaultGroupByFn, defaultGroupByFn,
getFirstDefined, getFirstDefined
} from '../utils' } from '../utils'
defaultState.groupBy = [] defaultState.groupBy = []
addActions({ addActions({
toggleGroupBy: '__toggleGroupBy__', toggleGroupBy: '__toggleGroupBy__'
}) })
const propTypes = { const propTypes = {
@@ -23,12 +23,12 @@ const propTypes = {
PropTypes.shape({ PropTypes.shape({
aggregate: PropTypes.func, aggregate: PropTypes.func,
canGroupBy: PropTypes.bool, canGroupBy: PropTypes.bool,
Aggregated: PropTypes.any, Aggregated: PropTypes.any
}) })
), ),
groupByFn: PropTypes.func, groupByFn: PropTypes.func,
manualGrouping: PropTypes.bool, manualGrouping: PropTypes.bool,
aggregations: PropTypes.object, aggregations: PropTypes.object
} }
export const useGroupBy = props => { export const useGroupBy = props => {
@@ -43,7 +43,7 @@ export const useGroupBy = props => {
disableGrouping, disableGrouping,
aggregations: userAggregations = {}, aggregations: userAggregations = {},
hooks, hooks,
state: [{ groupBy }, setState], state: [{ groupBy }, setState]
} = props } = props
columns.forEach(column => { columns.forEach(column => {
@@ -52,10 +52,10 @@ export const useGroupBy = props => {
column.canGroupBy = accessor column.canGroupBy = accessor
? getFirstDefined( ? getFirstDefined(
canGroupBy, canGroupBy,
disableGrouping === true ? false : undefined, disableGrouping === true ? false : undefined,
true true
) )
: false : false
column.Aggregated = column.Aggregated || column.Cell column.Aggregated = column.Aggregated || column.Cell
@@ -68,12 +68,12 @@ export const useGroupBy = props => {
if (resolvedToggle) { if (resolvedToggle) {
return { return {
...old, ...old,
groupBy: [...groupBy, id], groupBy: [...groupBy, id]
} }
} }
return { return {
...old, ...old,
groupBy: groupBy.filter(d => d !== id), groupBy: groupBy.filter(d => d !== id)
} }
}, actions.toggleGroupBy) }, actions.toggleGroupBy)
} }
@@ -97,14 +97,14 @@ export const useGroupBy = props => {
{ {
onClick: canGroupBy onClick: canGroupBy
? e => { ? e => {
e.persist() e.persist()
column.toggleGroupBy() column.toggleGroupBy()
} }
: undefined, : undefined,
style: { style: {
cursor: canGroupBy ? 'pointer' : undefined, cursor: canGroupBy ? 'pointer' : undefined
}, },
title: 'Toggle GroupBy', title: 'Toggle GroupBy'
}, },
applyPropHooks(api.hooks.getGroupByToggleProps, column, api), applyPropHooks(api.hooks.getGroupByToggleProps, column, api),
props props
@@ -169,7 +169,7 @@ export const useGroupBy = props => {
values, values,
subRows, subRows,
depth, depth,
index, index
} }
return row return row
} }
@@ -180,18 +180,10 @@ export const useGroupBy = props => {
// Assign the new data // Assign the new data
return groupRecursively(rows, groupBy) return groupRecursively(rows, groupBy)
}, [ }, [rows, groupBy, columns, manualGroupBy])
manualGroupBy,
groupBy,
debug,
rows,
columns,
userAggregations,
groupByFn,
])
return { return {
...props, ...props,
rows: groupedRows, rows: groupedRows
} }
} }
+14 -23
View File
@@ -9,12 +9,12 @@ defaultState.pageSize = 10
defaultState.pageIndex = 0 defaultState.pageIndex = 0
addActions({ addActions({
pageChange: '__pageChange__', pageChange: '__pageChange__'
}) })
const propTypes = { const propTypes = {
// General // General
manualPagination: PropTypes.bool, manualPagination: PropTypes.bool
} }
export const usePagination = props => { export const usePagination = props => {
@@ -23,7 +23,6 @@ export const usePagination = props => {
const { const {
rows, rows,
manualPagination, manualPagination,
disablePageResetOnDataChange,
debug, debug,
state: [ state: [
{ {
@@ -32,34 +31,27 @@ export const usePagination = props => {
pageCount: userPageCount, pageCount: userPageCount,
filters, filters,
groupBy, groupBy,
sortBy, sortBy
}, },
setState, setState
], ]
} = props } = props
const pageOptions = useMemo(
() => [...new Array(userPageCount)].map((d, i) => i),
[userPageCount]
)
const rowDep = disablePageResetOnDataChange ? null : rows
useLayoutEffect(() => { useLayoutEffect(() => {
setState( setState(
old => ({ old => ({
...old, ...old,
pageIndex: 0, pageIndex: 0
}), }),
actions.pageChange actions.pageChange
) )
}, [setState, rowDep, filters, groupBy, sortBy]) }, [filters, groupBy, sortBy])
const { pages, pageCount } = useMemo(() => { const { pages, pageCount } = useMemo(() => {
if (manualPagination) { if (manualPagination) {
return { return {
pages: [rows], pages: [rows],
pageCount: userPageCount, pageCount: userPageCount
} }
} }
if (debug) console.info('getPages') if (debug) console.info('getPages')
@@ -80,10 +72,11 @@ export const usePagination = props => {
return { return {
pages, pages,
pageCount, pageCount,
pageOptions, pageOptions
} }
}, [manualPagination, debug, rows, pageOptions, userPageCount, pageSize]) }, [rows, pageSize, userPageCount])
const pageOptions = [...new Array(pageCount)].map((d, i) => i)
const page = manualPagination ? rows : pages[pageIndex] || [] const page = manualPagination ? rows : pages[pageIndex] || []
const canPreviousPage = pageIndex > 0 const canPreviousPage = pageIndex > 0
const canNextPage = pageIndex < pageCount - 1 const canNextPage = pageIndex < pageCount - 1
@@ -96,7 +89,7 @@ export const usePagination = props => {
} }
return { return {
...old, ...old,
pageIndex, pageIndex
} }
}, actions.pageChange) }, actions.pageChange)
} }
@@ -116,7 +109,7 @@ export const usePagination = props => {
return { return {
...old, ...old,
pageIndex, pageIndex,
pageSize, pageSize
} }
}, actions.setPageSize) }, actions.setPageSize)
} }
@@ -131,8 +124,6 @@ export const usePagination = props => {
gotoPage, gotoPage,
previousPage, previousPage,
nextPage, nextPage,
setPageSize, setPageSize
pageIndex,
pageSize,
} }
} }
+4 -4
View File
@@ -2,7 +2,7 @@ import { useMemo } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const propTypes = { const propTypes = {
subRowsKey: PropTypes.string, subRowsKey: PropTypes.string
} }
export const useRows = props => { export const useRows = props => {
@@ -29,7 +29,7 @@ export const useRows = props => {
path: [i], // used to create a key for each row even if not nested path: [i], // used to create a key for each row even if not nested
subRows, subRows,
depth, depth,
cells: [{}], // This is a dummy cell cells: [{}] // This is a dummy cell
} }
// Override common array functions (and the dummy cell's getCellProps function) // Override common array functions (and the dummy cell's getCellProps function)
@@ -57,10 +57,10 @@ export const useRows = props => {
// Use the resolved data // Use the resolved data
return data.map((d, i) => accessRow(d, i)) return data.map((d, i) => accessRow(d, i))
}, [debug, data, subRowsKey, columns]) }, [data, columns])
return { return {
...props, ...props,
rows: accessedRows, rows: accessedRows
} }
} }
+16 -7
View File
@@ -1,23 +1,32 @@
export const useSimpleLayout = props => { export const useSimpleLayout = props => {
const { const {
hooks: { columns: columnsHooks, getHeaderProps, getCellProps }, hooks: {
columns: columnsHooks,
getHeaderProps,
getCellProps
}
} = props } = props
columnsHooks.push(columns => { columnsHooks.push((columns, api) => {
columns.forEach(column => {
column.visible =
typeof column.show === 'function' ? column.show(api) : !!column.show
})
getHeaderProps.push(column => ({ getHeaderProps.push(column => ({
style: { style: {
boxSizing: 'border-box', boxSizing: 'border-box',
width: column.width !== undefined ? `${column.width}px` : 'auto', width: column.width !== undefined ? `${column.width}px` : 'auto'
}, }
})) }))
getCellProps.push(cell => { getCellProps.push(cell => {
return { return {
style: { style: {
boxSizing: 'border-box', boxSizing: 'border-box',
width: width: cell.column.width !== undefined ? `${cell.column.width}px` : 'auto'
cell.column.width !== undefined ? `${cell.column.width}px` : 'auto', }
},
} }
}) })
+28 -33
View File
@@ -8,13 +8,13 @@ import {
applyPropHooks, applyPropHooks,
getFirstDefined, getFirstDefined,
defaultOrderByFn, defaultOrderByFn,
defaultSortByFn, defaultSortByFn
} from '../utils' } from '../utils'
defaultState.sortBy = [] defaultState.sortBy = []
addActions({ addActions({
sortByChange: '__sortByChange__', sortByChange: '__sortByChange__'
}) })
const propTypes = { const propTypes = {
@@ -22,15 +22,14 @@ const propTypes = {
columns: PropTypes.arrayOf( columns: PropTypes.arrayOf(
PropTypes.shape({ PropTypes.shape({
sortByFn: PropTypes.func, sortByFn: PropTypes.func,
defaultSortDesc: PropTypes.bool, efaultSortDesc: PropTypes.bool
}) })
), ),
sortByFn: PropTypes.func, sortByFn: PropTypes.func,
manualSorting: PropTypes.bool, manualSorting: PropTypes.bool,
disableSorting: PropTypes.bool, disableSorting: PropTypes.bool,
defaultSortDesc: PropTypes.bool, defaultSortDesc: PropTypes.bool,
disableMultiSort: PropTypes.bool, disableMultiSort: PropTypes.bool
disableSortRemove: PropTypes.bool,
} }
export const useSortBy = props => { export const useSortBy = props => {
@@ -45,19 +44,18 @@ export const useSortBy = props => {
manualSorting, manualSorting,
disableSorting, disableSorting,
defaultSortDesc, defaultSortDesc,
disableSortRemove,
hooks, hooks,
state: [{ sortBy }, setState], state: [{ sortBy }, setState]
} = props } = props
columns.forEach(column => { columns.forEach(column => {
const { accessor, canSortBy } = column const { accessor, canSortBy } = column
column.canSortBy = accessor column.canSortBy = accessor
? getFirstDefined( ? getFirstDefined(
canSortBy, canSortBy,
disableSorting === true ? false : undefined, disableSorting === true ? false : undefined,
true true
) )
: false : false
}) })
@@ -84,11 +82,8 @@ export const useSortBy = props => {
if (!multi) { if (!multi) {
if (sortBy.length <= 1 && existingSortBy) { if (sortBy.length <= 1 && existingSortBy) {
if ( if (existingSortBy.desc) {
(existingSortBy.desc && !resolvedDefaultSortDesc) || action = 'remove'
(!existingSortBy.desc && resolvedDefaultSortDesc)
) {
action = disableSortRemove ? 'toggle' : 'remove'
} else { } else {
action = 'toggle' action = 'toggle'
} }
@@ -111,23 +106,23 @@ export const useSortBy = props => {
newSortBy = [ newSortBy = [
{ {
id: columnID, id: columnID,
desc: hasDescDefined ? desc : resolvedDefaultSortDesc, desc: hasDescDefined ? desc : resolvedDefaultSortDesc
}, }
] ]
} else if (action === 'add') { } else if (action === 'add') {
newSortBy = [ newSortBy = [
...sortBy, ...sortBy,
{ {
id: columnID, id: columnID,
desc: hasDescDefined ? desc : resolvedDefaultSortDesc, desc: hasDescDefined ? desc : resolvedDefaultSortDesc
}, }
] ]
} else if (action === 'set') { } else if (action === 'set') {
newSortBy = sortBy.map(d => { newSortBy = sortBy.map(d => {
if (d.id === columnID) { if (d.id === columnID) {
return { return {
...d, ...d,
desc, desc
} }
} }
return d return d
@@ -137,7 +132,7 @@ export const useSortBy = props => {
if (d.id === columnID) { if (d.id === columnID) {
return { return {
...d, ...d,
desc: !existingSortBy.desc, desc: !existingSortBy.desc
} }
} }
return d return d
@@ -148,7 +143,7 @@ export const useSortBy = props => {
return { return {
...old, ...old,
sortBy: newSortBy, sortBy: newSortBy
} }
}, actions.sortByChange) }, actions.sortByChange)
} }
@@ -173,17 +168,17 @@ export const useSortBy = props => {
{ {
onClick: canSortBy onClick: canSortBy
? e => { ? e => {
e.persist() e.persist()
column.toggleSortBy( column.toggleSortBy(
undefined, undefined,
!api.disableMultiSort && e.shiftKey !api.disableMultiSort && e.shiftKey
) )
} }
: undefined, : undefined,
style: { style: {
cursor: canSortBy ? 'pointer' : undefined, cursor: canSortBy ? 'pointer' : undefined
}, },
title: 'Toggle SortBy', title: 'Toggle SortBy'
}, },
applyPropHooks(api.hooks.getSortByToggleProps, column, api), applyPropHooks(api.hooks.getSortByToggleProps, column, api),
props props
@@ -252,10 +247,10 @@ export const useSortBy = props => {
} }
return sortData(rows) return sortData(rows)
}, [manualSorting, sortBy, debug, columns, rows, orderByFn, sortByFn]) }, [rows, columns, sortBy, manualSorting])
return { return {
...props, ...props,
rows: sortedRows, rows: sortedRows
} }
} }
+11 -17
View File
@@ -10,7 +10,7 @@ const renderErr =
const propTypes = { const propTypes = {
// General // General
data: PropTypes.array.isRequired, data: PropTypes.array.isRequired,
debug: PropTypes.bool, debug: PropTypes.bool
} }
export const useTable = (props, ...plugins) => { export const useTable = (props, ...plugins) => {
@@ -41,7 +41,7 @@ export const useTable = (props, ...plugins) => {
getRowProps: [], getRowProps: [],
getHeaderRowProps: [], getHeaderRowProps: [],
getHeaderProps: [], getHeaderProps: [],
getCellProps: [], getCellProps: []
} }
// The initial api // The initial api
@@ -49,7 +49,7 @@ export const useTable = (props, ...plugins) => {
...props, ...props,
data, data,
state, state,
hooks, hooks
} }
if (debug) console.time('hooks') if (debug) console.time('hooks')
@@ -62,11 +62,6 @@ export const useTable = (props, ...plugins) => {
applyHooks(api.hooks.beforeRender, undefined, api) applyHooks(api.hooks.beforeRender, undefined, api)
if (debug) console.timeEnd('hooks.beforeRender') if (debug) console.timeEnd('hooks.beforeRender')
api.columns.forEach(column => {
column.visible =
typeof column.show === 'function' ? column.show(api) : !!column.show
})
if (debug) console.time('hooks.columns') if (debug) console.time('hooks.columns')
api.columns = applyHooks(api.hooks.columns, api.columns, api) api.columns = applyHooks(api.hooks.columns, api.columns, api)
if (debug) console.timeEnd('hooks.columns') if (debug) console.timeEnd('hooks.columns')
@@ -83,7 +78,7 @@ export const useTable = (props, ...plugins) => {
return flexRender(column[type], { return flexRender(column[type], {
...api, ...api,
...column, ...column,
...userProps, ...userProps
}) })
} }
@@ -91,8 +86,7 @@ export const useTable = (props, ...plugins) => {
column.getHeaderProps = props => column.getHeaderProps = props =>
mergeProps( mergeProps(
{ {
key: ['header', column.id].join('_'), key: ['header', column.id].join('_')
colSpan: column.columns ? column.columns.length : 1,
}, },
applyPropHooks(api.hooks.getHeaderProps, column, api), applyPropHooks(api.hooks.getHeaderProps, column, api),
props props
@@ -125,7 +119,7 @@ export const useTable = (props, ...plugins) => {
headerGroup.getRowProps = (props = {}) => headerGroup.getRowProps = (props = {}) =>
mergeProps( mergeProps(
{ {
key: [`header${i}`].join('_'), key: [`header${i}`].join('_')
}, },
applyPropHooks(api.hooks.getHeaderRowProps, headerGroup, api), applyPropHooks(api.hooks.getHeaderRowProps, headerGroup, api),
props props
@@ -150,7 +144,7 @@ export const useTable = (props, ...plugins) => {
row.getRowProps = props => row.getRowProps = props =>
mergeProps( mergeProps(
{ key: ['row', ...path].join('_') }, { key: ['row', ...path].join('_') },
applyPropHooks(api.hooks.getRowProps, row, api), applyHooks(api.hooks.getRowProps, row, api),
props props
) )
@@ -164,14 +158,14 @@ export const useTable = (props, ...plugins) => {
const cell = { const cell = {
column, column,
row, row,
value: row.values[column.id], value: row.values[column.id]
} }
cell.getCellProps = props => { cell.getCellProps = props => {
const columnPathStr = [path, column.id].join('_') const columnPathStr = [path, column.id].join('_')
return mergeProps( return mergeProps(
{ {
key: ['cell', columnPathStr].join('_'), key: ['cell', columnPathStr].join('_')
}, },
applyPropHooks(api.hooks.getCellProps, cell, api), applyPropHooks(api.hooks.getCellProps, cell, api),
props props
@@ -187,7 +181,7 @@ export const useTable = (props, ...plugins) => {
return flexRender(column[type], { return flexRender(column[type], {
...api, ...api,
...cell, ...cell,
...userProps, ...userProps
}) })
} }
@@ -199,7 +193,7 @@ export const useTable = (props, ...plugins) => {
mergeProps(applyPropHooks(api.hooks.getTableProps, api), userProps) mergeProps(applyPropHooks(api.hooks.getTableProps, api), userProps)
api.getRowProps = userProps => api.getRowProps = userProps =>
mergeProps(applyPropHooks(api.hooks.getRowProps, undefined, api), userProps) mergeProps(applyPropHooks(api.hooks.getRowProps, api), userProps)
return api return api
} }
+16 -25
View File
@@ -1,4 +1,4 @@
import React from 'react' import { useState, useMemo } from 'react'
export const defaultState = {} export const defaultState = {}
@@ -6,38 +6,29 @@ const defaultReducer = (old, newState) => newState
export const useTableState = ( export const useTableState = (
initialState = {}, initialState = {},
overrides, overrides = {},
{ reducer = defaultReducer, useState: userUseState = React.useState } = {} { reducer = defaultReducer, useState: userUseState = useState } = {}
) => { ) => {
let [state, setState] = userUseState({ let [state, setState] = userUseState({
...defaultState, ...defaultState,
...initialState, ...initialState
}) })
const overriddenState = React.useMemo(() => { const overriddenState = useMemo(() => {
const newState = { const newState = {
...state, ...state
}
if (overrides) {
Object.keys(overrides).forEach(key => {
newState[key] = overrides[key]
})
} }
Object.keys(overrides).forEach(key => {
newState[key] = overrides[key]
})
return newState return newState
// eslint-disable-next-line react-hooks/exhaustive-deps }, [state, ...Object.values(overrides)])
}, [overrides, state])
const reducedSetState = React.useCallback( const reducedSetState = (updater, type) =>
(updater, type) => setState(old => {
setState(old => { const newState = updater(old)
const newState = updater(old) return reducer(old, newState, type)
return reducer(old, newState, type) })
}),
[reducer, setState]
)
return React.useMemo(() => [overriddenState, reducedSetState], [ return [overriddenState, reducedSetState]
overriddenState,
reducedSetState,
])
} }
+1 -1
View File
@@ -46,6 +46,6 @@ export const useTokenPagination = () => {
nextPage, nextPage,
canPreviousPage, canPreviousPage,
canNextPage, canNextPage,
resetPagination, resetPagination
} }
} }
+9 -9
View File
@@ -70,8 +70,8 @@ export function defaultGroupByFn(rows, grouper) {
export function defaultFilterFn(row, id, value, column) { export function defaultFilterFn(row, id, value, column) {
return row.values[id] !== undefined return row.values[id] !== undefined
? String(row.values[id]) ? String(row.values[id])
.toLowerCase() .toLowerCase()
.includes(String(value).toLowerCase()) .includes(String(value).toLowerCase())
: true : true
} }
@@ -83,7 +83,7 @@ export function setBy(obj = {}, path, value) {
depth === path.length - 1 ? value : recurse(target, depth + 1) depth === path.length - 1 ? value : recurse(target, depth + 1)
return { return {
...obj, ...obj,
[key]: subValue, [key]: subValue
} }
} }
@@ -95,11 +95,11 @@ export function getElementDimensions(element) {
const style = window.getComputedStyle(element) const style = window.getComputedStyle(element)
const margins = { const margins = {
left: parseInt(style.marginLeft), left: parseInt(style.marginLeft),
right: parseInt(style.marginRight), right: parseInt(style.marginRight)
} }
const padding = { const padding = {
left: parseInt(style.paddingLeft), left: parseInt(style.paddingLeft),
right: parseInt(style.paddingRight), right: parseInt(style.paddingRight)
} }
return { return {
left: Math.ceil(rect.left), left: Math.ceil(rect.left),
@@ -111,7 +111,7 @@ export function getElementDimensions(element) {
marginRight: margins.right, marginRight: margins.right,
paddingLeft: padding.left, paddingLeft: padding.left,
paddingRight: padding.right, paddingRight: padding.right,
scrollWidth: element.scrollWidth, scrollWidth: element.scrollWidth
} }
} }
@@ -134,9 +134,9 @@ export const mergeProps = (...groups) => {
...rest, ...rest,
style: { style: {
...(props.style || {}), ...(props.style || {}),
...style, ...style
}, },
className: [props.className, className].filter(Boolean).join(' '), className: [props.className, className].filter(Boolean).join(' ')
} }
}) })
return props return props
@@ -152,7 +152,7 @@ export const warnUnknownProps = props => {
if (Object.keys(props).length) { if (Object.keys(props).length) {
throw new Error( throw new Error(
`Unknown options passed to useReactTable: `Unknown options passed to useReactTable:
${JSON.stringify(props, null, 2)}` ${JSON.stringify(props, null, 2)}`
) )
} }
View File
+187 -3662
View File
File diff suppressed because it is too large Load Diff