Compare commits

..
5 Commits
Author SHA1 Message Date
Tanner Linsley e059ceec75 4.1.1 2017-01-13 09:42:16 -07:00
Tanner Linsley 09f425aeb3 Redux package size to 5kb 2017-01-13 09:42:07 -07:00
Tanner Linsley ca038e9a69 4.1.0 2017-01-12 11:06:20 -07:00
Tanner Linsley 75c31b9354 Fully controlled component props and callbacks + docs 2017-01-12 11:06:09 -07:00
Tanner Linsley 4b2fa4e47d ignore react-storybook in testing 2017-01-11 20:04:32 -07:00
7 changed files with 143 additions and 88 deletions
+33 -2
View File
@@ -30,6 +30,7 @@
- [Header Groups](#header-groups)
- [Sub Tables & Components](#sub-tables-components)
- [Server-side Data](#server-side-data)
- [Fully Controlled Component](#fully-controlled-component)
- [Multi-sort](#multi-sort)
- [Component Overrides](#component-overrides)
@@ -123,11 +124,15 @@ These are all of the available props (and their default values) for the main `<R
tdStyle: {}, // style object for the `td` component
paginationStyle: {}, // style object for the `paginination` component
// Controlled State (see Using as a Fully Controlled Component below)
// Controlled Props (see Using as a Fully Controlled Component below)
page: undefined,
pageSize: undefined,
sorting: undefined,
visibleSubComponents: undefined
visibleSubComponents: undefined,
// Controlled Callbacks
onExpand: undefined,
onPageChange: undefined,
onPageSizeChange: undefined,
}
```
@@ -266,6 +271,32 @@ If you want to handle pagination, and sorting on the server, `react-table` makes
For a detailed example, take a peek at our [async table mockup](https://github.com/tannerlinsley/react-table/blob/master/example/src/screens/async.js)
## Fully Controlled Component
React Table by default works fantastically out of the box, but you can achieve even more control and customization if you choose to maintain the state yourself. It is very easy to do, even if you only want to manage *parts* of the state.
Here are the props and their corresponding callbacks that control the state of the a table:
```javascript
<ReactTable
// Props
page={0} // the index of the page you wish to display
pageSize={20} // the number of rows per page to be displayed
sorting={[{
id: 'lastName',
asc: true
}, {
id: 'firstName',
asc: true
}]} // the sorting model for the table
visibleSubComponents={[1,4,5]} // The row indexes on the current page that should appear expanded
// Callbacks
onPageChange={(pageIndex) => {...}} // Called when the page index is changed by the user
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data
onSortingChange={(column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held.
onExpand={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `visibleSubComponents`
/>
```
## 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!
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "4.0.1",
"version": "4.1.1",
"description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -35,8 +35,7 @@
"deploy": "build-storybook && zab deploy"
},
"dependencies": {
"classnames": "^2.2.5",
"inline-style-prefixer": "^2.0.5"
"classnames": "^2.2.5"
},
"peerDependencies": {
"react": "^15.x.x"
@@ -73,7 +72,8 @@
"dist",
"lib",
"example",
"react-table.js"
"react-table.js",
"stories"
]
},
"babel": {
+65 -52
View File
@@ -1,6 +1,5 @@
import React from 'react'
import classnames from 'classnames'
import prefixAll from 'inline-style-prefixer/static'
//
import _ from './utils'
@@ -17,13 +16,19 @@ export const ReactTableDefaults = {
showPageJump: true,
expanderColumnWidth: 30,
// State Overrides (for controlled-component style)
// Controlled State Overrides
// page
// pageSize
// sorting
// visibleSubComponents
// Callbacks
// Controlled State Callbacks
onExpand: undefined,
onPageChange: undefined,
onPageSizeChange: undefined,
onSortingChange: undefined,
// General Callbacks
onChange: () => null,
onTrClick: () => null,
// Classes
@@ -86,17 +91,17 @@ export const ReactTableDefaults = {
)
},
TdComponent: _.makeTemplateComponent('rt-td'),
ExpanderComponent: ({isOpen, toggle, ...rest}) => {
ExpanderComponent: ({isExpanded, toggle, ...rest}) => {
return (
<div
className={classnames('rt-expander', isOpen && '-open')}
className={classnames('rt-expander', isExpanded && '-open')}
{...rest}
/>
)
},
PaginationComponent: Pagination,
PreviousComponent: null,
NextComponent: null,
PreviousComponent: undefined,
NextComponent: undefined,
LoadingComponent: ({loading, loadingText}) => (
<div className={classnames('-loading', {'-active': loading})}>
<div className='-loading-inner'>
@@ -116,7 +121,7 @@ export default React.createClass({
page: 0,
pageSize: this.props.defaultPageSize || 10,
sorting: false,
visibleSubComponents: {}
visibleSubComponents: []
}
},
@@ -125,6 +130,7 @@ export default React.createClass({
},
render () {
const resolvedProps = this.getResolvedState()
const {
className,
style,
@@ -146,18 +152,11 @@ export default React.createClass({
trStyleCallback,
tdStyle,
showPagination,
showPageSizeOptions,
pageSizeOptions,
showPageJump,
previousText,
nextText,
pageText,
ofText,
rowsText,
paginationClassName,
expanderColumnWidth,
manual,
loadingText,
onExpand,
// State
visibleSubComponents,
loading,
@@ -173,11 +172,9 @@ export default React.createClass({
TdComponent,
ExpanderComponent,
PaginationComponent,
PreviousComponent,
NextComponent,
LoadingComponent,
SubComponent
} = this.getResolvedState()
} = resolvedProps
// Build Columns
const decoratedColumns = []
@@ -279,7 +276,7 @@ export default React.createClass({
{SubComponent && (
<ThComponent
className={classnames(thClassname, 'rt-expander-header')}
style={prefixAll({
style={_.prefixAll({
flex: `0 0 auto`,
width: `${expanderColumnWidth}px`
})}
@@ -290,7 +287,7 @@ export default React.createClass({
<ThComponent
key={i}
className={classnames(thClassname, column.headerClassName)}
style={Object.assign({}, thStyle, column.headerStyle, prefixAll({
style={Object.assign({}, thStyle, column.headerStyle, _.prefixAll({
flex: `${column.columns.length * columnPercentage} 0 auto`,
width: `${_.sum(column.columns.map(d => d.minWidth))}px`
}))}
@@ -320,7 +317,7 @@ export default React.createClass({
{SubComponent && (
<ThComponent
className={classnames(thClassname, 'rt-expander-header')}
style={prefixAll({
style={_.prefixAll({
flex: `0 0 auto`,
width: `${expanderColumnWidth}px`
})}
@@ -341,7 +338,7 @@ export default React.createClass({
'-hidden': !show
}
)}
style={Object.assign({}, thStyle, column.headerStyle, prefixAll({
style={Object.assign({}, thStyle, column.headerStyle, _.prefixAll({
flex: `${columnPercentage} 0 auto`,
width: `${column.minWidth}px`
}))}
@@ -373,6 +370,8 @@ export default React.createClass({
index: row.__index,
viewIndex: i
}
const visibleSubComponentIndex = visibleSubComponents.indexOf(i)
const isExpanded = visibleSubComponentIndex > -1
return (
<TrGroupComponent key={i}>
<TrComponent
@@ -383,21 +382,32 @@ export default React.createClass({
{SubComponent && (
<ThComponent
className={classnames(thClassname, 'rt-expander-wrap')}
style={prefixAll({
style={_.prefixAll({
flex: `0 0 auto`,
width: `${expanderColumnWidth}px`
})}
onClick={() => {
onClick={(e) => {
if (onExpand) {
return onExpand(i, e)
}
if (isExpanded) {
return this.setState({
visibleSubComponents: [
...visibleSubComponents.slice(0, visibleSubComponentIndex - 1),
...visibleSubComponents.slice(visibleSubComponentIndex + 1)
]
})
}
this.setState({
visibleSubComponents: {
...visibleSubComponents,
[i]: !visibleSubComponents[i]
}
visibleSubComponents: [
...visibleSubComponents,
i
]
})
}}
>
<ExpanderComponent
isOpen={visibleSubComponents[i]}
isExpanded={isExpanded}
/>
</ThComponent>
)}
@@ -408,7 +418,7 @@ export default React.createClass({
<TdComponent
key={i2}
className={classnames(column.className, {hidden: !show})}
style={Object.assign({}, tdStyle, column.style, prefixAll({
style={Object.assign({}, tdStyle, column.style, _.prefixAll({
flex: `${columnPercentage} 0 auto`,
width: `${column.minWidth}px`
}))}
@@ -424,7 +434,7 @@ export default React.createClass({
)
})}
</TrComponent>
{SubComponent && visibleSubComponents[i] ? (
{SubComponent && isExpanded ? (
SubComponent(rowInfo)
) : null}
</TrGroupComponent>
@@ -440,7 +450,7 @@ export default React.createClass({
{SubComponent && (
<ThComponent
className={classnames(thClassname, 'rt-expander-header')}
style={prefixAll({
style={_.prefixAll({
flex: `0 0 auto`,
width: `${expanderColumnWidth}px`
})}
@@ -468,25 +478,12 @@ export default React.createClass({
</TableComponent>
{showPagination && (
<PaginationComponent
page={page}
{...resolvedProps}
pagesLength={pagesLength}
pageSize={pageSize}
showPageSizeOptions={showPageSizeOptions}
pageSizeOptions={pageSizeOptions}
showPageJump={showPageJump}
canPrevious={canPrevious}
canNext={canNext}
previousText={previousText}
nextText={nextText}
pageText={pageText}
ofText={ofText}
rowsText={rowsText}
previousComponent={PreviousComponent}
nextComponent={NextComponent}
//
onChange={this.setPage}
onPageSizeChange={this.setPageSize}
//
onPageChange={this.onPageChange}
onPageSizeChange={this.onPageSizeChange}
className={paginationClassName}
/>
)}
@@ -577,18 +574,30 @@ export default React.createClass({
},
// User actions
setPage (page) {
onPageChange (page) {
const { onPageChange } = this.props
if (onPageChange) {
return onPageChange(page)
}
this.setState({
visibleSubComponents: {},
visibleSubComponents: [],
page
}, () => {
this.fireOnChange()
})
},
setPageSize (newPageSize) {
onPageSizeChange (newPageSize) {
const { onPageSizeChange } = this.props
const { pageSize, page } = this.getResolvedState()
// Normalize the page to display
const currentRow = pageSize * page
const newPage = Math.floor(currentRow / pageSize)
if (onPageSizeChange) {
return onPageSizeChange(newPageSize, newPage)
}
this.setState({
pageSize: newPageSize,
page: newPage
@@ -597,6 +606,10 @@ export default React.createClass({
})
},
sortColumn (column, additive) {
const { onSortingChange } = this.props
if (onSortingChange) {
return onSortingChange(column, additive)
}
const existingSorting = this.getSorting()
let sorting = _.clone(this.state.sorting || [])
const existingIndex = sorting.findIndex(d => d.id === column.id)
+7 -6
View File
@@ -22,7 +22,7 @@ export default React.createClass({
changePage (page) {
page = this.getSafePage(page)
this.setState({page})
this.props.onChange(page)
this.props.onPageChange(page)
},
applyPage (e) {
e && e.preventDefault()
@@ -31,8 +31,10 @@ export default React.createClass({
},
render () {
const {
page,
// Computed
pagesLength,
// Props
page,
showPageSizeOptions,
pageSizeOptions,
pageSize,
@@ -40,12 +42,11 @@ export default React.createClass({
canPrevious,
canNext,
onPageSizeChange,
className
className,
PreviousComponent = defaultButton,
NextComponent = defaultButton
} = this.props
const PreviousComponent = this.props.previousComponent || defaultButton
const NextComponent = this.props.nextComponent || defaultButton
return (
<div
className={classnames(className, '-pagination')}
+6 -1
View File
@@ -11,7 +11,8 @@ export default {
remove,
getFirstDefined,
sum,
makeTemplateComponent
makeTemplateComponent,
prefixAll
}
function remove (a, b) {
@@ -115,3 +116,7 @@ function makeTemplateComponent (compClass) {
</div>
)
}
function prefixAll (obj) {
return obj
}
+28 -8
View File
@@ -39,19 +39,21 @@ export default () => {
data={data}
columns={columns}
defaultPageSize={10}
subComponent={(row) => {
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!. It has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
subComponent={(row) => {
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table! It even has access to the row data: </em>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
@@ -96,9 +98,27 @@ export default (
data={data}
columns={columns}
defaultPageSize={10}
subComponent={(row) => {
SubComponent={(row) => {
return (
<code><pre>{JSON.stringify(row, null, 2)}</pre></code>
<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>
)
}}
/>
-15
View File
@@ -1362,10 +1362,6 @@ boom@2.x.x:
dependencies:
hoek "2.x.x"
bowser@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.6.0.tgz#37fc387b616cb6aef370dab4d6bd402b74c5c54d"
brace-expansion@^1.0.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
@@ -3000,10 +2996,6 @@ https-browserify@~0.0.0, https-browserify@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
hyphenate-style-name@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
iconv-lite@^0.4.13, iconv-lite@~0.4.13:
version "0.4.15"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
@@ -3071,13 +3063,6 @@ inline-source-map@~0.6.0:
dependencies:
source-map "~0.5.3"
inline-style-prefixer:
version "2.0.5"
resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7"
dependencies:
bowser "^1.0.0"
hyphenate-style-name "^1.0.1"
inquirer@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"