mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 16:30:21 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d5207eb4e | ||
|
|
0d397e0c29 | ||
|
|
b15f3ac3b0 | ||
|
|
48ea0df09d | ||
|
|
403fb7a708 | ||
|
|
ecd5658e4b | ||
|
|
3852227bdd | ||
|
|
1fec9b882f | ||
|
|
46c4c6fdb2 | ||
|
|
e702fc80ca | ||
|
|
beaa748187 | ||
|
|
cce77d24f2 | ||
|
|
3984a540c1 | ||
|
|
726fd52753 | ||
|
|
6a6d373526 | ||
|
|
e11fdab457 | ||
|
|
1e4f838326 |
@@ -22,6 +22,7 @@ import PivotingSubComponents from '../stories/PivotingSubComponents.js'
|
||||
import OneHundredKRows from '../stories/OneHundredKRows.js'
|
||||
import FunctionalRendering from '../stories/FunctionalRendering.js'
|
||||
import CustomExpanderPosition from '../stories/CustomExpanderPosition.js'
|
||||
import NoDataText from '../stories/NoDataText.js'
|
||||
//
|
||||
configure(() => {
|
||||
storiesOf('1. Docs')
|
||||
@@ -49,4 +50,5 @@ configure(() => {
|
||||
.add('100k Rows w/ Pivoting & Sub Components', OneHundredKRows)
|
||||
.add('Functional Rendering', FunctionalRendering)
|
||||
.add('Custom Expander Position', CustomExpanderPosition)
|
||||
.add('Custom "No Data" Text', NoDataText)
|
||||
}, module)
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
- [Props](#props)
|
||||
- [Columns](#columns)
|
||||
- [Column Header Groups](#column-header-groups)
|
||||
- [Custom Cell & Header Rendering](#custom-cell--and-header-rendering)
|
||||
- [Custom Cell and Header Rendering](#custom-cell-and-header-rendering)
|
||||
- [Styles](#styles)
|
||||
- [Custom Props](#custom-props)
|
||||
- [Pivoting & Aggregation](#pivoting--aggregation)
|
||||
- [Sub Tables & Sub Components](#sub-tables--sub-components)
|
||||
- [Pivoting and Aggregation](#pivoting-and-aggregation)
|
||||
- [Sub Tables and Sub Components](#sub-tables-and-sub-components)
|
||||
- [Server-side Data](#server-side-data)
|
||||
- [Fully Controlled Component](#fully-controlled-component)
|
||||
- [Functional Rendering](#functional-rendering)
|
||||
@@ -103,7 +103,7 @@ const columns = [{
|
||||
}, {
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
render: props => <span className='number'>props.value</span> // Custom cell components!
|
||||
render: props => <span className='number'>{props.value}</span> // Custom cell components!
|
||||
}, {
|
||||
header: 'Friend Name',
|
||||
accessor: d => d.friend.name // Custom value accessors!
|
||||
@@ -135,6 +135,10 @@ These are all of the available props (and their default values) for the main `<R
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: false,
|
||||
collapseOnPageChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
defaultSorting: [],
|
||||
|
||||
// Controlled State Overrides (see Fully Controlled Component section)
|
||||
page: undefined,
|
||||
@@ -183,6 +187,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
getTdProps: () => ({}),
|
||||
getPaginationProps: () => ({}),
|
||||
getLoadingProps: () => ({}),
|
||||
getNoDataProps: () => ({}),
|
||||
|
||||
// Global Column Defaults
|
||||
column: {
|
||||
@@ -205,6 +210,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
previousText: 'Previous',
|
||||
nextText: 'Next',
|
||||
loadingText: 'Loading...',
|
||||
noDataText: 'No rows found',
|
||||
pageText: 'Page',
|
||||
ofText: 'of',
|
||||
rowsText: 'rows',
|
||||
@@ -242,7 +248,6 @@ Or just define them as props
|
||||
accessor: 'propertyName' or Accessor eg. (row) => row.propertyName,
|
||||
id: 'myProperty', // Conditional - A unique ID is required if the accessor is not a string or if you would like to override the column name used in server-side calls
|
||||
sortable: true,
|
||||
sort: 'asc' or 'desc', // used to determine the column sorting on init
|
||||
show: true, // can be used to hide a column
|
||||
width: undefined, // A hardcoded width for the column. This overrides both min and max width options
|
||||
minWidth: 100 // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set)
|
||||
@@ -292,7 +297,7 @@ const columns = [{
|
||||
}]
|
||||
```
|
||||
|
||||
## Custom Cell & Header Rendering
|
||||
## Custom Cell and Header Rendering
|
||||
You can use any react component or JSX to display column headers or cells. Any component you use will be passed the following props:
|
||||
- `row` - Original row from your data
|
||||
- `rowValues` - The post-accessed values from the original row
|
||||
@@ -434,7 +439,7 @@ const columns = [{
|
||||
}]
|
||||
```
|
||||
|
||||
## Pivoting & Aggregation
|
||||
## Pivoting and Aggregation
|
||||
Pivoting the table will group records together based on their accessed values and allow the rows in that group to be expanded underneath it.
|
||||
To pivot, pass an array of `columnID`'s to `pivotBy`. Remember, a column's `id` is either the one that you assign it (when using a custom accessors) or its `accessor` string.
|
||||
```javascript
|
||||
@@ -464,7 +469,7 @@ const columns = [{
|
||||
|
||||
Pivoted columns can be sorted just like regular columns, but not independently of each other. For instance, if you click to sort the pivot column in ascending order, it will sort by each pivot recursively in ascending order together.
|
||||
|
||||
## Sub Tables & Sub Components
|
||||
## Sub Tables and Sub Components
|
||||
By adding a `SubComponent` props, you can easily add an expansion level to all root-level rows:
|
||||
```javascript
|
||||
<ReactTable
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="error-display"></div>
|
||||
<script src="static/preview.ee446fa2bd3fbfe7e38a.bundle.js"></script>
|
||||
<script src="static/preview.1dfdb2ebd0085aa535c8.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@
|
||||
</head>
|
||||
<body style="margin: 0;">
|
||||
<div id="root"></div>
|
||||
<script src="static/manager.f127c5ae855df8d8558a.bundle.js"></script>
|
||||
<script src="static/manager.d3baea6e6f08c3c0279c.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+26
-26
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"static/manager.f127c5ae855df8d8558a.bundle.js","sources":["webpack:///static/manager.f127c5ae855df8d8558a.bundle.js"],"mappings":"AAAA;AAkuDA;AA84DA;AA28DA;AA00DA;AAsyEA;AA89CA;AA8rDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAqxDA;AAsrDA;AAwyDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
|
||||
{"version":3,"file":"static/manager.d3baea6e6f08c3c0279c.bundle.js","sources":["webpack:///static/manager.d3baea6e6f08c3c0279c.bundle.js"],"mappings":"AAAA;AAkuDA;AA84DA;AA28DA;AA00DA;AAsyEA;AA89CA;AA8rDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAqxDA;AAsrDA;AAyyDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/preview.1dfdb2ebd0085aa535c8.bundle.js","sources":["webpack:///static/preview.1dfdb2ebd0085aa535c8.bundle.js"],"mappings":"AAAA;AAkuDA;AAu+CA;AA0+FA;AAmpFA;AAkxLA;AA7sBA;AAojOA;AAkjEA;AAivDA;AAy7DA;AAqlDA;AAmvDA;AAu8CA;AA6+DA;AAwlDA;AA2+CA;AAimDA;AA29DA;AA04DA;AAsxCA;AAynDA;AAurDA;AAgiEA;AA03DA;AAwwCA;AA8tDA;AA02FA;AA+tGA;AAy+CA;AAuzCA;AAkuCA;AAikDA;AA8dA;AA+jFA","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/preview.ee446fa2bd3fbfe7e38a.bundle.js","sources":["webpack:///static/preview.ee446fa2bd3fbfe7e38a.bundle.js"],"mappings":"AAAA;AAkuDA;AAiwDA;AAs1EA;AA+gGA;AAo4IA;AAt5NA;AA4udA;AA2hEA;AA2uDA;AA29DA;AA2gDA;AAosDA;AAuhDA;AA+6DA;AAioDA;AA4+CA;AAwpDA;AAisEA;AAqoDA;AAqwCA;AA2oDA;AAowDA;AAokEA;AA0vDA;AA2rDA;AA8nDA;AAwrFA;AAyiGA;AA0/CA;AAqyCA;AA22CA;AAu/CA;AAyGA;AA+jFA","sourceRoot":""}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "5.0.2",
|
||||
"version": "5.2.0",
|
||||
"description": "A fast, lightweight, opinionated table and datagrid built on React",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/tannerlinsley/react-table#readme",
|
||||
@@ -62,6 +62,7 @@
|
||||
"react-dom": "^15.4.2",
|
||||
"react-json-tree": "^0.10.1",
|
||||
"standard": "^8.0.0",
|
||||
"storybook": "^0.0.0",
|
||||
"stylus": "^0.54.5",
|
||||
"uglifyify": "3.0.3"
|
||||
},
|
||||
|
||||
+67
-74
@@ -10,7 +10,10 @@ export default {
|
||||
pivotValKey,
|
||||
subRowsKey,
|
||||
expanderColumnWidth,
|
||||
SubComponent
|
||||
SubComponent,
|
||||
page,
|
||||
pages,
|
||||
pageSize
|
||||
} = this.getResolvedState(nextProps, nextState)
|
||||
|
||||
// Determine Header Groups
|
||||
@@ -212,29 +215,29 @@ export default {
|
||||
resolvedData = groupRecursively(resolvedData, pivotBy)
|
||||
}
|
||||
|
||||
const newPages = _.getFirstDefined(pages, Math.ceil(resolvedData.length / pageSize))
|
||||
const newPage = page > newPages ? newPage - 1 : page
|
||||
|
||||
return {
|
||||
resolvedData,
|
||||
pivotColumn,
|
||||
allVisibleColumns,
|
||||
headerGroups,
|
||||
allDecoratedColumns,
|
||||
hasHeaderGroups
|
||||
hasHeaderGroups,
|
||||
page: Math.max(newPage, 0)
|
||||
}
|
||||
},
|
||||
getSortedData (nextProps, nextState) {
|
||||
getSortedData (resolvedState) {
|
||||
const {
|
||||
manual,
|
||||
sorting,
|
||||
allDecoratedColumns,
|
||||
resolvedData
|
||||
} = this.getResolvedState(nextProps, nextState)
|
||||
|
||||
const resolvedSorting = sorting.length ? sorting : this.getInitSorting(allDecoratedColumns)
|
||||
} = resolvedState
|
||||
|
||||
// Resolve the data from either manual data or sorted data
|
||||
return {
|
||||
resolvedSorting,
|
||||
sortedData: manual ? resolvedData : this.sortData(resolvedData, resolvedSorting)
|
||||
sortedData: manual ? resolvedData : this.sortData(resolvedData, sorting)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -247,27 +250,10 @@ export default {
|
||||
getStateOrProp (key) {
|
||||
return _.getFirstDefined(this.state[key], this.props[key])
|
||||
},
|
||||
getInitSorting (columns) {
|
||||
if (!columns) {
|
||||
return []
|
||||
}
|
||||
const initSorting = columns.filter(d => {
|
||||
return typeof d.sort !== 'undefined'
|
||||
}).map(d => {
|
||||
return {
|
||||
id: d.id,
|
||||
asc: d.sort === 'asc'
|
||||
}
|
||||
})
|
||||
|
||||
return initSorting
|
||||
|
||||
// return initSorting.length ? initSorting : [{
|
||||
// id: columns.find(d => d.id).id,
|
||||
// asc: true
|
||||
// }]
|
||||
},
|
||||
sortData (data, sorting) {
|
||||
if (!sorting.length) {
|
||||
return data
|
||||
}
|
||||
const sorted = _.orderBy(data, sorting.map(sort => {
|
||||
return row => {
|
||||
if (row[sort.id] === null || row[sort.id] === undefined) {
|
||||
@@ -275,7 +261,7 @@ export default {
|
||||
}
|
||||
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id]
|
||||
}
|
||||
}), sorting.map(d => d.asc ? 'asc' : 'desc'))
|
||||
}), sorting.map(d => !d.desc))
|
||||
|
||||
return sorted.map(row => {
|
||||
if (!row[this.props.subRowsKey]) {
|
||||
@@ -330,54 +316,25 @@ export default {
|
||||
if (onSortingChange) {
|
||||
return onSortingChange(column, additive)
|
||||
}
|
||||
let newSorting = _.clone(sorting || [])
|
||||
if (_.isArray(column)) {
|
||||
const existingIndex = newSorting.findIndex(d => d.id === column[0].id)
|
||||
if (existingIndex > -1) {
|
||||
const existing = newSorting[existingIndex]
|
||||
if (existing.asc) {
|
||||
column.forEach((d, i) => {
|
||||
newSorting[existingIndex + i].asc = false
|
||||
})
|
||||
} else {
|
||||
if (additive) {
|
||||
newSorting.splice(existingIndex, column.length)
|
||||
} else {
|
||||
column.forEach((d, i) => {
|
||||
newSorting[existingIndex + i].asc = true
|
||||
})
|
||||
}
|
||||
}
|
||||
if (!additive) {
|
||||
newSorting = newSorting.slice(existingIndex, column.length)
|
||||
}
|
||||
} else {
|
||||
if (additive) {
|
||||
newSorting = newSorting.concat(column.map(d => ({
|
||||
id: d.id,
|
||||
asc: true
|
||||
})))
|
||||
} else {
|
||||
newSorting = column.map(d => ({
|
||||
id: d.id,
|
||||
asc: true
|
||||
}))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let newSorting = _.clone(sorting || []).map(d => {
|
||||
d.desc = _.isSortingDesc(d)
|
||||
return d
|
||||
})
|
||||
if (!_.isArray(column)) {
|
||||
// Single-Sort
|
||||
const existingIndex = newSorting.findIndex(d => d.id === column.id)
|
||||
if (existingIndex > -1) {
|
||||
const existing = newSorting[existingIndex]
|
||||
if (existing.asc) {
|
||||
existing.asc = false
|
||||
if (!additive) {
|
||||
newSorting = [existing]
|
||||
}
|
||||
} else {
|
||||
if (existing.desc) {
|
||||
if (additive) {
|
||||
newSorting.splice(existingIndex, 1)
|
||||
} else {
|
||||
existing.asc = true
|
||||
existing.desc = false
|
||||
newSorting = [existing]
|
||||
}
|
||||
} else {
|
||||
existing.desc = true
|
||||
if (!additive) {
|
||||
newSorting = [existing]
|
||||
}
|
||||
}
|
||||
@@ -385,15 +342,51 @@ export default {
|
||||
if (additive) {
|
||||
newSorting.push({
|
||||
id: column.id,
|
||||
asc: true
|
||||
desc: false
|
||||
})
|
||||
} else {
|
||||
newSorting = [{
|
||||
id: column.id,
|
||||
asc: true
|
||||
desc: false
|
||||
}]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Multi-Sort
|
||||
const existingIndex = newSorting.findIndex(d => d.id === column[0].id)
|
||||
// Existing Sorted Column
|
||||
if (existingIndex > -1) {
|
||||
const existing = newSorting[existingIndex]
|
||||
if (existing.desc) {
|
||||
if (additive) {
|
||||
newSorting.splice(existingIndex, column.length)
|
||||
} else {
|
||||
column.forEach((d, i) => {
|
||||
newSorting[existingIndex + i].desc = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
column.forEach((d, i) => {
|
||||
newSorting[existingIndex + i].desc = true
|
||||
})
|
||||
}
|
||||
if (!additive) {
|
||||
newSorting = newSorting.slice(existingIndex, column.length)
|
||||
}
|
||||
} else {
|
||||
// New Sort Column
|
||||
if (additive) {
|
||||
newSorting = newSorting.concat(column.map(d => ({
|
||||
id: d.id,
|
||||
desc: false
|
||||
})))
|
||||
} else {
|
||||
newSorting = column.map(d => ({
|
||||
id: d.id,
|
||||
desc: false
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setStateWithData({
|
||||
page: ((!sorting.length && newSorting.length) || !additive) ? 0 : this.state.page,
|
||||
|
||||
+88
-44
@@ -18,6 +18,10 @@ export const ReactTableDefaults = {
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: false,
|
||||
collapseOnPageChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
defaultSorting: [],
|
||||
|
||||
// Controlled State Overrides
|
||||
// page: undefined,
|
||||
@@ -66,6 +70,7 @@ export const ReactTableDefaults = {
|
||||
getTdProps: emptyObj,
|
||||
getPaginationProps: emptyObj,
|
||||
getLoadingProps: emptyObj,
|
||||
getNoDataProps: emptyObj,
|
||||
|
||||
// Global Column Defaults
|
||||
column: {
|
||||
@@ -88,6 +93,7 @@ export const ReactTableDefaults = {
|
||||
previousText: 'Previous',
|
||||
nextText: 'Next',
|
||||
loadingText: 'Loading...',
|
||||
noDataText: 'No rows found',
|
||||
pageText: 'Page',
|
||||
ofText: 'of',
|
||||
rowsText: 'rows',
|
||||
@@ -135,7 +141,8 @@ export const ReactTableDefaults = {
|
||||
{loadingText}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
),
|
||||
NoDataComponent: _.makeTemplateComponent('rt-noData')
|
||||
}
|
||||
|
||||
export default React.createClass({
|
||||
@@ -147,17 +154,17 @@ export default React.createClass({
|
||||
return {
|
||||
page: 0,
|
||||
pageSize: this.props.defaultPageSize || 10,
|
||||
sorting: [],
|
||||
sorting: this.props.defaultSorting,
|
||||
expandedRows: {}
|
||||
}
|
||||
},
|
||||
|
||||
getResolvedState (props, state) {
|
||||
const resolvedState = {
|
||||
...this.state,
|
||||
...state,
|
||||
...this.props,
|
||||
...props
|
||||
..._.compactObject(this.state),
|
||||
..._.compactObject(state),
|
||||
..._.compactObject(this.props),
|
||||
..._.compactObject(props)
|
||||
}
|
||||
return resolvedState
|
||||
},
|
||||
@@ -173,6 +180,7 @@ export default React.createClass({
|
||||
componentWillReceiveProps (nextProps, nextState) {
|
||||
const oldState = this.getResolvedState()
|
||||
const newState = this.getResolvedState(nextProps, nextState)
|
||||
|
||||
// Props that trigger a data update
|
||||
if (
|
||||
oldState.data !== newState.data ||
|
||||
@@ -187,22 +195,53 @@ export default React.createClass({
|
||||
setStateWithData (newState, cb) {
|
||||
const oldState = this.getResolvedState()
|
||||
const newResolvedState = this.getResolvedState({}, newState)
|
||||
if (
|
||||
oldState.resolvedData !== newResolvedState.resolvedData ||
|
||||
oldState.sorting !== newResolvedState.sorting
|
||||
) {
|
||||
Object.assign(newState, this.getSortedData({}, 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.expandedRows)
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
if (newResolvedState.expandedRows[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.sorting !== newResolvedState.sorting ||
|
||||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData)
|
||||
) {
|
||||
// Handle collapseOnSortingChange & collapseOnPageChange
|
||||
if (
|
||||
(oldState.sorting !== newResolvedState.sorting && this.props.collapseOnSortingChange) ||
|
||||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnPageChange)
|
||||
) {
|
||||
newResolvedState.expandedRows = {}
|
||||
}
|
||||
|
||||
Object.assign(newResolvedState, this.getSortedData(newResolvedState))
|
||||
}
|
||||
|
||||
// Calculate pageSize all the time
|
||||
if (newResolvedState.resolvedData) {
|
||||
newState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.resolvedData.length / newResolvedState.pageSize)
|
||||
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.resolvedData.length / newResolvedState.pageSize)
|
||||
}
|
||||
return this.setState(newState, cb)
|
||||
|
||||
return this.setState(newResolvedState, cb)
|
||||
},
|
||||
|
||||
shouldComponentUpdate (nextProps, nextState) {
|
||||
const oldState = this.getResolvedState()
|
||||
const newState = this.getResolvedState(nextProps, nextState)
|
||||
|
||||
// State changes that trigger a render
|
||||
if (
|
||||
oldState.sortedData !== newState.sortedData ||
|
||||
@@ -236,15 +275,17 @@ export default React.createClass({
|
||||
getTdProps,
|
||||
getPaginationProps,
|
||||
getLoadingProps,
|
||||
getNoDataProps,
|
||||
showPagination,
|
||||
expanderColumnWidth,
|
||||
manual,
|
||||
loadingText,
|
||||
noDataText,
|
||||
// State
|
||||
loading,
|
||||
pageSize,
|
||||
page,
|
||||
resolvedSorting,
|
||||
sorting,
|
||||
pages,
|
||||
// Pivoting State
|
||||
pivotValKey,
|
||||
@@ -263,6 +304,7 @@ export default React.createClass({
|
||||
PaginationComponent,
|
||||
LoadingComponent,
|
||||
SubComponent,
|
||||
NoDataComponent,
|
||||
// Data model
|
||||
resolvedData,
|
||||
allVisibleColumns,
|
||||
@@ -376,6 +418,7 @@ export default React.createClass({
|
||||
if (column.pivotColumns) {
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-pivot-header',
|
||||
classes
|
||||
@@ -390,6 +433,7 @@ export default React.createClass({
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
classes
|
||||
@@ -415,12 +459,10 @@ export default React.createClass({
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={sortedData}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
{_.normalizeComponent(column.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
@@ -449,7 +491,7 @@ export default React.createClass({
|
||||
}
|
||||
|
||||
const makeHeader = (column, i) => {
|
||||
const sort = resolvedSorting.find(d => d.id === column.id)
|
||||
const sort = sorting.find(d => d.id === column.id)
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
@@ -475,7 +517,7 @@ export default React.createClass({
|
||||
|
||||
if (column.expander) {
|
||||
if (column.pivotColumns) {
|
||||
const pivotSort = resolvedSorting.find(d => d.id === column.id)
|
||||
const pivotSort = sorting.find(d => d.id === column.id)
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
@@ -483,7 +525,7 @@ export default React.createClass({
|
||||
'rt-pivot-header',
|
||||
column.sortable && '-cursor-pointer',
|
||||
classes,
|
||||
pivotSort ? (pivotSort.asc ? '-sort-asc' : '-sort-desc') : ''
|
||||
pivotSort ? (pivotSort.desc ? '-sort-asc' : '-sort-desc') : ''
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
@@ -499,12 +541,10 @@ export default React.createClass({
|
||||
{column.pivotColumns.map((pivotColumn, i) => {
|
||||
return (
|
||||
<span key={pivotColumn.id}>
|
||||
{typeof pivotColumn.header === 'function' ? (
|
||||
<pivotColumn.header
|
||||
data={sortedData}
|
||||
column={pivotColumn}
|
||||
/>
|
||||
) : pivotColumn.header}
|
||||
{_.normalizeComponent(pivotColumn.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
{i < column.pivotColumns.length - 1 && (
|
||||
<ExpanderComponent />
|
||||
)}
|
||||
@@ -536,7 +576,7 @@ export default React.createClass({
|
||||
key={i}
|
||||
className={classnames(
|
||||
classes,
|
||||
sort ? (sort.asc ? '-sort-asc' : '-sort-desc') : '',
|
||||
sort ? (sort.desc ? '-sort-asc' : '-sort-desc') : '',
|
||||
column.sortable && '-cursor-pointer',
|
||||
!show && '-hidden',
|
||||
)}
|
||||
@@ -551,12 +591,10 @@ export default React.createClass({
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={sortedData}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
{_.normalizeComponent(column.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
@@ -589,7 +627,6 @@ export default React.createClass({
|
||||
{...trProps.rest}
|
||||
>
|
||||
{allVisibleColumns.map((column, i2) => {
|
||||
const Cell = column.render
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
@@ -629,6 +666,7 @@ export default React.createClass({
|
||||
const PivotCell = column.pivotRender
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(
|
||||
'rt-pivot',
|
||||
classes
|
||||
@@ -669,6 +707,7 @@ export default React.createClass({
|
||||
// Return the regular expander cell
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(
|
||||
classes,
|
||||
{hidden: !show}
|
||||
@@ -705,13 +744,10 @@ export default React.createClass({
|
||||
}}
|
||||
{...tdProps.rest}
|
||||
>
|
||||
{typeof Cell === 'function' ? (
|
||||
<Cell
|
||||
{...rowInfo}
|
||||
value={rowInfo.rowValues[column.id]}
|
||||
/>
|
||||
) : typeof Cell !== 'undefined' ? Cell
|
||||
: rowInfo.rowValues[column.id]}
|
||||
{_.normalizeComponent(column.render, {
|
||||
...rowInfo,
|
||||
value: rowInfo.rowValues[column.id]
|
||||
}, rowInfo.rowValues[column.id])}
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
@@ -805,6 +841,7 @@ export default React.createClass({
|
||||
const tBodyProps = _.splitProps(getTbodyProps(finalState, undefined, undefined, this))
|
||||
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
|
||||
const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
|
||||
const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
|
||||
return (
|
||||
<div
|
||||
className={classnames(
|
||||
@@ -850,6 +887,13 @@ export default React.createClass({
|
||||
{...paginationProps.rest}
|
||||
/>
|
||||
)}
|
||||
{!pageRows.length && (
|
||||
<NoDataComponent
|
||||
{...noDataProps}
|
||||
>
|
||||
{_.normalizeComponent(noDataText)}
|
||||
</NoDataComponent>
|
||||
)}
|
||||
<LoadingComponent
|
||||
loading={loading}
|
||||
loadingText={loadingText}
|
||||
|
||||
@@ -170,6 +170,18 @@ $expandSize = 7px
|
||||
.-pageSizeOptions
|
||||
margin: 3px 10px
|
||||
|
||||
.rt-noData
|
||||
display:block
|
||||
position:absolute
|
||||
left:50%
|
||||
top:50%
|
||||
transform: translate(-50%, -50%)
|
||||
background: alpha(white, .8)
|
||||
transition: all .3s ease
|
||||
z-index: 1
|
||||
pointer-events: none
|
||||
padding: 20px
|
||||
color: alpha(black, .5)
|
||||
|
||||
.-loading
|
||||
display:block
|
||||
|
||||
+28
-1
@@ -15,7 +15,10 @@ export default {
|
||||
makeTemplateComponent,
|
||||
groupBy,
|
||||
isArray,
|
||||
splitProps
|
||||
splitProps,
|
||||
compactObject,
|
||||
isSortingDesc,
|
||||
normalizeComponent
|
||||
}
|
||||
|
||||
function get (obj, path, def) {
|
||||
@@ -173,3 +176,27 @@ function splitProps ({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') {
|
||||
newObj[key] = obj[key]
|
||||
}
|
||||
}
|
||||
return newObj
|
||||
}
|
||||
|
||||
function isSortingDesc (d) {
|
||||
return !!(d.sort === 'desc' || d.desc === true || d.asc === false)
|
||||
}
|
||||
|
||||
function normalizeComponent (Comp, params, fallback = Comp) {
|
||||
return typeof Comp === 'function' ? (
|
||||
Comp.prototype.isReactComponent ? (
|
||||
<Comp
|
||||
{...params}
|
||||
/>
|
||||
) : Comp(params)
|
||||
) : fallback
|
||||
}
|
||||
|
||||
@@ -34,12 +34,24 @@ export default () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<strong>Hey!</strong> Open your console! :)
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
getTdProps={(state, rowInfo, column, instance) => {
|
||||
return {
|
||||
onMouseEnter: e => console.log('Cell - onMouseEnter', {
|
||||
state,
|
||||
rowInfo,
|
||||
column,
|
||||
instance,
|
||||
event: e
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
@@ -53,9 +65,6 @@ export default () => {
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
// Create some column definitions
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
@@ -74,12 +83,23 @@ const columns = [{
|
||||
}]
|
||||
}]
|
||||
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
getTdProps={(state, rowInfo, column, instance) => {
|
||||
return {
|
||||
onMouseEnter: e => console.log('Cell - onMouseEnter', {
|
||||
state,
|
||||
rowInfo,
|
||||
column,
|
||||
instance,
|
||||
event: e
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
`
|
||||
|
||||
@@ -79,8 +79,6 @@ const columns = [{
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
expander: true
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
@@ -91,6 +89,8 @@ const columns = [{
|
||||
return <span>{row.aggregated ? \`$\{row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
expander: true
|
||||
}]
|
||||
|
||||
return (
|
||||
@@ -100,7 +100,6 @@ return (
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
SubComponent={() => <span>Hello</span>}
|
||||
pivotBy={['lastName']}
|
||||
/>
|
||||
)
|
||||
`
|
||||
|
||||
+32
-28
@@ -28,8 +28,7 @@ export default () => {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
sort: 'desc'
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
@@ -41,6 +40,10 @@ export default () => {
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
defaultSorting={[{
|
||||
id: 'age',
|
||||
desc: true
|
||||
}]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
@@ -54,34 +57,35 @@ export default () => {
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
// Create some column definitions
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
)
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
defaultSorting={[{
|
||||
id: 'age',
|
||||
desc: true
|
||||
}]}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../src/index'
|
||||
|
||||
export default () => {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
lastName: namor.generate({ words: 1, numLen: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
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'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={[]}
|
||||
noDataText='Oh Noes!'
|
||||
// noDataText={() => 'Oh Noes!'} // Supports functions
|
||||
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
// Create some column definitions
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
data={[]}
|
||||
noDataText='Oh Noes!'
|
||||
// noDataText={() => 'Oh Noes!'} // Supports functions
|
||||
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
@@ -100,15 +100,24 @@ const columns = [{
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
|
||||
+12
-31
@@ -50,12 +50,6 @@ export default () => {
|
||||
className='-striped -highlight'
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
// expandedRows={{
|
||||
// 2: true,
|
||||
// 3: {
|
||||
// 2: true
|
||||
// }
|
||||
// }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
@@ -83,38 +77,25 @@ const columns = [{
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
className='-striped -highlight'
|
||||
defaultPageSize={10}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>You can put any component you want here, even another React Table!</em>
|
||||
<br />
|
||||
<br />
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={3}
|
||||
showPagination={false}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>It even has access to the row data: </em>
|
||||
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
/>
|
||||
)
|
||||
`
|
||||
|
||||
@@ -100,15 +100,24 @@ const columns = [{
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
|
||||
@@ -125,4 +125,4 @@ export default (
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -2998,7 +2998,7 @@ indexof@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
|
||||
|
||||
inflight@^1.0.4:
|
||||
inflight@^1.0.4, inflight@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
dependencies:
|
||||
@@ -5248,6 +5248,10 @@ standard@^8.0.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
|
||||
|
||||
storybook@^0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/storybook/-/storybook-0.0.0.tgz#b3b9508fb99fd83615674917583cfe9e1532931d"
|
||||
|
||||
stream-browserify@^2.0.0, stream-browserify@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
|
||||
|
||||
Reference in New Issue
Block a user