mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f72fec3cc2 | ||
|
|
a8a0d1bab8 | ||
|
|
f06caec053 | ||
|
|
8fa7975ca5 | ||
|
|
e04a2dee69 | ||
|
|
e059ceec75 | ||
|
|
09f425aeb3 | ||
|
|
ca038e9a69 | ||
|
|
75c31b9354 | ||
|
|
4b2fa4e47d | ||
|
|
76e92de670 | ||
|
|
3c5ba2843d | ||
|
|
1cb280942d | ||
|
|
c8c650c729 |
@@ -13,6 +13,9 @@ import Readme from '../README.md'
|
||||
import Simple from '../stories/Simple.js'
|
||||
import ServerSide from '../stories/ServerSide.js'
|
||||
import SubComponents from '../stories/SubComponents.js'
|
||||
import Pivoting from '../stories/Pivoting.js'
|
||||
import PivotingSubComponents from '../stories/PivotingSubComponents.js'
|
||||
import MillionRows from '../stories/MillionRows.js'
|
||||
//
|
||||
configure(() => {
|
||||
storiesOf('1. Docs')
|
||||
@@ -31,4 +34,7 @@ configure(() => {
|
||||
.add('Client-side Data', Simple)
|
||||
.add('Server-side Data', ServerSide)
|
||||
.add('Sub Components', SubComponents)
|
||||
.add('Pivoting & Aggregation', Pivoting)
|
||||
.add('Pivoting & Aggregation w/ Sub Components', PivotingSubComponents)
|
||||
.add('1 Million Rows w/ Pivoting & Sub Components', MillionRows)
|
||||
}, module)
|
||||
|
||||
@@ -12,34 +12,36 @@
|
||||
|
||||
## Features
|
||||
|
||||
- Lightweight at 4kb (and just 2kb more for styles)
|
||||
- Fully customizable JSX and callbacks for everything
|
||||
- Supports both Client-side & Server-side pagination and sorting
|
||||
- Lightweight at 7kb (and just 2kb more for styles)
|
||||
- Fully customizable JSX templating
|
||||
- Supports both Client-side & Server-side pagination and multi-sorting
|
||||
- Column Pivoting & Aggregation
|
||||
- Minimal design & easily themeable
|
||||
- Fully controllable via optional props and callbacks
|
||||
- <a href="https://medium.com/@tannerlinsley/why-i-wrote-react-table-and-the-problems-it-has-solved-for-nozzle-others-445c4e93d4a8#.axza4ixba" target="\_blank">"Why I wrote React Table and the problems it has solved for Nozzle.io</a> by Tanner Linsley
|
||||
|
||||
## <a href="http://react-table.zabapps.com/?selectedKind=2.%20Demos&selectedStory=Client-side%20Data&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel" target="\_blank">Demo</a>
|
||||
|
||||
## Table of Contents
|
||||
- [Installation](#nstallation)
|
||||
- [Installation](#installation)
|
||||
- [Example](#example)
|
||||
- [Data](#data)
|
||||
- [Default Props](#default-props)
|
||||
- [Props](#props)
|
||||
- [Columns](#columns)
|
||||
- [Styles](#styles)
|
||||
- [Header Groups](#header-groups)
|
||||
- [Sub Tables & Components](#sub-tables--components)
|
||||
- [Pivoting & Aggregation](#pivoting-aggregation)
|
||||
- [Sub Tables & Sub Components](#sub-tables-sub-components)
|
||||
- [Server-side Data](#server-side-data)
|
||||
- [Fully Controlled Component](#fully-controlled-component)
|
||||
- [Multi-sort](#multi-sort)
|
||||
- [Component Overrides](#component-overrides)
|
||||
|
||||
<a name="installation"></a>
|
||||
## Installation
|
||||
```bash
|
||||
$ npm install react-table
|
||||
```
|
||||
|
||||
<a name="example"></a>
|
||||
## Example
|
||||
```javascript
|
||||
import ReactTable from 'react-table'
|
||||
@@ -76,19 +78,17 @@ const columns = [{
|
||||
/>
|
||||
```
|
||||
|
||||
<a name="data"></a>
|
||||
## Data
|
||||
Simply pass the `data` prop anything that resembles an array or object. Client-side filtering and pagination is built in, and your table will update gracefully as you change any props. [Server-side data](#server-side-data) is also supported!
|
||||
Simply pass the `data` prop anything that resembles an array or object. Client-side sorting and pagination are built in, and your table will update gracefully as you change any props. [Server-side data](#server-side-data) is also supported!
|
||||
|
||||
|
||||
<a name="default-props"></a>
|
||||
## Default Props
|
||||
These are the default props for the main react component `<ReactTable />`
|
||||
## Props
|
||||
These are all of the available props (and their default values) for the main `<ReactTable />` component.
|
||||
```javascript
|
||||
{
|
||||
// General
|
||||
loading: false, // Whether to show the loading overlay or not
|
||||
pageSize: 20, // The default page size (this can be changed by the user if `showPageSizeOptions` is enabled)
|
||||
defaultPageSize: 20, // The default page size (this can be changed by the user if `showPageSizeOptions` is enabled)
|
||||
minRows: 0, // Ensure this many rows are always rendered, regardless of rows on page
|
||||
showPagination: true, // Shows or hides the pagination component
|
||||
showPageJump: true, // Shows or hides the pagination number input
|
||||
@@ -115,6 +115,7 @@ These are the default props for the main react component `<ReactTable />`
|
||||
trClassName: '', // ClassName for all `tr` elements
|
||||
trClassCallback: row => null, // A call back to dynamically add classes (via the classnames module) to a row element
|
||||
paginationClassName: '' // ClassName for `pagination` element
|
||||
|
||||
// Styles
|
||||
style: {}, // Main style object for the component
|
||||
tableStyle: {}, // style object for the `table` component
|
||||
@@ -125,6 +126,16 @@ These are the default props for the main react component `<ReactTable />`
|
||||
thStyle: {}, // style object for the `th` component
|
||||
tdStyle: {}, // style object for the `td` component
|
||||
paginationStyle: {}, // style object for the `paginination` component
|
||||
|
||||
// Controlled Props (see Using as a Fully Controlled Component below)
|
||||
page: undefined,
|
||||
pageSize: undefined,
|
||||
sorting: undefined,
|
||||
expandedRows: undefined,
|
||||
// Controlled Callbacks
|
||||
onExpandRow: undefined,
|
||||
onPageChange: undefined,
|
||||
onPageSizeChange: undefined,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -134,7 +145,7 @@ You can easily override the core defaults like so:
|
||||
import { ReactTableDefaults } from 'react-table'
|
||||
|
||||
Object.assign(ReactTableDefaults, {
|
||||
pageSize: 10,
|
||||
defaultPageSize: 10,
|
||||
minRows: 3,
|
||||
// etc...
|
||||
})
|
||||
@@ -144,15 +155,14 @@ Or just define them on the component per-instance
|
||||
|
||||
```javascript
|
||||
<ReactTable
|
||||
pageSize={10}
|
||||
defaultPageSize={10}
|
||||
minRows={3}
|
||||
// etc...
|
||||
/>
|
||||
/>
|
||||
```
|
||||
|
||||
<a name="columns"></a>
|
||||
## Columns
|
||||
`<ReactTable/>` requires a `columns` prop, which is an array of objects with the following properties
|
||||
`<ReactTable/>` requires a `columns` prop, which is an array of objects containing the following properties
|
||||
|
||||
```javascript
|
||||
[{
|
||||
@@ -162,7 +172,7 @@ Or just define them on the component per-instance
|
||||
sortable: true,
|
||||
sort: 'asc' or 'desc', // used to determine the column sorting on init
|
||||
show: true, // can be used to hide a column
|
||||
minWidth: 100 // A minimum width for this column. If there is room, columns will flex to fill
|
||||
minWidth: 100 // A minimum width for this column. If there is room, columns will flex to fill available space
|
||||
|
||||
// Cell Options
|
||||
className: '', // Set the classname of the `td` element of the column
|
||||
@@ -185,11 +195,9 @@ Or just define them on the component per-instance
|
||||
}]
|
||||
```
|
||||
|
||||
<a name="styles"></a>
|
||||
## Styles
|
||||
React-table is built to be dropped into existing applications or styled from the ground up, but if you'd like a decent starting point, you can optionally include our default theme `react-table.css`. We think it looks great, honestly :)
|
||||
|
||||
<a name="header-groups"></a>
|
||||
## Header Groups
|
||||
To group columns with another header column, just nest your columns in a header column like so:
|
||||
```javascript
|
||||
@@ -208,14 +216,44 @@ const columns = [{
|
||||
}]
|
||||
```
|
||||
|
||||
## Sub Tables & Components
|
||||
By adding a `subComponent` props, you can easily add an expansion level to all root-level rows:
|
||||
## Pivoting & 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
|
||||
<ReactTable
|
||||
...
|
||||
pivotBy={['lastName', 'age']}
|
||||
/>
|
||||
```
|
||||
|
||||
Naturally when grouping rows together, you may want to aggregate the rows inside it into the grouped column. No aggregation is done by default, however, it is very simple to aggregate any pivoted columns:
|
||||
```javascript
|
||||
// In this example, we use lodash to sum and average the values, but you can use whatever you want to aggregate.
|
||||
const columns = [{
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: (values, rows) => _.round(_.mean(values)),
|
||||
render: row => {
|
||||
// You can even render the cell differently if it's an aggregated cell
|
||||
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
|
||||
}
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: (values, rows) => _.sum(values)
|
||||
}]
|
||||
```
|
||||
|
||||
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
|
||||
By adding a `SubComponent` props, you can easily add an expansion level to all root-level rows:
|
||||
```javascript
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
subComponent={(row) => {
|
||||
defaultPageSize={10}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div>
|
||||
You can put any component you want here, even another React Table! You even have access to the row-level data if you need! Spark-charts, drill-throughs, infographics... the possibilities are endless!
|
||||
@@ -226,7 +264,6 @@ By adding a `subComponent` props, you can easily add an expansion level to all r
|
||||
```
|
||||
|
||||
|
||||
<a name="server-side-data"></a>
|
||||
## Server-side Data
|
||||
If you want to handle pagination, and sorting on the server, `react-table` makes it easy on you.
|
||||
|
||||
@@ -267,38 +304,71 @@ 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)
|
||||
|
||||
<a name="multi-sort"></a>
|
||||
## 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
|
||||
expandedRows={{
|
||||
1: true,
|
||||
4: true,
|
||||
5: {
|
||||
2: true,
|
||||
3: true
|
||||
}
|
||||
}} // The nested 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. If the column is a pivoted column, `column` will be an array of columns
|
||||
onExpandRow={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
|
||||
/>
|
||||
```
|
||||
|
||||
## 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!
|
||||
|
||||
<a name="component-overrides"></a>
|
||||
## Component Overrides
|
||||
Though we wouldn't suggest it, `react-table` has the ability to change the core componentry it used to render it's table. You can do so by assigning a react component to it's corresponding global prop, or on a one-off basis like so:
|
||||
Though we confidently stand by the markup and architecture behind it, `react-table` does offer the ability to change the core componentry it uses to render everything. You can extend or override these internal components by passing a react component to it's corresponding prop on either the global props or on a one-off basis like so:
|
||||
```javascript
|
||||
// Change the global default
|
||||
import { ReactTableDefaults } from 'react-table'
|
||||
Object.assign(ReactTableDefaults, {
|
||||
tableComponent: Component,
|
||||
theadComponent: Component,
|
||||
tbodyComponent: Component,
|
||||
trComponent: Component,
|
||||
thComponent: Component,
|
||||
tdComponent: Component,
|
||||
paginationComponent: Component,
|
||||
previousComponent: Component,
|
||||
nextComponent: Component,
|
||||
loadingComponent: Component
|
||||
TableComponent: Component,
|
||||
TheadComponent: Component,
|
||||
TbodyComponent: Component,
|
||||
TrGroupComponent: Component,
|
||||
TrComponent: Component,
|
||||
ThComponent: Component,
|
||||
TdComponent: Component,
|
||||
PaginationComponent: Component,
|
||||
PreviousComponent: Component,
|
||||
NextComponent: Component,
|
||||
LoadingComponent: Component,
|
||||
ExpanderComponent: Component
|
||||
})
|
||||
|
||||
// Or change per instance
|
||||
<ReactTable
|
||||
tableComponent={Component},
|
||||
theadComponent={Component},
|
||||
TableComponent={Component},
|
||||
TheadComponent={Component},
|
||||
// etc...
|
||||
/>
|
||||
```
|
||||
|
||||
If you choose to change the core components React-Table uses to render, you must make sure your components support and utilized all of the neeeded features for that component to work properly. For a broad reference on how to do this, investigate [the source](https://github.com/tannerlinsley/react-table/blob/master/src/index.js) for the component you wish to replace.
|
||||
If you choose to change the core components React-Table uses to render, you must make sure your replacement components consume and utilize all of the supplied and inherited props that are needed for that component to function properly. We would suggest investigating [the source](https://github.com/tannerlinsley/react-table/blob/master/src/index.js) for the component you wish to replace.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "4.0.0",
|
||||
"version": "4.2.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": {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+793
-445
File diff suppressed because it is too large
Load Diff
+26
-18
@@ -56,6 +56,8 @@ $expandSize = 7px
|
||||
border-right:1px solid alpha(black, .02)
|
||||
&:last-child
|
||||
border-right:0
|
||||
.rt-pivot
|
||||
cursor: pointer
|
||||
.rt-tr-group
|
||||
display: flex
|
||||
flex-direction: column
|
||||
@@ -79,29 +81,35 @@ $expandSize = 7px
|
||||
border:0 !important
|
||||
opacity: 0 !important
|
||||
|
||||
.rt-expander-wrap
|
||||
display:flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
cursor: pointer
|
||||
|
||||
.rt-expander
|
||||
width: 0
|
||||
height: 0
|
||||
border-left: ($expandSize * .72) solid transparent
|
||||
border-right: ($expandSize * .72) solid transparent
|
||||
border-top: $expandSize solid alpha(black, .8)
|
||||
transition: all .3s $easeOutBack
|
||||
transform: rotate(-90deg)
|
||||
&.-open
|
||||
transform: rotate(0deg)
|
||||
display: inline-block
|
||||
position:relative
|
||||
margin: 0
|
||||
color: transparent
|
||||
margin: 0 10px
|
||||
&:after
|
||||
content: ''
|
||||
position: absolute
|
||||
width: 0
|
||||
height: 0
|
||||
top:50%
|
||||
left:50%
|
||||
transform: translate(-50%, -50%) rotate(-90deg)
|
||||
border-left: ($expandSize * .72) solid transparent
|
||||
border-right: ($expandSize * .72) solid transparent
|
||||
border-top: $expandSize solid alpha(black, .8)
|
||||
transition: all .3s $easeOutBack
|
||||
cursor: pointer
|
||||
&.-open:after
|
||||
transform: translate(-50%, -50%) rotate(0deg)
|
||||
|
||||
&.-striped
|
||||
.rt-tr-group:nth-child(even)
|
||||
.rt-tr.-odd
|
||||
background: alpha(black, .03)
|
||||
&.-highlight
|
||||
.rt-tr-group:hover
|
||||
background: alpha(black, .05)
|
||||
.rt-tbody
|
||||
.rt-tr:not(.-padRow):hover
|
||||
background: alpha(black, .05)
|
||||
|
||||
.-pagination
|
||||
z-index: 1
|
||||
|
||||
+17
-16
@@ -10,29 +10,31 @@ const defaultButton = (props) => (
|
||||
export default React.createClass({
|
||||
getInitialState () {
|
||||
return {
|
||||
page: this.props.currentPage
|
||||
page: this.props.page
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps (nextProps) {
|
||||
this.setState({page: nextProps.currentPage})
|
||||
this.setState({page: nextProps.page})
|
||||
},
|
||||
getSafePage (page) {
|
||||
return Math.min(Math.max(page, 0), this.props.pagesLength - 1)
|
||||
return Math.min(Math.max(page, 0), this.props.pages - 1)
|
||||
},
|
||||
changePage (page) {
|
||||
page = this.getSafePage(page)
|
||||
this.setState({page})
|
||||
this.props.onChange(page)
|
||||
this.props.onPageChange(page)
|
||||
},
|
||||
applyPage (e) {
|
||||
e && e.preventDefault()
|
||||
const page = this.state.page
|
||||
this.changePage(page === '' ? this.props.currentPage : page)
|
||||
this.changePage(page === '' ? this.props.page : page)
|
||||
},
|
||||
render () {
|
||||
const {
|
||||
currentPage,
|
||||
pagesLength,
|
||||
// Computed
|
||||
pages,
|
||||
// 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')}
|
||||
@@ -55,7 +56,7 @@ export default React.createClass({
|
||||
<PreviousComponent
|
||||
onClick={(e) => {
|
||||
if (!canPrevious) return
|
||||
this.changePage(currentPage - 1)
|
||||
this.changePage(page - 1)
|
||||
}}
|
||||
disabled={!canPrevious}
|
||||
>
|
||||
@@ -82,9 +83,9 @@ export default React.createClass({
|
||||
onBlur={this.applyPage}
|
||||
/>
|
||||
</form>
|
||||
) : (
|
||||
<span className='-currentPage'>{currentPage + 1}</span>
|
||||
)} {this.props.ofText} <span className='-totalPages'>{pagesLength}</span>
|
||||
) : (
|
||||
<span className='-currentPage'>{page + 1}</span>
|
||||
)} {this.props.ofText} <span className='-totalPages'>{pages}</span>
|
||||
</span>
|
||||
{showPageSizeOptions && (
|
||||
<span className='select-wrap -pageSizeOptions'>
|
||||
@@ -109,7 +110,7 @@ export default React.createClass({
|
||||
<NextComponent
|
||||
onClick={(e) => {
|
||||
if (!canNext) return
|
||||
this.changePage(currentPage + 1)
|
||||
this.changePage(page + 1)
|
||||
}}
|
||||
disabled={!canNext}
|
||||
>
|
||||
|
||||
+105
-38
@@ -1,38 +1,47 @@
|
||||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
//
|
||||
export default {
|
||||
get,
|
||||
set,
|
||||
takeRight,
|
||||
last,
|
||||
orderBy,
|
||||
sortBy,
|
||||
range,
|
||||
clone,
|
||||
remove,
|
||||
clone,
|
||||
getFirstDefined,
|
||||
sum
|
||||
sum,
|
||||
makeTemplateComponent,
|
||||
prefixAll,
|
||||
groupBy,
|
||||
isArray
|
||||
}
|
||||
|
||||
function remove (a, b) {
|
||||
return a.filter(function (o, i) {
|
||||
var r = b(o)
|
||||
if (r) {
|
||||
a.splice(i, 1)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
function get (a, b) {
|
||||
if (isArray(b)) {
|
||||
b = b.join('.')
|
||||
function get (obj, path, def) {
|
||||
if (!path) {
|
||||
return obj
|
||||
}
|
||||
return b
|
||||
.replace('[', '.').replace(']', '')
|
||||
.split('.')
|
||||
.reduce(
|
||||
function (obj, property) {
|
||||
return obj[property]
|
||||
}, a
|
||||
)
|
||||
const pathObj = makePathArray(path)
|
||||
let val
|
||||
try {
|
||||
val = pathObj.reduce((current, pathPart) => current[pathPart], obj)
|
||||
} catch (e) {}
|
||||
return typeof val !== 'undefined' ? val : def
|
||||
}
|
||||
|
||||
function set (obj = {}, path, value) {
|
||||
const keys = makePathArray(path)
|
||||
let keyPart
|
||||
let cursor = obj
|
||||
while ((keyPart = keys.shift()) && keys.length) {
|
||||
if (!cursor[keyPart]) {
|
||||
cursor[keyPart] = {}
|
||||
}
|
||||
cursor = cursor[keyPart]
|
||||
}
|
||||
cursor[keyPart] = value
|
||||
return obj
|
||||
}
|
||||
|
||||
function takeRight (arr, n) {
|
||||
@@ -52,7 +61,7 @@ function range (n) {
|
||||
return arr
|
||||
}
|
||||
|
||||
function orderBy (arr, funcs, dirs) {
|
||||
function sortBy (arr, funcs, dirs) {
|
||||
return arr.sort((a, b) => {
|
||||
for (let i = 0; i < funcs.length; i++) {
|
||||
const comp = funcs[i]
|
||||
@@ -70,21 +79,28 @@ function orderBy (arr, funcs, dirs) {
|
||||
})
|
||||
}
|
||||
|
||||
function clone (a) {
|
||||
return JSON.parse(JSON.stringify(a, function (key, value) {
|
||||
if (typeof value === 'function') {
|
||||
return value.toString()
|
||||
function remove (a, b) {
|
||||
return a.filter(function (o, i) {
|
||||
var r = b(o)
|
||||
if (r) {
|
||||
a.splice(i, 1)
|
||||
return true
|
||||
}
|
||||
return value
|
||||
}))
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// Helpers
|
||||
// ########################################################################
|
||||
|
||||
function isArray (a) {
|
||||
return Array.isArray(a)
|
||||
function clone (a) {
|
||||
try {
|
||||
return JSON.parse(JSON.stringify(a, (key, value) => {
|
||||
if (typeof value === 'function') {
|
||||
return value.toString()
|
||||
}
|
||||
return value
|
||||
}))
|
||||
} catch (e) {
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstDefined (...args) {
|
||||
@@ -100,3 +116,54 @@ function sum (arr) {
|
||||
return a + b
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function makeTemplateComponent (compClass) {
|
||||
return ({children, className, ...rest}) => (
|
||||
<div
|
||||
className={classnames(compClass, className)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function prefixAll (obj) {
|
||||
return obj
|
||||
}
|
||||
|
||||
function groupBy (xs, key) {
|
||||
return xs.reduce((rv, x, i) => {
|
||||
const resKey = typeof key === 'function' ? key(x, i) : x[key]
|
||||
rv[resKey] = rv[resKey] || []
|
||||
rv[resKey].push(x)
|
||||
return rv
|
||||
}, {})
|
||||
}
|
||||
|
||||
function isArray (a) {
|
||||
return Array.isArray(a)
|
||||
}
|
||||
|
||||
// ########################################################################
|
||||
// Non-exported Helpers
|
||||
// ########################################################################
|
||||
|
||||
function makePathArray (obj) {
|
||||
return flattenDeep(obj)
|
||||
.join('.')
|
||||
.replace('[', '.')
|
||||
.replace(']', '')
|
||||
.split('.')
|
||||
}
|
||||
|
||||
function flattenDeep (arr, newArr = []) {
|
||||
if (!isArray(arr)) {
|
||||
newArr.push(arr)
|
||||
} else {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
flattenDeep(arr[i], newArr)
|
||||
}
|
||||
}
|
||||
return newArr
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../lib/index'
|
||||
|
||||
export default () => {
|
||||
const data = _.map(_.range(1000000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
lastName: namor.generate({ words: 1, numLen: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
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',
|
||||
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)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../lib/index'
|
||||
|
||||
export default () => {
|
||||
const data = _.map(_.range(10000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
lastName: namor.generate({ words: 1, numLen: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
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',
|
||||
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)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
// expandedRows={{
|
||||
// 2: true,
|
||||
// 3: {
|
||||
// 2: true
|
||||
// }
|
||||
// }}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../lib/index'
|
||||
|
||||
export default () => {
|
||||
const data = _.map(_.range(1000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
lastName: namor.generate({ words: 1, numLen: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
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',
|
||||
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)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
@@ -48,6 +48,7 @@ const ServerSide = React.createClass({
|
||||
}
|
||||
},
|
||||
fetchData (state, instance) {
|
||||
console.log(state, instance)
|
||||
// Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model.
|
||||
// You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want.
|
||||
this.setState({loading: true})
|
||||
@@ -85,7 +86,7 @@ const ServerSide = React.createClass({
|
||||
}]
|
||||
}]}
|
||||
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
|
||||
pageSize={10}
|
||||
defaultPageSize={10}
|
||||
data={this.state.data} // Set the rows to be displayed
|
||||
pages={this.state.pages} // Display the total number of pages
|
||||
loading={this.state.loading} // Display the loading overlay when we need it
|
||||
@@ -111,7 +112,7 @@ function getCode () {
|
||||
import ReactTable from 'react-table'
|
||||
import Axios from 'axios'
|
||||
|
||||
export default React.creatClass({
|
||||
export default React.createClass({
|
||||
getInitialState () {
|
||||
// To handle our data server-side, we need to keep track of our table state
|
||||
return {
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ export default () => {
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
@@ -78,7 +78,7 @@ return (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
)
|
||||
`
|
||||
|
||||
+30
-10
@@ -38,20 +38,22 @@ export default () => {
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
subComponent={(row) => {
|
||||
defaultPageSize={10}
|
||||
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}
|
||||
pageSize={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>
|
||||
)
|
||||
@@ -95,10 +97,28 @@ export default (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
subComponent={(row) => {
|
||||
defaultPageSize={10}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user