Added defaultSortDesc prop and formatted with prettier + project's eslint

This commit is contained in:
Tanner Linsley
2017-06-09 21:02:28 -06:00
parent f4704b146c
commit d9248cef2b
11 changed files with 1209 additions and 980 deletions
+5
View File
@@ -1,3 +1,8 @@
## 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
##### New Features
+8 -2
View File
@@ -169,6 +169,7 @@ These are all of the available props (and their default values) for the main `<R
sortable: true,
resizable: true,
filterable: false,
defaultSortDesc: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
@@ -286,7 +287,8 @@ These are all of the available props (and their default values) for the main `<R
footerStyle: {},
getFooterProps: () => ({}),
filterMethod: undefined,
sortMethod: undefined
sortMethod: undefined,
defaultSortDesc: undefined,
},
// Global Expander Column Defaults
@@ -804,7 +806,11 @@ Accessing internal state and wrapping with more UI:
The possibilities are endless!
## 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
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!
+30 -23
View File
@@ -6,7 +6,7 @@ import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
render() {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
@@ -22,35 +22,43 @@ class Story extends React.PureComponent {
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName'
},
{
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}
]
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age'
}
]
}
]
return (
<div>
<div className='table-wrap'>
<div className="table-wrap">
<ReactTable
className='-striped -highlight'
className="-striped -highlight"
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<div style={{ textAlign: 'center' }}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
@@ -62,9 +70,8 @@ class Story extends React.PureComponent {
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Simple')
export default () => (
export default () =>
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+11 -9
View File
@@ -4557,14 +4557,16 @@ react-json-tree@^0.10.9:
prop-types "^15.5.8"
react-base16-styling "^0.5.1"
react-router-dom@next:
version "4.0.0-beta.8"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.0.0-beta.8.tgz#907a5a0a36e9190652c80f2feead0eadbbba262e"
react-router-dom@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025"
dependencies:
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"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95"
dependencies:
@@ -4621,9 +4623,9 @@ react-scripts@0.9.5:
optionalDependencies:
fsevents "1.0.17"
react-story@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/react-story/-/react-story-0.0.6.tgz#ec3e6b42e5edab8a74dd581c12bd321ec304eaba"
react-story@^0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/react-story/-/react-story-0.0.10.tgz#4c07d122962900162f0871666780da34402a2573"
dependencies:
classnames "^2.2.5"
glamor "^2.20.25"
@@ -4631,7 +4633,7 @@ react-story@^0.0.6:
javascript-detect-element-resize "^0.5.3"
raf "^3.3.2"
react-fastclick "^3.0.1"
react-router-dom next
react-router-dom "^4.1.1"
react@^15.5.4:
version "15.5.4"
+2 -2
View File
@@ -34,8 +34,8 @@
"build": "npm-run-all build:*",
"prepublish": "npm run build && npm run umd",
"postpublish": "git push --tags",
"docs": "cd docs && yarn && yarn start",
"docs:build": "cd docs && yarn && yarn run build"
"docs": "yarn watch & cd docs && yarn && yarn start",
"docs:build": "yarn build && cd docs && yarn && yarn run build"
},
"dependencies": {
"classnames": "^2.2.5",
+31 -34
View File
@@ -24,18 +24,21 @@ export default {
sortable: true,
resizable: true,
filterable: false,
defaultSortDesc: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
defaultExpanded: {},
defaultFilterMethod: (filter, row, column) => {
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) => {
// force null and undefined to the bottom
a = (a === null || a === undefined) ? '' : a
b = (b === null || b === undefined) ? '' : b
a = a === null || a === undefined ? '' : a
b = b === null || b === undefined ? '' : b
// force any string values to lowercase
a = typeof a === 'string' ? a.toLowerCase() : a
b = typeof b === 'string' ? b.toLowerCase() : b
@@ -142,7 +145,7 @@ export default {
footerStyle: {},
getFooterProps: emptyObj,
filterMethod: undefined,
sortMethod: undefined
sortMethod: undefined,
},
// Global Expander Column Defaults
@@ -150,7 +153,7 @@ export default {
sortable: false,
resizable: false,
filterable: false,
width: 35
width: 35,
},
pivotDefaults: {
@@ -172,7 +175,7 @@ export default {
TbodyComponent: _.makeTemplateComponent('rt-tbody'),
TrGroupComponent: _.makeTemplateComponent('rt-tr-group'),
TrComponent: _.makeTemplateComponent('rt-tr'),
ThComponent: ({toggleSort, className, children, ...rest}) => {
ThComponent: ({ toggleSort, className, children, ...rest }) => {
return (
<div
className={classnames(className, 'rt-th')}
@@ -187,51 +190,45 @@ export default {
},
TdComponent: _.makeTemplateComponent('rt-td'),
TfootComponent: _.makeTemplateComponent('rt-tfoot'),
FilterComponent: ({filter, onChange}) => (
<input type='text'
FilterComponent: ({ filter, onChange }) =>
<input
type='text'
style={{
width: '100%'
width: '100%',
}}
value={filter ? filter.value : ''}
onChange={(event) => onChange(event.target.value)}
/>
),
ExpanderComponent: ({isExpanded}) => (
onChange={event => onChange(event.target.value)}
/>,
ExpanderComponent: ({ isExpanded }) =>
<div className={classnames('rt-expander', isExpanded && '-open')}>
&bull;
</div>
),
PivotValueComponent: ({subRows, value}) => (
<span>{value} {subRows && `(${subRows.length})`}</span>
),
AggregatedComponent: ({subRows, column}) => {
</div>,
PivotValueComponent: ({ subRows, value }) =>
<span>{value} {subRows && `(${subRows.length})`}</span>,
AggregatedComponent: ({ subRows, column }) => {
const previewValues = subRows
.filter(d => typeof d[column.id] !== 'undefined')
.map((row, i) => (
<span key={i}>{row[column.id]}{i < subRows.length - 1 ? ', ' : ''}</span>
))
return (
<span>{previewValues}</span>
)
.map((row, i) =>
<span key={i}>
{row[column.id]}{i < subRows.length - 1 ? ', ' : ''}
</span>
)
return <span>{previewValues}</span>
},
PivotComponent: undefined, // this is a computed default generated using
// the ExpanderComponent and PivotValueComponent at run-time in methods.js
PaginationComponent: Pagination,
PreviousComponent: undefined,
NextComponent: undefined,
LoadingComponent: ({className, loading, loadingText, ...rest}) => (
<div className={classnames(
'-loading',
{'-active': loading},
className
)}
LoadingComponent: ({ className, loading, loadingText, ...rest }) =>
<div
className={classnames('-loading', { '-active': loading }, className)}
{...rest}
>
<div className='-loading-inner'>
{loadingText}
</div>
</div>
),
</div>,
NoDataComponent: _.makeTemplateComponent('rt-noData'),
ResizerComponent: _.makeTemplateComponent('rt-resizer')
ResizerComponent: _.makeTemplateComponent('rt-resizer'),
}
+304 -167
View File
@@ -11,7 +11,7 @@ export const ReactTableDefaults = defaultProps
export default class ReactTable extends Methods(Lifecycle(Component)) {
static defaultProps = defaultProps
constructor (props) {
constructor(props) {
super()
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 {
children,
@@ -148,7 +148,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const newPath = path.concat([i])
if (rowWithViewIndex[subRowsKey] && _.get(expanded, newPath)) {
[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index)
;[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(
rowWithViewIndex[subRowsKey],
newPath,
index
)
}
return rowWithViewIndex
}),
@@ -156,15 +160,17 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
]
}
[pageRows] = recurseRowsViewIndex(pageRows)
;[pageRows] = recurseRowsViewIndex(pageRows)
const canPrevious = page > 0
const canNext = page + 1 < pages
const rowMinWidth = _.sum(allVisibleColumns.map(d => {
const resizedColumn = resized.find(x => x.id === d.id) || {}
return _.getFirstDefined(resizedColumn.value, d.width, d.minWidth)
}))
const rowMinWidth = _.sum(
allVisibleColumns.map(d => {
const resizedColumn = resized.find(x => x.id === d.id) || {}
return _.getFirstDefined(resizedColumn.value, d.width, d.minWidth)
})
)
let rowIndex = -1
@@ -184,8 +190,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
// Visual Components
const makeHeaderGroups = () => {
const theadGroupProps = _.splitProps(getTheadGroupProps(finalState, undefined, undefined, this))
const theadGroupTrProps = _.splitProps(getTheadGroupTrProps(finalState, undefined, undefined, this))
const theadGroupProps = _.splitProps(
getTheadGroupProps(finalState, undefined, undefined, this)
)
const theadGroupTrProps = _.splitProps(
getTheadGroupTrProps(finalState, undefined, undefined, this)
)
return (
<TheadComponent
className={classnames('-headerGroups', theadGroupProps.className)}
@@ -207,13 +217,30 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const makeHeaderGroup = (column, i) => {
const resizedValue = col => (resized.find(x => x.id === col.id) || {}).value
const flex = _.sum(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 resizedValue = col =>
(resized.find(x => x.id === col.id) || {}).value
const flex = _.sum(
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 columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
const theadGroupThProps = _.splitProps(
getTheadGroupThProps(finalState, undefined, column, this)
)
const columnHeaderProps = _.splitProps(
column.getHeaderProps(finalState, undefined, column, this)
)
const classes = [
column.headerClassName,
@@ -241,9 +268,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return (
<ThComponent
key={i + '-' + column.id}
className={classnames(
classes
)}
className={classnames(classes)}
style={{
...styles,
...flexStyles
@@ -259,8 +284,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const makeHeaders = () => {
const theadProps = _.splitProps(getTheadProps(finalState, undefined, undefined, this))
const theadTrProps = _.splitProps(getTheadTrProps(finalState, undefined, undefined, this))
const theadProps = _.splitProps(
getTheadProps(finalState, undefined, undefined, this)
)
const theadTrProps = _.splitProps(
getTheadTrProps(finalState, undefined, undefined, this)
)
return (
<TheadComponent
className={classnames('-header', theadProps.className)}
@@ -284,11 +313,25 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeHeader = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {}
const sort = sorted.find(d => d.id === column.id)
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(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 show = typeof column.show === 'function'
? column.show()
: column.show
const width = _.getFirstDefined(
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 = [
column.headerClassName,
@@ -308,14 +351,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const isResizable = _.getFirstDefined(column.resizable, resizable, false)
const resizer = isResizable ? (
<ResizerComponent
onMouseDown={e => this.resizeColumnStart(column, e, false)}
onTouchStart={e => this.resizeColumnStart(column, e, true)}
{...resizerProps}
/>
) : null
const resizer = isResizable
? <ResizerComponent
onMouseDown={e => this.resizeColumnStart(column, e, false)}
onTouchStart={e => this.resizeColumnStart(column, e, true)}
{...resizerProps}
/>
: null
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') : '',
isSortable && '-cursor-pointer',
!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={{
...styles,
@@ -336,12 +380,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
width: `${width}px`,
maxWidth: `${maxWidth}px`
}}
toggleSort={(e) => {
toggleSort={e => {
isSortable && this.sortColumn(column, e.shiftKey)
}}
{...rest}
>
<div className='rt-resizable-header-content'>
<div className="rt-resizable-header-content">
{_.normalizeComponent(column.Header, {
data: sortedData,
column: column
@@ -353,8 +397,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const makeFilters = () => {
const theadFilterProps = _.splitProps(getTheadFilterProps(finalState, undefined, undefined, this))
const theadFilterTrProps = _.splitProps(getTheadFilterTrProps(finalState, undefined, undefined, this))
const theadFilterProps = _.splitProps(
getTheadFilterProps(finalState, undefined, undefined, this)
)
const theadFilterTrProps = _.splitProps(
getTheadFilterTrProps(finalState, undefined, undefined, this)
)
return (
<TheadComponent
className={classnames('-filters', theadFilterProps.className)}
@@ -377,10 +425,22 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeFilter = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {}
const width = _.getFirstDefined(resizedCol.value, column.width, 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 width = _.getFirstDefined(
resizedCol.value,
column.width,
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 = [
column.headerClassName,
@@ -403,14 +463,16 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const ResolvedFilterComponent = column.Filter || FilterComponent
const isFilterable = _.getFirstDefined(column.filterable, filterable, false)
const isFilterable = _.getFirstDefined(
column.filterable,
filterable,
false
)
return (
<ThComponent
key={i + '-' + column.id}
className={classnames(
classes
)}
className={classnames(classes)}
style={{
...styles,
flex: `${width} 0 auto`,
@@ -419,16 +481,17 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}}
{...rest}
>
{isFilterable ? (
_.normalizeComponent(ResolvedFilterComponent,
{
column,
filter,
onChange: (value) => (this.filterColumn(column, value))
},
defaultProps.column.Filter
)
) : null}
{isFilterable
? _.normalizeComponent(
ResolvedFilterComponent,
{
column,
filter,
onChange: value => this.filterColumn(column, value)
},
defaultProps.column.Filter
)
: null}
</ThComponent>
)
}
@@ -447,12 +510,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const isExpanded = _.get(expanded, rowInfo.nestingPath)
const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this)
const trProps = _.splitProps(getTrProps(finalState, rowInfo, undefined, this))
const trProps = _.splitProps(
getTrProps(finalState, rowInfo, undefined, this)
)
return (
<TrGroupComponent
key={rowInfo.nestingPath.join('_')}
{...trGroupProps}
>
<TrGroupComponent key={rowInfo.nestingPath.join('_')} {...trGroupProps}>
<TrComponent
className={classnames(
trProps.className,
@@ -463,11 +525,25 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
>
{allVisibleColumns.map((column, i2) => {
const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(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 show = typeof column.show === 'function'
? column.show()
: column.show
const width = _.getFirstDefined(
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 = [
tdProps.className,
@@ -484,7 +560,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const cellInfo = {
...rowInfo,
isExpanded,
column: {...column},
column: { ...column },
value: rowInfo.row[column.id],
pivoted: column.pivoted,
expander: column.expander,
@@ -504,7 +580,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
let isBranch
let isPreview
const onExpanderClick = (e) => {
const onExpanderClick = e => {
let newExpanded = _.clone(expanded)
if (isExpanded) {
newExpanded = _.set(newExpanded, cellInfo.nestingPath, false)
@@ -512,29 +588,41 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
newExpanded = _.set(newExpanded, cellInfo.nestingPath, {})
}
return this.setStateWithData({
expanded: newExpanded
}, () => {
onExpandedChange && onExpandedChange(newExpanded, cellInfo.nestingPath, e)
})
return this.setStateWithData(
{
expanded: newExpanded
},
() => {
onExpandedChange &&
onExpandedChange(newExpanded, cellInfo.nestingPath, e)
}
)
}
// Default to a standard cell
let resolvedCell = _.normalizeComponent(column.Cell, cellInfo, value)
let resolvedCell = _.normalizeComponent(
column.Cell,
cellInfo,
value
)
// Resolve Renderers
const ResolvedAggregatedComponent = column.Aggregated || (!column.aggregate ? AggregatedComponent : column.Cell)
const ResolvedExpanderComponent = column.Expander || ExpanderComponent
const ResolvedPivotValueComponent = column.PivotValue || PivotValueComponent
const DefaultResolvedPivotComponent = PivotComponent || (
props => (
<div>
<ResolvedExpanderComponent {...props} />
<ResolvedPivotValueComponent {...props} />
</div>
)
)
const ResolvedPivotComponent = column.Pivot || DefaultResolvedPivotComponent
const ResolvedAggregatedComponent =
column.Aggregated ||
(!column.aggregate ? AggregatedComponent : column.Cell)
const ResolvedExpanderComponent =
column.Expander || ExpanderComponent
const ResolvedPivotValueComponent =
column.PivotValue || PivotValueComponent
const DefaultResolvedPivotComponent =
PivotComponent ||
(props =>
<div>
<ResolvedExpanderComponent {...props} />
<ResolvedPivotValueComponent {...props} />
</div>)
const ResolvedPivotComponent =
column.Pivot || DefaultResolvedPivotComponent
// Is this cell expandable?
if (cellInfo.pivoted || cellInfo.expander) {
@@ -556,30 +644,47 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
if (cellInfo.pivoted) {
// Is this column a branch?
isBranch = rowInfo.row[pivotIDKey] === column.id &&
cellInfo.subRows
isBranch =
rowInfo.row[pivotIDKey] === column.id && cellInfo.subRows
// Should this column be blank?
isPreview = pivotBy.indexOf(column.id) > pivotBy.indexOf(rowInfo.row[pivotIDKey]) &&
cellInfo.subRows
isPreview =
pivotBy.indexOf(column.id) >
pivotBy.indexOf(rowInfo.row[pivotIDKey]) && cellInfo.subRows
// Pivot Cell Render Override
if (isBranch) {
// isPivot
resolvedCell = _.normalizeComponent(ResolvedPivotComponent, {
...cellInfo,
value: row[pivotValKey]
}, row[pivotValKey])
resolvedCell = _.normalizeComponent(
ResolvedPivotComponent,
{
...cellInfo,
value: row[pivotValKey]
},
row[pivotValKey]
)
} else if (isPreview) {
// Show the pivot preview
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value)
resolvedCell = _.normalizeComponent(
ResolvedAggregatedComponent,
cellInfo,
value
)
} else {
resolvedCell = null
}
} else if (cellInfo.aggregated) {
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value)
resolvedCell = _.normalizeComponent(
ResolvedAggregatedComponent,
cellInfo,
value
)
}
if (cellInfo.expander) {
resolvedCell = _.normalizeComponent(ResolvedExpanderComponent, cellInfo, row[pivotValKey])
resolvedCell = _.normalizeComponent(
ResolvedExpanderComponent,
cellInfo,
row[pivotValKey]
)
if (pivotBy) {
if (cellInfo.groupedByPivot) {
resolvedCell = null
@@ -614,24 +719,31 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
)
})}
</TrComponent>
{(
rowInfo.subRows &&
{rowInfo.subRows &&
isExpanded &&
rowInfo.subRows.map((d, i) => makePageRow(d, i, rowInfo.nestingPath))
)}
{SubComponent && !rowInfo.subRows && isExpanded && SubComponent(rowInfo)}
rowInfo.subRows.map((d, i) =>
makePageRow(d, i, rowInfo.nestingPath)
)}
{SubComponent &&
!rowInfo.subRows &&
isExpanded &&
SubComponent(rowInfo)}
</TrGroupComponent>
)
}
const makePadRow = (row, i) => {
const trGroupProps = getTrGroupProps(finalState, undefined, undefined, this)
const trProps = _.splitProps(getTrProps(finalState, undefined, undefined, this))
const trGroupProps = getTrGroupProps(
finalState,
undefined,
undefined,
this
)
const trProps = _.splitProps(
getTrProps(finalState, undefined, undefined, this)
)
return (
<TrGroupComponent
key={i}
{...trGroupProps}
>
<TrGroupComponent key={i} {...trGroupProps}>
<TrComponent
className={classnames(
'-padRow',
@@ -648,12 +760,26 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makePadColumn = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
let width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
const show = typeof column.show === 'function'
? column.show()
: column.show
let width = _.getFirstDefined(
resizedCol.value,
column.width,
column.minWidth
)
let flex = width
let maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this))
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
let maxWidth = _.getFirstDefined(
resizedCol.value,
column.width,
column.maxWidth
)
const tdProps = _.splitProps(
getTdProps(finalState, undefined, column, this)
)
const columnProps = _.splitProps(
column.getProps(finalState, undefined, column, this)
)
const classes = [
tdProps.className,
@@ -670,10 +796,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return (
<TdComponent
key={i + '-' + column.id}
className={classnames(
classes,
!show && 'hidden'
)}
className={classnames(classes, !show && 'hidden')}
style={{
...styles,
flex: `${flex} 0 auto`,
@@ -681,15 +804,15 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
maxWidth: `${maxWidth}px`
}}
{...tdProps.rest}
>
&nbsp;
</TdComponent>
/>
)
}
const makeColumnFooters = () => {
const tFootProps = getTfootProps(finalState, undefined, undefined, this)
const tFootTrProps = _.splitProps(getTfootTrProps(finalState, undefined, undefined, this))
const tFootTrProps = _.splitProps(
getTfootTrProps(finalState, undefined, undefined, this)
)
return (
<TfootComponent
className={tFootProps.className}
@@ -700,9 +823,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...tFootProps.rest}
>
<TrComponent
className={classnames(
tFootTrProps.className
)}
className={classnames(tFootTrProps.className)}
style={tFootTrProps.style}
{...tFootTrProps.rest}
>
@@ -714,12 +835,28 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makeColumnFooter = (column, i) => {
const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(resizedCol.value, 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 show = typeof column.show === 'function'
? column.show()
: column.show
const width = _.getFirstDefined(
resizedCol.value,
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 = [
tFootTdProps.className,
@@ -738,10 +875,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
return (
<TdComponent
key={i + '-' + column.id}
className={classnames(
classes,
!show && 'hidden'
)}
className={classnames(classes, !show && 'hidden')}
style={{
...styles,
flex: `${width} 0 auto`,
@@ -761,23 +895,33 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}
const makePagination = () => {
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
return <PaginationComponent
{...resolvedState}
pages={pages}
canPrevious={canPrevious}
canNext={canNext}
onPageChange={this.onPageChange}
onPageSizeChange={this.onPageSizeChange}
className={paginationProps.className}
style={paginationProps.style}
{...paginationProps.rest}
/>
const paginationProps = _.splitProps(
getPaginationProps(finalState, undefined, undefined, this)
)
return (
<PaginationComponent
{...resolvedState}
pages={pages}
canPrevious={canPrevious}
canNext={canNext}
onPageChange={this.onPageChange}
onPageSizeChange={this.onPageSizeChange}
className={paginationProps.className}
style={paginationProps.style}
{...paginationProps.rest}
/>
)
}
const rootProps = _.splitProps(getProps(finalState, undefined, undefined, this))
const tableProps = _.splitProps(getTableProps(finalState, undefined, undefined, this))
const tBodyProps = _.splitProps(getTbodyProps(finalState, undefined, undefined, this))
const rootProps = _.splitProps(
getProps(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 noDataProps = getNoDataProps(finalState, undefined, undefined, this)
const resizerProps = getResizerProps(finalState, undefined, undefined, this)
@@ -786,11 +930,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const pagination = makePagination()
return (
<div
className={classnames(
'ReactTable',
className,
rootProps.className
)}
className={classnames('ReactTable', className, rootProps.className)}
style={{
...style,
...rootProps.style
@@ -798,9 +938,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...rootProps.rest}
>
{showPagination && showPaginationTop
? <div className='pagination-top'>
{pagination}
</div>
? <div className="pagination-top">
{pagination}
</div>
: null}
<TableComponent
className={classnames(
@@ -827,17 +967,14 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{hasColumnFooter ? makeColumnFooters() : null}
</TableComponent>
{showPagination && showPaginationBottom
? <div className='pagination-bottom'>
{pagination}
</div>
? <div className="pagination-bottom">
{pagination}
</div>
: null}
{!pageRows.length && (
<NoDataComponent
{...noDataProps}
>
{!pageRows.length &&
<NoDataComponent {...noDataProps}>
{_.normalizeComponent(noDataText)}
</NoDataComponent>
)}
</NoDataComponent>}
<LoadingComponent
loading={loading}
loadingText={loadingText}
+104 -86
View File
@@ -1,100 +1,118 @@
export default Base => class extends Base {
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))
export default Base =>
class extends Base {
componentWillMount () {
this.setStateWithData(this.getDataModel(this.getResolvedState()))
}
}
setStateWithData (newState, cb) {
const oldState = this.getResolvedState()
const newResolvedState = this.getResolvedState({}, newState)
const {freezeWhenExpanded} = newResolvedState
componentDidMount () {
this.fireFetchData()
}
// Default to unfrozen state
newResolvedState.frozen = false
componentWillReceiveProps (nextProps, nextState) {
const oldState = this.getResolvedState()
const newState = this.getResolvedState(nextProps, nextState)
// 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
// 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) {
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
// 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 the data isn't frozen and either the data or
// sorting model has changed, update the data
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)
(oldState.frozen && !newResolvedState.frozen) ||
oldState.sorted !== newResolvedState.sorted ||
oldState.filtered !== newResolvedState.filtered ||
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
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)
}
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'
const defaultButton = (props) => (
const defaultButton = props =>
<button type='button' {...props} className='-btn'>{props.children}</button>
)
export default class ReactTablePagination extends Component {
constructor (props) {
@@ -16,12 +15,12 @@ export default class ReactTablePagination extends Component {
this.applyPage = this.applyPage.bind(this)
this.state = {
page: props.page
page: props.page,
}
}
componentWillReceiveProps (nextProps) {
this.setState({page: nextProps.page})
this.setState({ page: nextProps.page })
}
getSafePage (page) {
@@ -33,7 +32,7 @@ export default class ReactTablePagination extends Component {
changePage (page) {
page = this.getSafePage(page)
this.setState({page})
this.setState({ page })
if (this.props.page !== page) {
this.props.onPageChange(page)
}
@@ -60,7 +59,7 @@ export default class ReactTablePagination extends Component {
onPageSizeChange,
className,
PreviousComponent = defaultButton,
NextComponent = defaultButton
NextComponent = defaultButton,
} = this.props
return (
@@ -70,7 +69,7 @@ export default class ReactTablePagination extends Component {
>
<div className='-previous'>
<PreviousComponent
onClick={(e) => {
onClick={e => {
if (!canPrevious) return
this.changePage(page - 1)
}}
@@ -81,53 +80,51 @@ export default class ReactTablePagination extends Component {
</div>
<div className='-center'>
<span className='-pageInfo'>
{this.props.pageText} {showPageJump ? (
<div className='-pageJump'>
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value
const page = val - 1
if (val === '') {
return this.setState({page: val})
}
this.setState({page: this.getSafePage(page)})
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage()
}
}}
/>
</div>
) : (
<span className='-currentPage'>{page + 1}</span>
)} {this.props.ofText} <span className='-totalPages'>{pages || 1}</span>
{this.props.pageText}{' '}
{showPageJump
? <div className='-pageJump'>
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value
const page = val - 1
if (val === '') {
return this.setState({ page: val })
}
this.setState({ page: this.getSafePage(page) })
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage()
}
}}
/>
</div>
: <span className='-currentPage'>{page + 1}</span>}{' '}
{this.props.ofText}{' '}
<span className='-totalPages'>{pages || 1}</span>
</span>
{showPageSizeOptions && (
{showPageSizeOptions &&
<span className='select-wrap -pageSizeOptions'>
<select
onChange={(e) => onPageSizeChange(Number(e.target.value))}
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}
>
{pageSizeOptions.map((option, i) => {
return (
<option
key={i}
value={option}>
<option key={i} value={option}>
{option} {this.props.rowsText}
</option>
)
})}
</select>
</span>
)}
</span>}
</div>
<div className='-next'>
<NextComponent
onClick={(e) => {
onClick={e => {
if (!canNext) return
this.changePage(page + 1)
}}
+27 -27
View File
@@ -18,7 +18,7 @@ export default {
splitProps,
compactObject,
isSortingDesc,
normalizeComponent
normalizeComponent,
}
function get (obj, path, def) {
@@ -94,12 +94,14 @@ function remove (a, b) {
function clone (a) {
try {
return JSON.parse(JSON.stringify(a, (key, value) => {
if (typeof value === 'function') {
return value.toString()
}
return value
}))
return JSON.parse(
JSON.stringify(a, (key, value) => {
if (typeof value === 'function') {
return value.toString()
}
return value
})
)
} catch (e) {
return a
}
@@ -120,14 +122,10 @@ function sum (arr) {
}
function makeTemplateComponent (compClass) {
return ({children, className, ...rest}) => (
<div
className={classnames(compClass, className)}
{...rest}
>
return ({ children, className, ...rest }) =>
<div className={classnames(compClass, className)} {...rest}>
{children}
</div>
)
}
function groupBy (xs, key) {
@@ -149,10 +147,10 @@ function isArray (a) {
function makePathArray (obj) {
return flattenDeep(obj)
.join('.')
.replace('[', '.')
.replace(']', '')
.split('.')
.join('.')
.replace('[', '.')
.replace(']', '')
.split('.')
}
function flattenDeep (arr, newArr = []) {
@@ -166,18 +164,22 @@ function flattenDeep (arr, newArr = []) {
return newArr
}
function splitProps ({className, style, ...rest}) {
function splitProps ({ className, style, ...rest }) {
return {
className,
style,
rest
rest,
}
}
function compactObject (obj) {
const newObj = {}
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]
}
}
@@ -189,11 +191,9 @@ function isSortingDesc (d) {
}
function normalizeComponent (Comp, params = {}, fallback = Comp) {
return typeof Comp === 'function' ? (
Object.getPrototypeOf(Comp).isReactComponent ? (
<Comp
{...params}
/>
) : Comp(params)
) : fallback
return typeof Comp === 'function'
? Object.getPrototypeOf(Comp).isReactComponent
? <Comp {...params} />
: Comp(params)
: fallback
}