Compare commits

...
12 changed files with 1218 additions and 981 deletions
+9
View File
@@ -1,3 +1,12 @@
## 6.4.0
##### New Features
- `PadRowComponent` - the content rendered inside of a padding row. Defaults to a react component that renders ` `
## 6.3.0
##### New Features
- `defaultSortDesc` - allows you to set the default sorting direction for all columns to descending.
- `column.defaultSortDesc` - allows you to set the default sorting direction for a specific column. Falls back to the global `defaultSortDesc` when not set at all.
## 6.0.0 ## 6.0.0
##### New Features ##### New Features
+9 -2
View File
@@ -169,6 +169,7 @@ These are all of the available props (and their default values) for the main `<R
sortable: true, sortable: true,
resizable: true, resizable: true,
filterable: false, filterable: false,
defaultSortDesc: false,
defaultSorted: [], defaultSorted: [],
defaultFiltered: [], defaultFiltered: [],
defaultResized: [], defaultResized: [],
@@ -194,6 +195,7 @@ These are all of the available props (and their default values) for the main `<R
// returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker // returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker
return 0 return 0
}, },
PadRowComponent: () => <span>&nbsp;</span>, // the content rendered inside of a padding row
// Controlled State Overrides (see Fully Controlled Component section) // Controlled State Overrides (see Fully Controlled Component section)
page: undefined, page: undefined,
@@ -286,7 +288,8 @@ These are all of the available props (and their default values) for the main `<R
footerStyle: {}, footerStyle: {},
getFooterProps: () => ({}), getFooterProps: () => ({}),
filterMethod: undefined, filterMethod: undefined,
sortMethod: undefined sortMethod: undefined,
defaultSortDesc: undefined,
}, },
// Global Expander Column Defaults // Global Expander Column Defaults
@@ -804,7 +807,11 @@ Accessing internal state and wrapping with more UI:
The possibilities are endless! The possibilities are endless!
## Sorting ## Sorting
Sorting comes built in with React-Table. Click column header to sort by its column. Click it again to reverse the sort. Sorting comes built in with React-Table.
- Click a column header to sort by its accessor.
- Click it again to reverse the sort.
- Set `defaultSortDesc` property to `true` to make the first sort direction default to descending.
- Override a specific column's default sort direction by using the same `defaultSortDesc` property on a column, set to `true`
## Multi-Sort ## Multi-Sort
When clicking on a column header, hold shift to multi-sort! You can toggle `ascending` `descending` and `none` for multi-sort columns. Clicking on a header without holding shift will clear the multi-sort and replace it with the single sort of that column. It's quite handy! When clicking on a column header, hold shift to multi-sort! You can toggle `ascending` `descending` and `none` for multi-sort columns. Clicking on a header without holding shift will clear the multi-sort and replace it with the single sort of that column. It's quite handy!
+1 -1
View File
@@ -71,7 +71,7 @@ class Story extends React.PureComponent {
} }
const CodeHighlight = require('./components/codeHighlight').default const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Simple') const source = require('!raw!./FixedHeader')
export default () => ( export default () => (
<div> <div>
+30 -23
View File
@@ -6,7 +6,7 @@ import namor from 'namor'
import ReactTable from '../../../lib/index' import ReactTable from '../../../lib/index'
class Story extends React.PureComponent { class Story extends React.PureComponent {
render () { render() {
const data = _.map(_.range(5553), d => { const data = _.map(_.range(5553), d => {
return { return {
firstName: namor.generate({ words: 1, numbers: 0 }), firstName: namor.generate({ words: 1, numbers: 0 }),
@@ -22,35 +22,43 @@ class Story extends React.PureComponent {
} }
}) })
const columns = [{ const columns = [
Header: 'Name', {
columns: [{ Header: 'Name',
Header: 'First Name', columns: [
accessor: 'firstName' {
}, { Header: 'First Name',
Header: 'Last Name', accessor: 'firstName'
id: 'lastName', },
accessor: d => d.lastName {
}] Header: 'Last Name',
}, { id: 'lastName',
Header: 'Info', accessor: d => d.lastName
columns: [{ }
Header: 'Age', ]
accessor: 'age' },
}] {
}] Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age'
}
]
}
]
return ( return (
<div> <div>
<div className='table-wrap'> <div className="table-wrap">
<ReactTable <ReactTable
className='-striped -highlight' className="-striped -highlight"
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
/> />
</div> </div>
<div style={{textAlign: 'center'}}> <div style={{ textAlign: 'center' }}>
<br /> <br />
<em>Tip: Hold shift when sorting to multi-sort!</em> <em>Tip: Hold shift when sorting to multi-sort!</em>
</div> </div>
@@ -62,9 +70,8 @@ class Story extends React.PureComponent {
const CodeHighlight = require('./components/codeHighlight').default const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Simple') const source = require('!raw!./Simple')
export default () => ( export default () =>
<div> <div>
<Story /> <Story />
<CodeHighlight>{() => source}</CodeHighlight> <CodeHighlight>{() => source}</CodeHighlight>
</div> </div>
)
+11 -9
View File
@@ -4557,14 +4557,16 @@ react-json-tree@^0.10.9:
prop-types "^15.5.8" prop-types "^15.5.8"
react-base16-styling "^0.5.1" react-base16-styling "^0.5.1"
react-router-dom@next: react-router-dom@^4.1.1:
version "4.0.0-beta.8" version "4.1.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.0.0-beta.8.tgz#907a5a0a36e9190652c80f2feead0eadbbba262e" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025"
dependencies: dependencies:
history "^4.5.1" history "^4.5.1"
react-router "^4.0.0-beta.8" loose-envify "^1.3.1"
prop-types "^15.5.4"
react-router "^4.1.1"
react-router@^4.0.0-beta.8: react-router@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95" resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95"
dependencies: dependencies:
@@ -4621,9 +4623,9 @@ react-scripts@0.9.5:
optionalDependencies: optionalDependencies:
fsevents "1.0.17" fsevents "1.0.17"
react-story@^0.0.6: react-story@^0.0.10:
version "0.0.6" version "0.0.10"
resolved "https://registry.yarnpkg.com/react-story/-/react-story-0.0.6.tgz#ec3e6b42e5edab8a74dd581c12bd321ec304eaba" resolved "https://registry.yarnpkg.com/react-story/-/react-story-0.0.10.tgz#4c07d122962900162f0871666780da34402a2573"
dependencies: dependencies:
classnames "^2.2.5" classnames "^2.2.5"
glamor "^2.20.25" glamor "^2.20.25"
@@ -4631,7 +4633,7 @@ react-story@^0.0.6:
javascript-detect-element-resize "^0.5.3" javascript-detect-element-resize "^0.5.3"
raf "^3.3.2" raf "^3.3.2"
react-fastclick "^3.0.1" react-fastclick "^3.0.1"
react-router-dom next react-router-dom "^4.1.1"
react@^15.5.4: react@^15.5.4:
version "15.5.4" version "15.5.4"
+3 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "react-table", "name": "react-table",
"version": "6.2.0", "version": "6.4.0",
"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",
@@ -34,8 +34,8 @@
"build": "npm-run-all build:*", "build": "npm-run-all build:*",
"prepublish": "npm run build && npm run umd", "prepublish": "npm run build && npm run umd",
"postpublish": "git push --tags", "postpublish": "git push --tags",
"docs": "cd docs && yarn && yarn start", "docs": "yarn watch & cd docs && yarn && yarn start",
"docs:build": "cd docs && yarn && yarn run build" "docs:build": "yarn build && cd docs && yarn && yarn run build"
}, },
"dependencies": { "dependencies": {
"classnames": "^2.2.5", "classnames": "^2.2.5",
+32 -34
View File
@@ -24,18 +24,21 @@ export default {
sortable: true, sortable: true,
resizable: true, resizable: true,
filterable: false, filterable: false,
defaultSortDesc: false,
defaultSorted: [], defaultSorted: [],
defaultFiltered: [], defaultFiltered: [],
defaultResized: [], defaultResized: [],
defaultExpanded: {}, defaultExpanded: {},
defaultFilterMethod: (filter, row, column) => { defaultFilterMethod: (filter, row, column) => {
const id = filter.pivotId || filter.id const id = filter.pivotId || filter.id
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true return row[id] !== undefined
? String(row[id]).startsWith(filter.value)
: true
}, },
defaultSortMethod: (a, b) => { defaultSortMethod: (a, b) => {
// force null and undefined to the bottom // force null and undefined to the bottom
a = (a === null || a === undefined) ? '' : a a = a === null || a === undefined ? '' : a
b = (b === null || b === undefined) ? '' : b b = b === null || b === undefined ? '' : b
// force any string values to lowercase // force any string values to lowercase
a = typeof a === 'string' ? a.toLowerCase() : a a = typeof a === 'string' ? a.toLowerCase() : a
b = typeof b === 'string' ? b.toLowerCase() : b b = typeof b === 'string' ? b.toLowerCase() : b
@@ -142,7 +145,7 @@ export default {
footerStyle: {}, footerStyle: {},
getFooterProps: emptyObj, getFooterProps: emptyObj,
filterMethod: undefined, filterMethod: undefined,
sortMethod: undefined sortMethod: undefined,
}, },
// Global Expander Column Defaults // Global Expander Column Defaults
@@ -150,7 +153,7 @@ export default {
sortable: false, sortable: false,
resizable: false, resizable: false,
filterable: false, filterable: false,
width: 35 width: 35,
}, },
pivotDefaults: { pivotDefaults: {
@@ -172,7 +175,7 @@ export default {
TbodyComponent: _.makeTemplateComponent('rt-tbody'), TbodyComponent: _.makeTemplateComponent('rt-tbody'),
TrGroupComponent: _.makeTemplateComponent('rt-tr-group'), TrGroupComponent: _.makeTemplateComponent('rt-tr-group'),
TrComponent: _.makeTemplateComponent('rt-tr'), TrComponent: _.makeTemplateComponent('rt-tr'),
ThComponent: ({toggleSort, className, children, ...rest}) => { ThComponent: ({ toggleSort, className, children, ...rest }) => {
return ( return (
<div <div
className={classnames(className, 'rt-th')} className={classnames(className, 'rt-th')}
@@ -187,51 +190,46 @@ export default {
}, },
TdComponent: _.makeTemplateComponent('rt-td'), TdComponent: _.makeTemplateComponent('rt-td'),
TfootComponent: _.makeTemplateComponent('rt-tfoot'), TfootComponent: _.makeTemplateComponent('rt-tfoot'),
FilterComponent: ({filter, onChange}) => ( FilterComponent: ({ filter, onChange }) =>
<input type='text' <input
type='text'
style={{ style={{
width: '100%' width: '100%',
}} }}
value={filter ? filter.value : ''} value={filter ? filter.value : ''}
onChange={(event) => onChange(event.target.value)} onChange={event => onChange(event.target.value)}
/> />,
), ExpanderComponent: ({ isExpanded }) =>
ExpanderComponent: ({isExpanded}) => (
<div className={classnames('rt-expander', isExpanded && '-open')}> <div className={classnames('rt-expander', isExpanded && '-open')}>
&bull; &bull;
</div> </div>,
), PivotValueComponent: ({ subRows, value }) =>
PivotValueComponent: ({subRows, value}) => ( <span>{value} {subRows && `(${subRows.length})`}</span>,
<span>{value} {subRows && `(${subRows.length})`}</span> AggregatedComponent: ({ subRows, column }) => {
),
AggregatedComponent: ({subRows, column}) => {
const previewValues = subRows const previewValues = subRows
.filter(d => typeof d[column.id] !== 'undefined') .filter(d => typeof d[column.id] !== 'undefined')
.map((row, i) => ( .map((row, i) =>
<span key={i}>{row[column.id]}{i < subRows.length - 1 ? ', ' : ''}</span> <span key={i}>
)) {row[column.id]}{i < subRows.length - 1 ? ', ' : ''}
return ( </span>
<span>{previewValues}</span> )
) return <span>{previewValues}</span>
}, },
PivotComponent: undefined, // this is a computed default generated using PivotComponent: undefined, // this is a computed default generated using
// the ExpanderComponent and PivotValueComponent at run-time in methods.js // the ExpanderComponent and PivotValueComponent at run-time in methods.js
PaginationComponent: Pagination, PaginationComponent: Pagination,
PreviousComponent: undefined, PreviousComponent: undefined,
NextComponent: undefined, NextComponent: undefined,
LoadingComponent: ({className, loading, loadingText, ...rest}) => ( LoadingComponent: ({ className, loading, loadingText, ...rest }) =>
<div className={classnames( <div
'-loading', className={classnames('-loading', { '-active': loading }, className)}
{'-active': loading},
className
)}
{...rest} {...rest}
> >
<div className='-loading-inner'> <div className='-loading-inner'>
{loadingText} {loadingText}
</div> </div>
</div> </div>,
),
NoDataComponent: _.makeTemplateComponent('rt-noData'), NoDataComponent: _.makeTemplateComponent('rt-noData'),
ResizerComponent: _.makeTemplateComponent('rt-resizer') ResizerComponent: _.makeTemplateComponent('rt-resizer'),
PadRowComponent: () => <span>&nbsp;</span>,
} }
+305 -166
View File
@@ -11,7 +11,7 @@ export const ReactTableDefaults = defaultProps
export default class ReactTable extends Methods(Lifecycle(Component)) { export default class ReactTable extends Methods(Lifecycle(Component)) {
static defaultProps = defaultProps static defaultProps = defaultProps
constructor (props) { constructor(props) {
super() super()
this.getResolvedState = this.getResolvedState.bind(this) this.getResolvedState = this.getResolvedState.bind(this)
@@ -43,7 +43,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
} }
render () { render() {
const resolvedState = this.getResolvedState() const resolvedState = this.getResolvedState()
const { const {
children, children,
@@ -118,6 +118,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
PivotComponent, PivotComponent,
AggregatedComponent, AggregatedComponent,
FilterComponent, FilterComponent,
PadRowComponent,
// Data model // Data model
resolvedData, resolvedData,
allVisibleColumns, allVisibleColumns,
@@ -148,23 +149,28 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const newPath = path.concat([i]) const newPath = path.concat([i])
if (rowWithViewIndex[subRowsKey] && _.get(expanded, newPath)) { if (rowWithViewIndex[subRowsKey] && _.get(expanded, newPath)) {
[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index) ;[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(
rowWithViewIndex[subRowsKey],
newPath,
index
)
} }
return rowWithViewIndex return rowWithViewIndex
}), }),
index index
] ]
} }
;[pageRows] = recurseRowsViewIndex(pageRows)
[pageRows] = recurseRowsViewIndex(pageRows)
const canPrevious = page > 0 const canPrevious = page > 0
const canNext = page + 1 < pages const canNext = page + 1 < pages
const rowMinWidth = _.sum(allVisibleColumns.map(d => { const rowMinWidth = _.sum(
const resizedColumn = resized.find(x => x.id === d.id) || {} allVisibleColumns.map(d => {
return _.getFirstDefined(resizedColumn.value, d.width, d.minWidth) const resizedColumn = resized.find(x => x.id === d.id) || {}
})) return _.getFirstDefined(resizedColumn.value, d.width, d.minWidth)
})
)
let rowIndex = -1 let rowIndex = -1
@@ -184,8 +190,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
// Visual Components // Visual Components
const makeHeaderGroups = () => { const makeHeaderGroups = () => {
const theadGroupProps = _.splitProps(getTheadGroupProps(finalState, undefined, undefined, this)) const theadGroupProps = _.splitProps(
const theadGroupTrProps = _.splitProps(getTheadGroupTrProps(finalState, undefined, undefined, this)) getTheadGroupProps(finalState, undefined, undefined, this)
)
const theadGroupTrProps = _.splitProps(
getTheadGroupTrProps(finalState, undefined, undefined, this)
)
return ( return (
<TheadComponent <TheadComponent
className={classnames('-headerGroups', theadGroupProps.className)} className={classnames('-headerGroups', theadGroupProps.className)}
@@ -207,13 +217,30 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeHeaderGroup = (column, i) => { const makeHeaderGroup = (column, i) => {
const resizedValue = col => (resized.find(x => x.id === col.id) || {}).value const resizedValue = col =>
const flex = _.sum(column.columns.map(col => col.width || resizedValue(col) ? 0 : col.minWidth)) (resized.find(x => x.id === col.id) || {}).value
const width = _.sum(column.columns.map(col => _.getFirstDefined(resizedValue(col), col.width, col.minWidth))) const flex = _.sum(
const maxWidth = _.sum(column.columns.map(col => _.getFirstDefined(resizedValue(col), col.width, col.maxWidth))) column.columns.map(
col => (col.width || resizedValue(col) ? 0 : col.minWidth)
)
)
const width = _.sum(
column.columns.map(col =>
_.getFirstDefined(resizedValue(col), col.width, col.minWidth)
)
)
const maxWidth = _.sum(
column.columns.map(col =>
_.getFirstDefined(resizedValue(col), col.width, col.maxWidth)
)
)
const theadGroupThProps = _.splitProps(getTheadGroupThProps(finalState, undefined, column, this)) const theadGroupThProps = _.splitProps(
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) getTheadGroupThProps(finalState, undefined, column, this)
)
const columnHeaderProps = _.splitProps(
column.getHeaderProps(finalState, undefined, column, this)
)
const classes = [ const classes = [
column.headerClassName, column.headerClassName,
@@ -241,9 +268,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return ( return (
<ThComponent <ThComponent
key={i + '-' + column.id} key={i + '-' + column.id}
className={classnames( className={classnames(classes)}
classes
)}
style={{ style={{
...styles, ...styles,
...flexStyles ...flexStyles
@@ -259,8 +284,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeHeaders = () => { const makeHeaders = () => {
const theadProps = _.splitProps(getTheadProps(finalState, undefined, undefined, this)) const theadProps = _.splitProps(
const theadTrProps = _.splitProps(getTheadTrProps(finalState, undefined, undefined, this)) getTheadProps(finalState, undefined, undefined, this)
)
const theadTrProps = _.splitProps(
getTheadTrProps(finalState, undefined, undefined, this)
)
return ( return (
<TheadComponent <TheadComponent
className={classnames('-header', theadProps.className)} className={classnames('-header', theadProps.className)}
@@ -284,11 +313,25 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeHeader = (column, i) => { const makeHeader = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const sort = sorted.find(d => d.id === column.id) const sort = sorted.find(d => d.id === column.id)
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function'
const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth) ? column.show()
const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth) : column.show
const theadThProps = _.splitProps(getTheadThProps(finalState, undefined, column, this)) const width = _.getFirstDefined(
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) resizedCol.value,
column.width,
column.minWidth
)
const maxWidth = _.getFirstDefined(
resizedCol.value,
column.width,
column.maxWidth
)
const theadThProps = _.splitProps(
getTheadThProps(finalState, undefined, column, this)
)
const columnHeaderProps = _.splitProps(
column.getHeaderProps(finalState, undefined, column, this)
)
const classes = [ const classes = [
column.headerClassName, column.headerClassName,
@@ -308,14 +351,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const isResizable = _.getFirstDefined(column.resizable, resizable, false) const isResizable = _.getFirstDefined(column.resizable, resizable, false)
const resizer = isResizable ? ( const resizer = isResizable
<ResizerComponent ? <ResizerComponent
onMouseDown={e => this.resizeColumnStart(column, e, false)} onMouseDown={e => this.resizeColumnStart(column, e, false)}
onTouchStart={e => this.resizeColumnStart(column, e, true)} onTouchStart={e => this.resizeColumnStart(column, e, true)}
{...resizerProps}
{...resizerProps} />
/> : null
) : null
const isSortable = _.getFirstDefined(column.sortable, sortable, false) const isSortable = _.getFirstDefined(column.sortable, sortable, false)
@@ -328,7 +370,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '', sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '',
isSortable && '-cursor-pointer', isSortable && '-cursor-pointer',
!show && '-hidden', !show && '-hidden',
pivotBy && pivotBy.slice(0, -1).includes(column.id) && 'rt-header-pivot' pivotBy &&
pivotBy.slice(0, -1).includes(column.id) &&
'rt-header-pivot'
)} )}
style={{ style={{
...styles, ...styles,
@@ -336,12 +380,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
width: `${width}px`, width: `${width}px`,
maxWidth: `${maxWidth}px` maxWidth: `${maxWidth}px`
}} }}
toggleSort={(e) => { toggleSort={e => {
isSortable && this.sortColumn(column, e.shiftKey) isSortable && this.sortColumn(column, e.shiftKey)
}} }}
{...rest} {...rest}
> >
<div className='rt-resizable-header-content'> <div className="rt-resizable-header-content">
{_.normalizeComponent(column.Header, { {_.normalizeComponent(column.Header, {
data: sortedData, data: sortedData,
column: column column: column
@@ -353,8 +397,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeFilters = () => { const makeFilters = () => {
const theadFilterProps = _.splitProps(getTheadFilterProps(finalState, undefined, undefined, this)) const theadFilterProps = _.splitProps(
const theadFilterTrProps = _.splitProps(getTheadFilterTrProps(finalState, undefined, undefined, this)) getTheadFilterProps(finalState, undefined, undefined, this)
)
const theadFilterTrProps = _.splitProps(
getTheadFilterTrProps(finalState, undefined, undefined, this)
)
return ( return (
<TheadComponent <TheadComponent
className={classnames('-filters', theadFilterProps.className)} className={classnames('-filters', theadFilterProps.className)}
@@ -377,10 +425,22 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeFilter = (column, i) => { const makeFilter = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth) const width = _.getFirstDefined(
const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth) resizedCol.value,
const theadFilterThProps = _.splitProps(getTheadFilterThProps(finalState, undefined, column, this)) column.width,
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) column.minWidth
)
const maxWidth = _.getFirstDefined(
resizedCol.value,
column.width,
column.maxWidth
)
const theadFilterThProps = _.splitProps(
getTheadFilterThProps(finalState, undefined, column, this)
)
const columnHeaderProps = _.splitProps(
column.getHeaderProps(finalState, undefined, column, this)
)
const classes = [ const classes = [
column.headerClassName, column.headerClassName,
@@ -403,14 +463,16 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const ResolvedFilterComponent = column.Filter || FilterComponent const ResolvedFilterComponent = column.Filter || FilterComponent
const isFilterable = _.getFirstDefined(column.filterable, filterable, false) const isFilterable = _.getFirstDefined(
column.filterable,
filterable,
false
)
return ( return (
<ThComponent <ThComponent
key={i + '-' + column.id} key={i + '-' + column.id}
className={classnames( className={classnames(classes)}
classes
)}
style={{ style={{
...styles, ...styles,
flex: `${width} 0 auto`, flex: `${width} 0 auto`,
@@ -419,16 +481,17 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}} }}
{...rest} {...rest}
> >
{isFilterable ? ( {isFilterable
_.normalizeComponent(ResolvedFilterComponent, ? _.normalizeComponent(
{ ResolvedFilterComponent,
column, {
filter, column,
onChange: (value) => (this.filterColumn(column, value)) filter,
}, onChange: value => this.filterColumn(column, value)
defaultProps.column.Filter },
) defaultProps.column.Filter
) : null} )
: null}
</ThComponent> </ThComponent>
) )
} }
@@ -447,12 +510,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const isExpanded = _.get(expanded, rowInfo.nestingPath) const isExpanded = _.get(expanded, rowInfo.nestingPath)
const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this) const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this)
const trProps = _.splitProps(getTrProps(finalState, rowInfo, undefined, this)) const trProps = _.splitProps(
getTrProps(finalState, rowInfo, undefined, this)
)
return ( return (
<TrGroupComponent <TrGroupComponent key={rowInfo.nestingPath.join('_')} {...trGroupProps}>
key={rowInfo.nestingPath.join('_')}
{...trGroupProps}
>
<TrComponent <TrComponent
className={classnames( className={classnames(
trProps.className, trProps.className,
@@ -463,11 +525,25 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
> >
{allVisibleColumns.map((column, i2) => { {allVisibleColumns.map((column, i2) => {
const resizedCol = resized.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function'
const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth) ? column.show()
const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth) : column.show
const tdProps = _.splitProps(getTdProps(finalState, rowInfo, column, this)) const width = _.getFirstDefined(
const columnProps = _.splitProps(column.getProps(finalState, rowInfo, column, this)) resizedCol.value,
column.width,
column.minWidth
)
const maxWidth = _.getFirstDefined(
resizedCol.value,
column.width,
column.maxWidth
)
const tdProps = _.splitProps(
getTdProps(finalState, rowInfo, column, this)
)
const columnProps = _.splitProps(
column.getProps(finalState, rowInfo, column, this)
)
const classes = [ const classes = [
tdProps.className, tdProps.className,
@@ -484,7 +560,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const cellInfo = { const cellInfo = {
...rowInfo, ...rowInfo,
isExpanded, isExpanded,
column: {...column}, column: { ...column },
value: rowInfo.row[column.id], value: rowInfo.row[column.id],
pivoted: column.pivoted, pivoted: column.pivoted,
expander: column.expander, expander: column.expander,
@@ -504,7 +580,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
let isBranch let isBranch
let isPreview let isPreview
const onExpanderClick = (e) => { const onExpanderClick = e => {
let newExpanded = _.clone(expanded) let newExpanded = _.clone(expanded)
if (isExpanded) { if (isExpanded) {
newExpanded = _.set(newExpanded, cellInfo.nestingPath, false) newExpanded = _.set(newExpanded, cellInfo.nestingPath, false)
@@ -512,29 +588,41 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
newExpanded = _.set(newExpanded, cellInfo.nestingPath, {}) newExpanded = _.set(newExpanded, cellInfo.nestingPath, {})
} }
return this.setStateWithData({ return this.setStateWithData(
expanded: newExpanded {
}, () => { expanded: newExpanded
onExpandedChange && onExpandedChange(newExpanded, cellInfo.nestingPath, e) },
}) () => {
onExpandedChange &&
onExpandedChange(newExpanded, cellInfo.nestingPath, e)
}
)
} }
// Default to a standard cell // Default to a standard cell
let resolvedCell = _.normalizeComponent(column.Cell, cellInfo, value) let resolvedCell = _.normalizeComponent(
column.Cell,
cellInfo,
value
)
// Resolve Renderers // Resolve Renderers
const ResolvedAggregatedComponent = column.Aggregated || (!column.aggregate ? AggregatedComponent : column.Cell) const ResolvedAggregatedComponent =
const ResolvedExpanderComponent = column.Expander || ExpanderComponent column.Aggregated ||
const ResolvedPivotValueComponent = column.PivotValue || PivotValueComponent (!column.aggregate ? AggregatedComponent : column.Cell)
const DefaultResolvedPivotComponent = PivotComponent || ( const ResolvedExpanderComponent =
props => ( column.Expander || ExpanderComponent
<div> const ResolvedPivotValueComponent =
<ResolvedExpanderComponent {...props} /> column.PivotValue || PivotValueComponent
<ResolvedPivotValueComponent {...props} /> const DefaultResolvedPivotComponent =
</div> PivotComponent ||
) (props =>
) <div>
const ResolvedPivotComponent = column.Pivot || DefaultResolvedPivotComponent <ResolvedExpanderComponent {...props} />
<ResolvedPivotValueComponent {...props} />
</div>)
const ResolvedPivotComponent =
column.Pivot || DefaultResolvedPivotComponent
// Is this cell expandable? // Is this cell expandable?
if (cellInfo.pivoted || cellInfo.expander) { if (cellInfo.pivoted || cellInfo.expander) {
@@ -556,30 +644,47 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
if (cellInfo.pivoted) { if (cellInfo.pivoted) {
// Is this column a branch? // Is this column a branch?
isBranch = rowInfo.row[pivotIDKey] === column.id && isBranch =
cellInfo.subRows rowInfo.row[pivotIDKey] === column.id && cellInfo.subRows
// Should this column be blank? // Should this column be blank?
isPreview = pivotBy.indexOf(column.id) > pivotBy.indexOf(rowInfo.row[pivotIDKey]) && isPreview =
cellInfo.subRows pivotBy.indexOf(column.id) >
pivotBy.indexOf(rowInfo.row[pivotIDKey]) && cellInfo.subRows
// Pivot Cell Render Override // Pivot Cell Render Override
if (isBranch) { if (isBranch) {
// isPivot // isPivot
resolvedCell = _.normalizeComponent(ResolvedPivotComponent, { resolvedCell = _.normalizeComponent(
...cellInfo, ResolvedPivotComponent,
value: row[pivotValKey] {
}, row[pivotValKey]) ...cellInfo,
value: row[pivotValKey]
},
row[pivotValKey]
)
} else if (isPreview) { } else if (isPreview) {
// Show the pivot preview // Show the pivot preview
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value) resolvedCell = _.normalizeComponent(
ResolvedAggregatedComponent,
cellInfo,
value
)
} else { } else {
resolvedCell = null resolvedCell = null
} }
} else if (cellInfo.aggregated) { } else if (cellInfo.aggregated) {
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value) resolvedCell = _.normalizeComponent(
ResolvedAggregatedComponent,
cellInfo,
value
)
} }
if (cellInfo.expander) { if (cellInfo.expander) {
resolvedCell = _.normalizeComponent(ResolvedExpanderComponent, cellInfo, row[pivotValKey]) resolvedCell = _.normalizeComponent(
ResolvedExpanderComponent,
cellInfo,
row[pivotValKey]
)
if (pivotBy) { if (pivotBy) {
if (cellInfo.groupedByPivot) { if (cellInfo.groupedByPivot) {
resolvedCell = null resolvedCell = null
@@ -614,24 +719,31 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
) )
})} })}
</TrComponent> </TrComponent>
{( {rowInfo.subRows &&
rowInfo.subRows &&
isExpanded && isExpanded &&
rowInfo.subRows.map((d, i) => makePageRow(d, i, rowInfo.nestingPath)) rowInfo.subRows.map((d, i) =>
)} makePageRow(d, i, rowInfo.nestingPath)
{SubComponent && !rowInfo.subRows && isExpanded && SubComponent(rowInfo)} )}
{SubComponent &&
!rowInfo.subRows &&
isExpanded &&
SubComponent(rowInfo)}
</TrGroupComponent> </TrGroupComponent>
) )
} }
const makePadRow = (row, i) => { const makePadRow = (row, i) => {
const trGroupProps = getTrGroupProps(finalState, undefined, undefined, this) const trGroupProps = getTrGroupProps(
const trProps = _.splitProps(getTrProps(finalState, undefined, undefined, this)) finalState,
undefined,
undefined,
this
)
const trProps = _.splitProps(
getTrProps(finalState, undefined, undefined, this)
)
return ( return (
<TrGroupComponent <TrGroupComponent key={i} {...trGroupProps}>
key={i}
{...trGroupProps}
>
<TrComponent <TrComponent
className={classnames( className={classnames(
'-padRow', '-padRow',
@@ -648,12 +760,26 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makePadColumn = (column, i) => { const makePadColumn = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function'
let width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth) ? column.show()
: column.show
let width = _.getFirstDefined(
resizedCol.value,
column.width,
column.minWidth
)
let flex = width let flex = width
let maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth) let maxWidth = _.getFirstDefined(
const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this)) resizedCol.value,
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this)) column.width,
column.maxWidth
)
const tdProps = _.splitProps(
getTdProps(finalState, undefined, column, this)
)
const columnProps = _.splitProps(
column.getProps(finalState, undefined, column, this)
)
const classes = [ const classes = [
tdProps.className, tdProps.className,
@@ -670,10 +796,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return ( return (
<TdComponent <TdComponent
key={i + '-' + column.id} key={i + '-' + column.id}
className={classnames( className={classnames(classes, !show && 'hidden')}
classes,
!show && 'hidden'
)}
style={{ style={{
...styles, ...styles,
flex: `${flex} 0 auto`, flex: `${flex} 0 auto`,
@@ -682,14 +805,16 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}} }}
{...tdProps.rest} {...tdProps.rest}
> >
&nbsp; {_.normalizeComponent(PadRowComponent)}
</TdComponent> </TdComponent>
) )
} }
const makeColumnFooters = () => { const makeColumnFooters = () => {
const tFootProps = getTfootProps(finalState, undefined, undefined, this) const tFootProps = getTfootProps(finalState, undefined, undefined, this)
const tFootTrProps = _.splitProps(getTfootTrProps(finalState, undefined, undefined, this)) const tFootTrProps = _.splitProps(
getTfootTrProps(finalState, undefined, undefined, this)
)
return ( return (
<TfootComponent <TfootComponent
className={tFootProps.className} className={tFootProps.className}
@@ -700,9 +825,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...tFootProps.rest} {...tFootProps.rest}
> >
<TrComponent <TrComponent
className={classnames( className={classnames(tFootTrProps.className)}
tFootTrProps.className
)}
style={tFootTrProps.style} style={tFootTrProps.style}
{...tFootTrProps.rest} {...tFootTrProps.rest}
> >
@@ -714,12 +837,28 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeColumnFooter = (column, i) => { const makeColumnFooter = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function'
const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth) ? column.show()
const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth) : column.show
const tFootTdProps = _.splitProps(getTfootTdProps(finalState, undefined, undefined, this)) const width = _.getFirstDefined(
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this)) resizedCol.value,
const columnFooterProps = _.splitProps(column.getFooterProps(finalState, undefined, column, this)) column.width,
column.minWidth
)
const maxWidth = _.getFirstDefined(
resizedCol.value,
column.width,
column.maxWidth
)
const tFootTdProps = _.splitProps(
getTfootTdProps(finalState, undefined, undefined, this)
)
const columnProps = _.splitProps(
column.getProps(finalState, undefined, column, this)
)
const columnFooterProps = _.splitProps(
column.getFooterProps(finalState, undefined, column, this)
)
const classes = [ const classes = [
tFootTdProps.className, tFootTdProps.className,
@@ -738,10 +877,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return ( return (
<TdComponent <TdComponent
key={i + '-' + column.id} key={i + '-' + column.id}
className={classnames( className={classnames(classes, !show && 'hidden')}
classes,
!show && 'hidden'
)}
style={{ style={{
...styles, ...styles,
flex: `${width} 0 auto`, flex: `${width} 0 auto`,
@@ -761,23 +897,33 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makePagination = () => { const makePagination = () => {
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this)) const paginationProps = _.splitProps(
return <PaginationComponent getPaginationProps(finalState, undefined, undefined, this)
{...resolvedState} )
pages={pages} return (
canPrevious={canPrevious} <PaginationComponent
canNext={canNext} {...resolvedState}
onPageChange={this.onPageChange} pages={pages}
onPageSizeChange={this.onPageSizeChange} canPrevious={canPrevious}
className={paginationProps.className} canNext={canNext}
style={paginationProps.style} onPageChange={this.onPageChange}
{...paginationProps.rest} onPageSizeChange={this.onPageSizeChange}
/> className={paginationProps.className}
style={paginationProps.style}
{...paginationProps.rest}
/>
)
} }
const rootProps = _.splitProps(getProps(finalState, undefined, undefined, this)) const rootProps = _.splitProps(
const tableProps = _.splitProps(getTableProps(finalState, undefined, undefined, this)) getProps(finalState, undefined, undefined, this)
const tBodyProps = _.splitProps(getTbodyProps(finalState, undefined, undefined, this)) )
const tableProps = _.splitProps(
getTableProps(finalState, undefined, undefined, this)
)
const tBodyProps = _.splitProps(
getTbodyProps(finalState, undefined, undefined, this)
)
const loadingProps = getLoadingProps(finalState, undefined, undefined, this) const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
const noDataProps = getNoDataProps(finalState, undefined, undefined, this) const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
const resizerProps = getResizerProps(finalState, undefined, undefined, this) const resizerProps = getResizerProps(finalState, undefined, undefined, this)
@@ -786,11 +932,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const pagination = makePagination() const pagination = makePagination()
return ( return (
<div <div
className={classnames( className={classnames('ReactTable', className, rootProps.className)}
'ReactTable',
className,
rootProps.className
)}
style={{ style={{
...style, ...style,
...rootProps.style ...rootProps.style
@@ -798,9 +940,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...rootProps.rest} {...rootProps.rest}
> >
{showPagination && showPaginationTop {showPagination && showPaginationTop
? <div className='pagination-top'> ? <div className="pagination-top">
{pagination} {pagination}
</div> </div>
: null} : null}
<TableComponent <TableComponent
className={classnames( className={classnames(
@@ -827,17 +969,14 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{hasColumnFooter ? makeColumnFooters() : null} {hasColumnFooter ? makeColumnFooters() : null}
</TableComponent> </TableComponent>
{showPagination && showPaginationBottom {showPagination && showPaginationBottom
? <div className='pagination-bottom'> ? <div className="pagination-bottom">
{pagination} {pagination}
</div> </div>
: null} : null}
{!pageRows.length && ( {!pageRows.length &&
<NoDataComponent <NoDataComponent {...noDataProps}>
{...noDataProps}
>
{_.normalizeComponent(noDataText)} {_.normalizeComponent(noDataText)}
</NoDataComponent> </NoDataComponent>}
)}
<LoadingComponent <LoadingComponent
loading={loading} loading={loading}
loadingText={loadingText} loadingText={loadingText}
+104 -86
View File
@@ -1,100 +1,118 @@
export default Base => class extends Base { export default Base =>
componentWillMount () { class extends Base {
this.setStateWithData(this.getDataModel(this.getResolvedState())) componentWillMount () {
} this.setStateWithData(this.getDataModel(this.getResolvedState()))
componentDidMount () {
this.fireFetchData()
}
componentWillReceiveProps (nextProps, nextState) {
const oldState = this.getResolvedState()
const newState = this.getResolvedState(nextProps, nextState)
// Do a deep compare of new and old `defaultOption` and
// if they are different reset `option = defaultOption`
const defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded']
defaultableOptions.forEach(x => {
const defaultName = `default${x.charAt(0).toUpperCase() + x.slice(1)}`
if (JSON.stringify(oldState[defaultName]) !== JSON.stringify(newState[defaultName])) {
newState[x] = newState[defaultName]
}
})
// If they change these table options, we need to reset defaults
// or else we could get into a state where the user has changed the UI
// and then disabled the ability to change it back.
// e.g. If `filterable` has changed, set `filtered = defaultFiltered`
const resettableOptions = ['sortable', 'filterable', 'resizable']
resettableOptions.forEach(x => {
if (oldState[x] !== newState[x]) {
const baseName = x.replace('able', '')
const optionName = `${baseName}ed`
const defaultName = `default${optionName.charAt(0).toUpperCase() + optionName.slice(1)}`
newState[optionName] = newState[defaultName]
}
})
// Props that trigger a data update
if (
oldState.data !== newState.data ||
oldState.columns !== newState.columns ||
oldState.pivotBy !== newState.pivotBy ||
oldState.sorted !== newState.sorted ||
oldState.filtered !== newState.filtered
) {
this.setStateWithData(this.getDataModel(newState))
} }
}
setStateWithData (newState, cb) { componentDidMount () {
const oldState = this.getResolvedState() this.fireFetchData()
const newResolvedState = this.getResolvedState({}, newState) }
const {freezeWhenExpanded} = newResolvedState
// Default to unfrozen state componentWillReceiveProps (nextProps, nextState) {
newResolvedState.frozen = false const oldState = this.getResolvedState()
const newState = this.getResolvedState(nextProps, nextState)
// If freezeWhenExpanded is set, check for frozen conditions // Do a deep compare of new and old `defaultOption` and
if (freezeWhenExpanded) { // if they are different reset `option = defaultOption`
// if any rows are expanded, freeze the existing data and sorting const defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded']
const keys = Object.keys(newResolvedState.expanded) defaultableOptions.forEach(x => {
for (var i = 0; i < keys.length; i++) { const defaultName = `default${x.charAt(0).toUpperCase() + x.slice(1)}`
if (newResolvedState.expanded[keys[i]]) { if (
newResolvedState.frozen = true JSON.stringify(oldState[defaultName]) !==
break JSON.stringify(newState[defaultName])
) {
newState[x] = newState[defaultName]
}
})
// If they change these table options, we need to reset defaults
// or else we could get into a state where the user has changed the UI
// and then disabled the ability to change it back.
// e.g. If `filterable` has changed, set `filtered = defaultFiltered`
const resettableOptions = ['sortable', 'filterable', 'resizable']
resettableOptions.forEach(x => {
if (oldState[x] !== newState[x]) {
const baseName = x.replace('able', '')
const optionName = `${baseName}ed`
const defaultName = `default${optionName.charAt(0).toUpperCase() +
optionName.slice(1)}`
newState[optionName] = newState[defaultName]
}
})
// Props that trigger a data update
if (
oldState.data !== newState.data ||
oldState.columns !== newState.columns ||
oldState.pivotBy !== newState.pivotBy ||
oldState.sorted !== newState.sorted ||
oldState.filtered !== newState.filtered
) {
this.setStateWithData(this.getDataModel(newState))
}
}
setStateWithData (newState, cb) {
const oldState = this.getResolvedState()
const newResolvedState = this.getResolvedState({}, newState)
const { freezeWhenExpanded } = newResolvedState
// Default to unfrozen state
newResolvedState.frozen = false
// If freezeWhenExpanded is set, check for frozen conditions
if (freezeWhenExpanded) {
// if any rows are expanded, freeze the existing data and sorting
const keys = Object.keys(newResolvedState.expanded)
for (var i = 0; i < keys.length; i++) {
if (newResolvedState.expanded[keys[i]]) {
newResolvedState.frozen = true
break
}
} }
} }
}
// If the data isn't frozen and either the data or // If the data isn't frozen and either the data or
// sorting model has changed, update the data // sorting model has changed, update the data
if (
(oldState.frozen && !newResolvedState.frozen) ||
oldState.sorted !== newResolvedState.sorted ||
oldState.filtered !== newResolvedState.filtered ||
oldState.showFilters !== newResolvedState.showFilters ||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData)
) {
// Handle collapseOnsortedChange & collapseOnDataChange
if ( if (
(oldState.sorted !== newResolvedState.sorted && this.props.collapseOnSortingChange) || (oldState.frozen && !newResolvedState.frozen) ||
(oldState.filtered !== newResolvedState.filtered) || oldState.sorted !== newResolvedState.sorted ||
(oldState.showFilters !== newResolvedState.showFilters) || oldState.filtered !== newResolvedState.filtered ||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnDataChange) oldState.showFilters !== newResolvedState.showFilters ||
(!newResolvedState.frozen &&
oldState.resolvedData !== newResolvedState.resolvedData)
) { ) {
newResolvedState.expanded = {} // Handle collapseOnsortedChange & collapseOnDataChange
if (
(oldState.sorted !== newResolvedState.sorted &&
this.props.collapseOnSortingChange) ||
oldState.filtered !== newResolvedState.filtered ||
oldState.showFilters !== newResolvedState.showFilters ||
(!newResolvedState.frozen &&
oldState.resolvedData !== newResolvedState.resolvedData &&
this.props.collapseOnDataChange)
) {
newResolvedState.expanded = {}
}
Object.assign(newResolvedState, this.getSortedData(newResolvedState))
} }
Object.assign(newResolvedState, this.getSortedData(newResolvedState)) // Calculate pageSize all the time
} if (newResolvedState.sortedData) {
newResolvedState.pages = newResolvedState.manual
? newResolvedState.pages
: Math.ceil(
newResolvedState.sortedData.length / newResolvedState.pageSize
)
newResolvedState.page = Math.max(
newResolvedState.page >= newResolvedState.pages
? newResolvedState.pages - 1
: newResolvedState.page,
0
)
}
// Calculate pageSize all the time return this.setState(newResolvedState, cb)
if (newResolvedState.sortedData) {
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.sortedData.length / newResolvedState.pageSize)
newResolvedState.page = Math.max(newResolvedState.page >= newResolvedState.pages ? newResolvedState.pages - 1 : newResolvedState.page, 0)
} }
return this.setState(newResolvedState, cb)
} }
}
+651 -591
View File
File diff suppressed because it is too large Load Diff
+36 -39
View File
@@ -3,9 +3,8 @@ import classnames from 'classnames'
// //
// import _ from './utils' // import _ from './utils'
const defaultButton = (props) => ( const defaultButton = props =>
<button type='button' {...props} className='-btn'>{props.children}</button> <button type='button' {...props} className='-btn'>{props.children}</button>
)
export default class ReactTablePagination extends Component { export default class ReactTablePagination extends Component {
constructor (props) { constructor (props) {
@@ -16,12 +15,12 @@ export default class ReactTablePagination extends Component {
this.applyPage = this.applyPage.bind(this) this.applyPage = this.applyPage.bind(this)
this.state = { this.state = {
page: props.page page: props.page,
} }
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
this.setState({page: nextProps.page}) this.setState({ page: nextProps.page })
} }
getSafePage (page) { getSafePage (page) {
@@ -33,7 +32,7 @@ export default class ReactTablePagination extends Component {
changePage (page) { changePage (page) {
page = this.getSafePage(page) page = this.getSafePage(page)
this.setState({page}) this.setState({ page })
if (this.props.page !== page) { if (this.props.page !== page) {
this.props.onPageChange(page) this.props.onPageChange(page)
} }
@@ -60,7 +59,7 @@ export default class ReactTablePagination extends Component {
onPageSizeChange, onPageSizeChange,
className, className,
PreviousComponent = defaultButton, PreviousComponent = defaultButton,
NextComponent = defaultButton NextComponent = defaultButton,
} = this.props } = this.props
return ( return (
@@ -70,7 +69,7 @@ export default class ReactTablePagination extends Component {
> >
<div className='-previous'> <div className='-previous'>
<PreviousComponent <PreviousComponent
onClick={(e) => { onClick={e => {
if (!canPrevious) return if (!canPrevious) return
this.changePage(page - 1) this.changePage(page - 1)
}} }}
@@ -81,53 +80,51 @@ export default class ReactTablePagination extends Component {
</div> </div>
<div className='-center'> <div className='-center'>
<span className='-pageInfo'> <span className='-pageInfo'>
{this.props.pageText} {showPageJump ? ( {this.props.pageText}{' '}
<div className='-pageJump'> {showPageJump
<input ? <div className='-pageJump'>
type={this.state.page === '' ? 'text' : 'number'} <input
onChange={e => { type={this.state.page === '' ? 'text' : 'number'}
const val = e.target.value onChange={e => {
const page = val - 1 const val = e.target.value
if (val === '') { const page = val - 1
return this.setState({page: val}) if (val === '') {
} return this.setState({ page: val })
this.setState({page: this.getSafePage(page)}) }
}} this.setState({ page: this.getSafePage(page) })
value={this.state.page === '' ? '' : this.state.page + 1} }}
onBlur={this.applyPage} value={this.state.page === '' ? '' : this.state.page + 1}
onKeyPress={e => { onBlur={this.applyPage}
if (e.which === 13 || e.keyCode === 13) { onKeyPress={e => {
this.applyPage() if (e.which === 13 || e.keyCode === 13) {
} this.applyPage()
}} }
/> }}
</div> />
) : ( </div>
<span className='-currentPage'>{page + 1}</span> : <span className='-currentPage'>{page + 1}</span>}{' '}
)} {this.props.ofText} <span className='-totalPages'>{pages || 1}</span> {this.props.ofText}{' '}
<span className='-totalPages'>{pages || 1}</span>
</span> </span>
{showPageSizeOptions && ( {showPageSizeOptions &&
<span className='select-wrap -pageSizeOptions'> <span className='select-wrap -pageSizeOptions'>
<select <select
onChange={(e) => onPageSizeChange(Number(e.target.value))} onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize} value={pageSize}
> >
{pageSizeOptions.map((option, i) => { {pageSizeOptions.map((option, i) => {
return ( return (
<option <option key={i} value={option}>
key={i}
value={option}>
{option} {this.props.rowsText} {option} {this.props.rowsText}
</option> </option>
) )
})} })}
</select> </select>
</span> </span>}
)}
</div> </div>
<div className='-next'> <div className='-next'>
<NextComponent <NextComponent
onClick={(e) => { onClick={e => {
if (!canNext) return if (!canNext) return
this.changePage(page + 1) this.changePage(page + 1)
}} }}
+27 -27
View File
@@ -18,7 +18,7 @@ export default {
splitProps, splitProps,
compactObject, compactObject,
isSortingDesc, isSortingDesc,
normalizeComponent normalizeComponent,
} }
function get (obj, path, def) { function get (obj, path, def) {
@@ -94,12 +94,14 @@ function remove (a, b) {
function clone (a) { function clone (a) {
try { try {
return JSON.parse(JSON.stringify(a, (key, value) => { return JSON.parse(
if (typeof value === 'function') { JSON.stringify(a, (key, value) => {
return value.toString() if (typeof value === 'function') {
} return value.toString()
return value }
})) return value
})
)
} catch (e) { } catch (e) {
return a return a
} }
@@ -120,14 +122,10 @@ function sum (arr) {
} }
function makeTemplateComponent (compClass) { function makeTemplateComponent (compClass) {
return ({children, className, ...rest}) => ( return ({ children, className, ...rest }) =>
<div <div className={classnames(compClass, className)} {...rest}>
className={classnames(compClass, className)}
{...rest}
>
{children} {children}
</div> </div>
)
} }
function groupBy (xs, key) { function groupBy (xs, key) {
@@ -149,10 +147,10 @@ function isArray (a) {
function makePathArray (obj) { function makePathArray (obj) {
return flattenDeep(obj) return flattenDeep(obj)
.join('.') .join('.')
.replace('[', '.') .replace('[', '.')
.replace(']', '') .replace(']', '')
.split('.') .split('.')
} }
function flattenDeep (arr, newArr = []) { function flattenDeep (arr, newArr = []) {
@@ -166,18 +164,22 @@ function flattenDeep (arr, newArr = []) {
return newArr return newArr
} }
function splitProps ({className, style, ...rest}) { function splitProps ({ className, style, ...rest }) {
return { return {
className, className,
style, style,
rest rest,
} }
} }
function compactObject (obj) { function compactObject (obj) {
const newObj = {} const newObj = {}
for (var key in obj) { for (var key in obj) {
if (obj.hasOwnProperty(key) && obj[key] !== undefined && typeof obj[key] !== 'undefined') { if (
obj.hasOwnProperty(key) &&
obj[key] !== undefined &&
typeof obj[key] !== 'undefined'
) {
newObj[key] = obj[key] newObj[key] = obj[key]
} }
} }
@@ -189,11 +191,9 @@ function isSortingDesc (d) {
} }
function normalizeComponent (Comp, params = {}, fallback = Comp) { function normalizeComponent (Comp, params = {}, fallback = Comp) {
return typeof Comp === 'function' ? ( return typeof Comp === 'function'
Object.getPrototypeOf(Comp).isReactComponent ? ( ? Object.getPrototypeOf(Comp).isReactComponent
<Comp ? <Comp {...params} />
{...params} : Comp(params)
/> : fallback
) : Comp(params)
) : fallback
} }