mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca038e9a69 | ||
|
|
75c31b9354 | ||
|
|
4b2fa4e47d | ||
|
|
76e92de670 | ||
|
|
3c5ba2843d | ||
|
|
1cb280942d | ||
|
|
c8c650c729 | ||
|
|
29eda4dc71 | ||
|
|
e5689bc9d4 | ||
|
|
dd433f7d9c | ||
|
|
0daffaf08d |
@@ -4,3 +4,5 @@ react-table.js
|
||||
react-table.css
|
||||
*.log
|
||||
example/dist/
|
||||
|
||||
storybook-static
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react'
|
||||
import { configure, storiesOf } from '@kadira/storybook'
|
||||
|
||||
import './reset.css'
|
||||
import './fonts.css'
|
||||
import './layout.css'
|
||||
import '../stories/utils/prism.css'
|
||||
import 'github-markdown-css/github-markdown.css'
|
||||
import '../react-table.css'
|
||||
//
|
||||
import Readme from '../README.md'
|
||||
//
|
||||
import Simple from '../stories/Simple.js'
|
||||
import ServerSide from '../stories/ServerSide.js'
|
||||
import SubComponents from '../stories/SubComponents.js'
|
||||
//
|
||||
configure(() => {
|
||||
storiesOf('1. Docs')
|
||||
.add('Readme', () => {
|
||||
const ReadmeCmp = React.createClass({
|
||||
render () {
|
||||
return <span className='markdown-body' dangerouslySetInnerHTML={{__html: Readme}} />
|
||||
},
|
||||
componentDidMount () {
|
||||
global.Prism.highlightAll()
|
||||
}
|
||||
})
|
||||
return <ReadmeCmp />
|
||||
})
|
||||
storiesOf('2. Demos')
|
||||
.add('Client-side Data', Simple)
|
||||
.add('Server-side Data', ServerSide)
|
||||
.add('Sub Components', SubComponents)
|
||||
}, module)
|
||||
@@ -0,0 +1,6 @@
|
||||
@import url("https://fonts.googleapis.com/css?family=Open+Sans:300,600");
|
||||
body {
|
||||
background: #fff;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
body{
|
||||
padding: 20px;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
/*ol, ul {
|
||||
list-style: none;
|
||||
}*/
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
const path = require('path')
|
||||
|
||||
// load the default config generator.
|
||||
const genDefaultConfig = require('@kadira/storybook/dist/server/config/defaults/webpack.config.js')
|
||||
|
||||
module.exports = (config, env) => {
|
||||
config = genDefaultConfig(config, env)
|
||||
|
||||
Object.assign(config, {
|
||||
module: Object.assign(config.module, {
|
||||
loaders: config.module.loaders.concat([{
|
||||
test: /\.md$/,
|
||||
loader: 'html!markdown',
|
||||
include: path.resolve(__dirname, '../')
|
||||
}, {
|
||||
test: /\.html$/,
|
||||
loader: 'html',
|
||||
query: {
|
||||
minimize: true
|
||||
},
|
||||
include: path.resolve(__dirname, '../')
|
||||
}])
|
||||
})
|
||||
})
|
||||
|
||||
return config
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
</div>
|
||||
|
||||
# react-table
|
||||
A fast, lightweight, opinionated table and datagrid built on React
|
||||
# React Table
|
||||
`react-table` is a **lightweight, fast and extendable datagrid** built for React
|
||||
|
||||
[](https://travis-ci.org/tannerlinsley/react-table) [](https://npmjs.com/packag/react-table) [](https://react-table-slack.herokuapp.com/) [](https://github.com/tannerlinsley/react-table) [](https://twitter.com/tannerlinsley)
|
||||
|
||||
@@ -16,29 +16,29 @@ A fast, lightweight, opinionated table and datagrid built on React
|
||||
- Fully customizable JSX and callbacks for everything
|
||||
- Supports both Client-side & Server-side pagination and sorting
|
||||
- Minimal design & easily themeable
|
||||
- ["Why I wrote React Table and the problems it has solved for Nozzle.io"](https://medium.com/@tannerlinsley/why-i-wrote-react-table-and-the-problems-it-has-solved-for-nozzle-others-445c4e93d4a8#.axza4ixba) by Tanner Linsley
|
||||
- <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
|
||||
|
||||
## [Demo](http://react-table.zabapps.com)
|
||||
## <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)
|
||||
- [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'
|
||||
@@ -75,24 +75,23 @@ 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
|
||||
showPageSizeOptions: true, // Enables the user to change the page size
|
||||
pageSizeOptions: [5, 10, 20, 25, 50, 100], // The available page size options
|
||||
expanderColumnWidth: 30, // default columnWidth for the expander column
|
||||
|
||||
// Callbacks
|
||||
onChange: (state, instance) => null, // Anytime the internal state of the table changes, this will fire
|
||||
@@ -113,6 +112,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
|
||||
@@ -123,6 +123,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,
|
||||
visibleSubComponents: undefined,
|
||||
// Controlled Callbacks
|
||||
onExpand: undefined,
|
||||
onPageChange: undefined,
|
||||
onPageSizeChange: undefined,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -132,7 +142,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...
|
||||
})
|
||||
@@ -142,15 +152,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
|
||||
[{
|
||||
@@ -160,13 +169,11 @@ 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: Number // Allows the column to flex above this minimum amount
|
||||
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
|
||||
style: {}, // Set the style of the `td` element of the column
|
||||
innerClassName: '', // Set the classname of the `.-td-inner` element of the column
|
||||
innerStyle: {}, // Set the style of the `.-td-inner` element of the column
|
||||
render: JSX eg. ({value, rowValues, row, index, viewIndex}) => <span>{value}</span>, // Provide a JSX element or stateless function to render whatever you want as the column's cell with access to the entire row
|
||||
// value == the accessed value of the column
|
||||
// rowValues == an object of all of the accessed values for the row
|
||||
@@ -178,8 +185,6 @@ Or just define them on the component per-instance
|
||||
header: 'Header Name' or JSX eg. ({data, column}) => <div>Header Name</div>,
|
||||
headerClassName: '', // Set the classname of the `th` element of the column
|
||||
headerStyle: {}, // Set the style of the `th` element of the column
|
||||
headerInnerClassName: '', // Set the classname of the `.-th-inner` element of the column
|
||||
headerInnerStyle: {}, // Set the style of the `.th-inner` element of the column
|
||||
|
||||
// Header Groups only
|
||||
columns: [...] // See Header Groups section below
|
||||
@@ -187,11 +192,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
|
||||
@@ -210,7 +213,24 @@ const columns = [{
|
||||
}]
|
||||
```
|
||||
|
||||
<a name="server-side-data"></a>
|
||||
## Sub Tables & Components
|
||||
By adding a `SubComponent` props, you can easily add an expansion level to all root-level rows:
|
||||
```javascript
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
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!
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
## Server-side Data
|
||||
If you want to handle pagination, and sorting on the server, `react-table` makes it easy on you.
|
||||
|
||||
@@ -251,38 +271,64 @@ 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
|
||||
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!
|
||||
|
||||
<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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
# Jumpsuit Getting Started
|
||||
@@ -1,28 +0,0 @@
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var stylus = require('stylus')
|
||||
var nib = require('nib')
|
||||
|
||||
var stylusEntry = path.resolve('src/app.styl')
|
||||
|
||||
module.exports = {
|
||||
styles: {
|
||||
extensions: ['.css', '.styl'],
|
||||
action: buildStyles
|
||||
}
|
||||
}
|
||||
|
||||
function buildStyles () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
stylus.render(fs.readFileSync(stylusEntry, 'utf8'), {
|
||||
'include css': true,
|
||||
'hoist atrules': true,
|
||||
compress: process.env.NODE_ENV === 'production',
|
||||
paths: [path.resolve('src')],
|
||||
use: nib()
|
||||
}, function (err, css) {
|
||||
if (err) reject(err)
|
||||
else resolve(css)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"name": "react-table-example",
|
||||
"version": "0.0.1",
|
||||
"description": "Jumpsuit getting started example",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/jumpsuit/jumpsuit.git"
|
||||
},
|
||||
"scripts": {
|
||||
"watch": "jumpsuit watch",
|
||||
"build": "jumpsuit build",
|
||||
"deploy": "jumpsuit build && zab deploy"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nib": "^1.1.0",
|
||||
"standard": "^8.4.0",
|
||||
"stylus": "^0.54.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"jumpsuit": "^1.3.3",
|
||||
"lodash": "^4.16.4",
|
||||
"namor": "^0.3.0",
|
||||
"react-syntax-highlighter": "^3.0.0",
|
||||
"react-table": "^3.1.2"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Render, Router, Route, IndexRoute } from 'jumpsuit'
|
||||
//
|
||||
import Layout from 'components/layout'
|
||||
import Simple from 'screens/simple'
|
||||
import ServerSide from 'screens/serverSide'
|
||||
|
||||
Render(null, (
|
||||
<Router>
|
||||
<Route path='/' component={Layout}>
|
||||
<IndexRoute component={Simple} />
|
||||
<Route path='simple' component={Simple} />
|
||||
<Route path='server-side' component={ServerSide} />
|
||||
</Route>
|
||||
</Router>
|
||||
), {
|
||||
useHash: false
|
||||
})
|
||||
@@ -1,112 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Globals
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,600')
|
||||
@import 'nib'
|
||||
|
||||
global-reset()
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// vendor styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@import '../node_modules/react-table/src/index'
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
$fnt-open-sans = 'Open Sans', sans-serif
|
||||
$react = #25d8fd
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// styles
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
*
|
||||
box-sizing border-box
|
||||
|
||||
html
|
||||
min-height 100vh
|
||||
|
||||
body
|
||||
background: white
|
||||
font-family: $fnt-open-sans
|
||||
font-weight: 300
|
||||
|
||||
h1
|
||||
font-size: 2.5em
|
||||
color: white
|
||||
|
||||
a
|
||||
color: darken($react, 20%)
|
||||
font-weight: bold
|
||||
text-decoration: none
|
||||
|
||||
strong
|
||||
font-weight: bold
|
||||
|
||||
.logo
|
||||
width: 400px
|
||||
max-width: 100%
|
||||
|
||||
.container
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
justify-content: center
|
||||
min-height: 100vh
|
||||
padding-top: 20px
|
||||
|
||||
.github-addon
|
||||
font-size: 20px
|
||||
padding: 10px
|
||||
|
||||
.viewport
|
||||
width:100%
|
||||
|
||||
.table-wrap
|
||||
width: 90%
|
||||
margin: auto
|
||||
padding: 10px
|
||||
border-radius: 5px
|
||||
box-shadow: 0 0 20px 0 alpha(black, .2)
|
||||
|
||||
.menu
|
||||
display:block
|
||||
margin: 0 10px 20px
|
||||
ul
|
||||
display:block
|
||||
li
|
||||
display:inline-block
|
||||
a
|
||||
display:block
|
||||
padding: 10px
|
||||
margin: 5px
|
||||
background: alpha(black, .4)
|
||||
color: white
|
||||
border-radius: 3px
|
||||
transition: all .2s ease-out
|
||||
&.active
|
||||
&:hover
|
||||
background: alpha(black, .9)
|
||||
|
||||
.ReactTable
|
||||
thead
|
||||
th
|
||||
td
|
||||
&.-sort-asc
|
||||
box-shadow:inset 0 3px 0 0 alpha(black, .6)
|
||||
&.-sort-desc
|
||||
box-shadow:inset 0 -3px 0 0 alpha(black, .6)
|
||||
|
||||
pre
|
||||
display:block
|
||||
font-family: monospace
|
||||
font-size: 15px
|
||||
line-height: 20px
|
||||
border-radius: 5px
|
||||
margin: 20px auto
|
||||
max-width: 90%
|
||||
padding: 0 20px !important
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>React-Table Demo</title>
|
||||
<link rel="stylesheet" href="/app.css" charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="/app.js"></script>
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Component } from 'jumpsuit'
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter'
|
||||
import atomOneDark from '../../node_modules/react-syntax-highlighter/dist/styles/atom-one-dark'
|
||||
|
||||
export default Component({
|
||||
render () {
|
||||
return (
|
||||
<SyntaxHighlighter language='javascript' style={atomOneDark}>{this.props.children}</SyntaxHighlighter>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,59 +0,0 @@
|
||||
import { Component, Link } from 'jumpsuit'
|
||||
|
||||
export default Component({
|
||||
render () {
|
||||
return (
|
||||
<div className='container'>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<h1>
|
||||
<span style={{position: 'absolute', textIndent: '-9999em'}}>
|
||||
react-table
|
||||
</span>
|
||||
<img src='/Banner.png' className='logo' />
|
||||
</h1>
|
||||
<br />
|
||||
<div>
|
||||
<a
|
||||
className='github-button'
|
||||
href='https://github.com/tannerlinsley/react-table'
|
||||
target='_blank'
|
||||
data-style='mega'
|
||||
data-count-href='/tannerlinsley/react-table/stargazers'
|
||||
data-count-api='/repos/tannerlinsley/react-table#stargazers_count'
|
||||
data-count-aria-label='# stargazers on GitHub'
|
||||
aria-label='Star tannerlinsley/react-table on GitHub'>
|
||||
Star
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<div className='github-addon'>
|
||||
<a
|
||||
target='_blank'
|
||||
href='https://github.com/tannerlinsley/react-table'>
|
||||
View on Github
|
||||
</a>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
<div className='menu'>
|
||||
<ul>
|
||||
<li>
|
||||
<Link to='/simple' activeClassName='active'>
|
||||
Simple
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to='/server-side' activeClassName='active'>
|
||||
Server-Side
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className='viewport'>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,103 +0,0 @@
|
||||
import { Component } from 'jumpsuit'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from 'components/codeHighlight'
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
export default Component({
|
||||
render () {
|
||||
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
|
||||
data={data}
|
||||
columns={columns}
|
||||
pageSize={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'
|
||||
|
||||
// To help us mock some data
|
||||
import namor from 'namor'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default () => {
|
||||
|
||||
// Mock some data
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
||||
// 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={data}
|
||||
columns={columns}
|
||||
pageSize={10}
|
||||
/>
|
||||
)
|
||||
})
|
||||
`
|
||||
}
|
||||
-2741
File diff suppressed because it is too large
Load Diff
+17
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "3.2.0",
|
||||
"version": "4.1.0",
|
||||
"description": "A fast, lightweight, opinionated table and datagrid built on React",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/tannerlinsley/react-table#readme",
|
||||
@@ -25,19 +25,24 @@
|
||||
"scripts": {
|
||||
"build:node": "babel src --out-dir lib --source-maps inline",
|
||||
"build:css": "rm -rf react-table.css && stylus src/index.styl --use ./node_modules/nib/lib/nib.js --compress -o react-table.css",
|
||||
"watch": "onchange 'src/**' -i -- npm-run-all build:*",
|
||||
"watch": "npm-run-all --parallel watch:*",
|
||||
"watch:node": "onchange 'src/**/*.js' -i -- npm run build:node",
|
||||
"watch:css": "onchange 'src/**/*.styl' -i -- npm run build:css",
|
||||
"test": "standard",
|
||||
"umd": "rm -rf react-table.js && browserify lib/index.js -s reactTable -x react -t babelify -g uglifyify -o react-table.js",
|
||||
"prepublish": "npm-run-all build:* && npm run umd",
|
||||
"postpublish": "git push --tags"
|
||||
"storybook": "start-storybook -p 8000 -c .storybook",
|
||||
"deploy": "build-storybook && zab deploy"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5"
|
||||
"classnames": "^2.2.5",
|
||||
"inline-style-prefixer": "^2.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.x.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kadira/storybook": "^2.35.1",
|
||||
"babel-cli": "6.14.0",
|
||||
"babel-eslint": "6.1.2",
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
@@ -45,9 +50,15 @@
|
||||
"babel-preset-stage-2": "6.13.0",
|
||||
"babelify": "^7.3.0",
|
||||
"browserify": "13.1.0",
|
||||
"github-markdown-css": "^2.4.1",
|
||||
"html-loader": "^0.4.4",
|
||||
"markdown-loader": "^0.1.7",
|
||||
"namor": "^0.3.0",
|
||||
"nib": "^1.1.2",
|
||||
"npm-run-all": "^3.1.1",
|
||||
"onchange": "^3.0.2",
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"standard": "^8.0.0",
|
||||
"stylus": "^0.54.5",
|
||||
"uglifyify": "3.0.3"
|
||||
@@ -62,7 +73,8 @@
|
||||
"dist",
|
||||
"lib",
|
||||
"example",
|
||||
"react-table.js"
|
||||
"react-table.js",
|
||||
"stories"
|
||||
]
|
||||
},
|
||||
"babel": {
|
||||
|
||||
+450
-312
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import prefixAll from 'inline-style-prefixer/static'
|
||||
//
|
||||
import _ from './utils'
|
||||
|
||||
@@ -9,13 +10,27 @@ export const ReactTableDefaults = {
|
||||
// General
|
||||
data: [],
|
||||
loading: false,
|
||||
pageSize: 20,
|
||||
showPagination: true,
|
||||
showPageSizeOptions: true,
|
||||
pageSizeOptions: [5, 10, 20, 25, 50, 100],
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
// Callbacks
|
||||
expanderColumnWidth: 30,
|
||||
|
||||
// Controlled State Overrides
|
||||
// page
|
||||
// pageSize
|
||||
// sorting
|
||||
// visibleSubComponents
|
||||
|
||||
// Controlled State Callbacks
|
||||
onExpand: undefined,
|
||||
onPageChange: undefined,
|
||||
onPageSizeChange: undefined,
|
||||
|
||||
// General Callbacks
|
||||
onChange: () => null,
|
||||
onTrClick: () => null,
|
||||
// Classes
|
||||
className: '-striped -highlight',
|
||||
tableClassName: '',
|
||||
@@ -23,7 +38,6 @@ export const ReactTableDefaults = {
|
||||
tbodyClassName: '',
|
||||
trClassName: '',
|
||||
trClassCallback: d => null,
|
||||
onTrClick: () => null,
|
||||
thClassName: '',
|
||||
thGroupClassName: '',
|
||||
tdClassName: '',
|
||||
@@ -44,12 +58,11 @@ export const ReactTableDefaults = {
|
||||
show: true,
|
||||
className: '',
|
||||
style: {},
|
||||
innerClassName: '',
|
||||
innerStyle: {},
|
||||
headerClassName: '',
|
||||
headerStyle: {},
|
||||
headerInnerClassName: '',
|
||||
headerInnerStyle: {}
|
||||
headerInnerStyle: {},
|
||||
minWidth: 100
|
||||
},
|
||||
// Text
|
||||
previousText: 'Previous',
|
||||
@@ -59,25 +72,40 @@ export const ReactTableDefaults = {
|
||||
ofText: 'of',
|
||||
rowsText: 'rows',
|
||||
// Components
|
||||
tableComponent: (props) => <table {...props}>{props.children}</table>,
|
||||
theadComponent: (props) => <thead {...props}>{props.children}</thead>,
|
||||
tbodyComponent: (props) => <tbody {...props}>{props.children}</tbody>,
|
||||
trComponent: (props) => <tr {...props}>{props.children}</tr>,
|
||||
thComponent: (props) => {
|
||||
const {toggleSort, ...rest} = props
|
||||
TableComponent: _.makeTemplateComponent('rt-table'),
|
||||
TheadComponent: _.makeTemplateComponent('rt-thead'),
|
||||
TbodyComponent: _.makeTemplateComponent('rt-tbody'),
|
||||
TrGroupComponent: _.makeTemplateComponent('rt-tr-group'),
|
||||
TrComponent: _.makeTemplateComponent('rt-tr'),
|
||||
ThComponent: ({toggleSort, className, children, ...rest}) => {
|
||||
return (
|
||||
<th {...rest} onClick={e => {
|
||||
toggleSort && toggleSort(e)
|
||||
}}>{props.children}</th>
|
||||
<div
|
||||
className={classnames(className, 'rt-th')}
|
||||
onClick={e => {
|
||||
toggleSort && toggleSort(e)
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
tdComponent: (props) => <td {...props}>{props.children}</td>,
|
||||
previousComponent: null,
|
||||
nextComponent: null,
|
||||
loadingComponent: props => (
|
||||
<div className={classnames('-loading', {'-active': props.loading})}>
|
||||
TdComponent: _.makeTemplateComponent('rt-td'),
|
||||
ExpanderComponent: ({isExpanded, toggle, ...rest}) => {
|
||||
return (
|
||||
<div
|
||||
className={classnames('rt-expander', isExpanded && '-open')}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
},
|
||||
PaginationComponent: Pagination,
|
||||
PreviousComponent: undefined,
|
||||
NextComponent: undefined,
|
||||
LoadingComponent: ({loading, loadingText}) => (
|
||||
<div className={classnames('-loading', {'-active': loading})}>
|
||||
<div className='-loading-inner'>
|
||||
{props.loadingText}
|
||||
{loadingText}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -87,22 +115,397 @@ export default React.createClass({
|
||||
getDefaultProps () {
|
||||
return ReactTableDefaults
|
||||
},
|
||||
|
||||
getInitialState () {
|
||||
return {
|
||||
page: 0,
|
||||
sorting: false
|
||||
pageSize: this.props.defaultPageSize || 10,
|
||||
sorting: false,
|
||||
visibleSubComponents: []
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount () {
|
||||
this.fireOnChange()
|
||||
},
|
||||
fireOnChange () {
|
||||
this.props.onChange({
|
||||
page: this.getPropOrState('page'),
|
||||
pageSize: this.getStateOrProp('pageSize'),
|
||||
|
||||
render () {
|
||||
const resolvedProps = this.getResolvedState()
|
||||
const {
|
||||
className,
|
||||
style,
|
||||
tableClassName,
|
||||
tableStyle,
|
||||
theadGroupClassName,
|
||||
theadStyle,
|
||||
trClassName,
|
||||
trStyle,
|
||||
thClassname,
|
||||
thStyle,
|
||||
data,
|
||||
columns,
|
||||
theadClassName,
|
||||
tbodyClassName,
|
||||
tbodyStyle,
|
||||
onTrClick,
|
||||
trClassCallback,
|
||||
trStyleCallback,
|
||||
tdStyle,
|
||||
showPagination,
|
||||
paginationClassName,
|
||||
expanderColumnWidth,
|
||||
manual,
|
||||
loadingText,
|
||||
onExpand,
|
||||
// State
|
||||
visibleSubComponents,
|
||||
loading,
|
||||
pageSize,
|
||||
page,
|
||||
// Components
|
||||
TableComponent,
|
||||
TheadComponent,
|
||||
TbodyComponent,
|
||||
TrGroupComponent,
|
||||
TrComponent,
|
||||
ThComponent,
|
||||
TdComponent,
|
||||
ExpanderComponent,
|
||||
PaginationComponent,
|
||||
LoadingComponent,
|
||||
SubComponent
|
||||
} = resolvedProps
|
||||
|
||||
// Build Columns
|
||||
const decoratedColumns = []
|
||||
const headerGroups = []
|
||||
let currentSpan = []
|
||||
|
||||
// Determine Header Groups
|
||||
let hasHeaderGroups = false
|
||||
columns.forEach(column => {
|
||||
if (column.columns) {
|
||||
hasHeaderGroups = true
|
||||
}
|
||||
})
|
||||
|
||||
// A convenience function to add a header and reset the currentSpan
|
||||
const addHeader = (columns, column = {}) => {
|
||||
headerGroups.push(Object.assign({}, column, {
|
||||
columns: columns
|
||||
}))
|
||||
currentSpan = []
|
||||
}
|
||||
|
||||
// Build the columns and headers
|
||||
const visibleColumns = columns.filter(d => _.getFirstDefined(d.show, true))
|
||||
visibleColumns.forEach((column, i) => {
|
||||
if (column.columns) {
|
||||
const nestedColumns = column.columns.filter(d => _.getFirstDefined(d.show, true))
|
||||
nestedColumns.forEach(nestedColumn => {
|
||||
decoratedColumns.push(this.makeDecoratedColumn(nestedColumn))
|
||||
})
|
||||
if (hasHeaderGroups) {
|
||||
if (currentSpan.length > 0) {
|
||||
addHeader(currentSpan)
|
||||
}
|
||||
addHeader(_.takeRight(decoratedColumns, nestedColumns.length), column)
|
||||
}
|
||||
} else {
|
||||
decoratedColumns.push(this.makeDecoratedColumn(column))
|
||||
currentSpan.push(_.last(decoratedColumns))
|
||||
}
|
||||
})
|
||||
|
||||
const columnPercentage = 100 / decoratedColumns.length
|
||||
|
||||
if (hasHeaderGroups && currentSpan.length > 0) {
|
||||
addHeader(currentSpan)
|
||||
}
|
||||
|
||||
const sorting = this.getSorting(decoratedColumns)
|
||||
const accessedData = data.map((d, i) => {
|
||||
const row = {
|
||||
__original: d,
|
||||
__index: i
|
||||
}
|
||||
decoratedColumns.forEach(column => {
|
||||
row[column.id] = column.accessor(d)
|
||||
})
|
||||
return row
|
||||
})
|
||||
const resolvedData = manual ? accessedData : this.sortData(accessedData, sorting)
|
||||
|
||||
// Normalize state
|
||||
const pagesLength = this.getPagesLength()
|
||||
|
||||
// Pagination
|
||||
const startRow = pageSize * page
|
||||
const endRow = startRow + pageSize
|
||||
const pageRows = manual ? resolvedData : resolvedData.slice(startRow, endRow)
|
||||
const minRows = this.getMinRows()
|
||||
const padRows = pagesLength > 1 ? _.range(pageSize - pageRows.length)
|
||||
: minRows ? _.range(Math.max(minRows - pageRows.length, 0))
|
||||
: []
|
||||
|
||||
const canPrevious = page > 0
|
||||
const canNext = page + 1 < pagesLength
|
||||
|
||||
const rowWidth = (SubComponent ? expanderColumnWidth : 0) + _.sum(decoratedColumns.map(d => d.minWidth))
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(className, 'ReactTable')}
|
||||
style={style}
|
||||
>
|
||||
<TableComponent
|
||||
className={classnames(tableClassName)}
|
||||
style={tableStyle}
|
||||
>
|
||||
{hasHeaderGroups && (
|
||||
<TheadComponent
|
||||
className={classnames(theadGroupClassName, '-headerGroups')}
|
||||
style={Object.assign({}, theadStyle, {
|
||||
minWidth: `${rowWidth}px`
|
||||
})}
|
||||
>
|
||||
<TrComponent
|
||||
className={trClassName}
|
||||
style={trStyle}
|
||||
>
|
||||
{SubComponent && (
|
||||
<ThComponent
|
||||
className={classnames(thClassname, 'rt-expander-header')}
|
||||
style={prefixAll({
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{headerGroups.map((column, i) => {
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(thClassname, column.headerClassName)}
|
||||
style={Object.assign({}, thStyle, column.headerStyle, prefixAll({
|
||||
flex: `${column.columns.length * columnPercentage} 0 auto`,
|
||||
width: `${_.sum(column.columns.map(d => d.minWidth))}px`
|
||||
}))}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={resolvedData}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
</ThComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
</TheadComponent>
|
||||
)}
|
||||
<TheadComponent
|
||||
className={classnames(theadClassName, '-header')}
|
||||
style={Object.assign({}, theadStyle, {
|
||||
minWidth: `${rowWidth}px`
|
||||
})}
|
||||
>
|
||||
<TrComponent
|
||||
className={trClassName}
|
||||
style={trStyle}
|
||||
>
|
||||
{SubComponent && (
|
||||
<ThComponent
|
||||
className={classnames(thClassname, 'rt-expander-header')}
|
||||
style={prefixAll({
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{decoratedColumns.map((column, i) => {
|
||||
const sort = sorting.find(d => d.id === column.id)
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
thClassname,
|
||||
column.headerClassName,
|
||||
sort ? (sort.asc ? '-sort-asc' : '-sort-desc') : '',
|
||||
{
|
||||
'-cursor-pointer': column.sortable,
|
||||
'-hidden': !show
|
||||
}
|
||||
)}
|
||||
style={Object.assign({}, thStyle, column.headerStyle, prefixAll({
|
||||
flex: `${columnPercentage} 0 auto`,
|
||||
width: `${column.minWidth}px`
|
||||
}))}
|
||||
toggleSort={(e) => {
|
||||
column.sortable && this.sortColumn(column, e.shiftKey)
|
||||
}}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={resolvedData}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
</ThComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
</TheadComponent>
|
||||
<TbodyComponent
|
||||
className={classnames(tbodyClassName)}
|
||||
style={Object.assign({}, tbodyStyle, {
|
||||
minWidth: `${rowWidth}px`
|
||||
})}
|
||||
>
|
||||
{pageRows.map((row, i) => {
|
||||
const rowInfo = {
|
||||
row: row.__original,
|
||||
rowValues: row,
|
||||
index: row.__index,
|
||||
viewIndex: i
|
||||
}
|
||||
const visibleSubComponentIndex = visibleSubComponents.indexOf(i)
|
||||
const isExpanded = visibleSubComponentIndex > -1
|
||||
return (
|
||||
<TrGroupComponent key={i}>
|
||||
<TrComponent
|
||||
onClick={event => onTrClick(rowInfo.row, event)}
|
||||
className={classnames(trClassName, trClassCallback(rowInfo))}
|
||||
style={Object.assign({}, trStyle, trStyleCallback(rowInfo))}
|
||||
>
|
||||
{SubComponent && (
|
||||
<ThComponent
|
||||
className={classnames(thClassname, 'rt-expander-wrap')}
|
||||
style={prefixAll({
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
})}
|
||||
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
|
||||
]
|
||||
})
|
||||
}}
|
||||
>
|
||||
<ExpanderComponent
|
||||
isExpanded={isExpanded}
|
||||
/>
|
||||
</ThComponent>
|
||||
)}
|
||||
{decoratedColumns.map((column, i2) => {
|
||||
const Cell = column.render
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(column.className, {hidden: !show})}
|
||||
style={Object.assign({}, tdStyle, column.style, prefixAll({
|
||||
flex: `${columnPercentage} 0 auto`,
|
||||
width: `${column.minWidth}px`
|
||||
}))}
|
||||
>
|
||||
{typeof Cell === 'function' ? (
|
||||
<Cell
|
||||
{...rowInfo}
|
||||
value={rowInfo.rowValues[column.id]}
|
||||
/>
|
||||
) : typeof Cell !== 'undefined' ? Cell
|
||||
: rowInfo.rowValues[column.id]}
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
{SubComponent && isExpanded ? (
|
||||
SubComponent(rowInfo)
|
||||
) : null}
|
||||
</TrGroupComponent>
|
||||
)
|
||||
})}
|
||||
{padRows.map((row, i) => {
|
||||
return (
|
||||
<TrComponent
|
||||
key={i}
|
||||
className={classnames(trClassName, '-padRow')}
|
||||
style={trStyle}
|
||||
>
|
||||
{SubComponent && (
|
||||
<ThComponent
|
||||
className={classnames(thClassname, 'rt-expander-header')}
|
||||
style={prefixAll({
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
{decoratedColumns.map((column, i2) => {
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(column.className, {hidden: !show})}
|
||||
style={Object.assign({}, tdStyle, column.style, {
|
||||
flex: `${columnPercentage} 0 auto`,
|
||||
width: `${column.minWidth}px`
|
||||
})}
|
||||
>
|
||||
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
)
|
||||
})}
|
||||
</TbodyComponent>
|
||||
</TableComponent>
|
||||
{showPagination && (
|
||||
<PaginationComponent
|
||||
{...resolvedProps}
|
||||
pagesLength={pagesLength}
|
||||
canPrevious={canPrevious}
|
||||
canNext={canNext}
|
||||
onPageChange={this.onPageChange}
|
||||
onPageSizeChange={this.onPageSizeChange}
|
||||
className={paginationClassName}
|
||||
/>
|
||||
)}
|
||||
<LoadingComponent
|
||||
loading={loading}
|
||||
loadingText={loadingText}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
// Helpers
|
||||
getResolvedState () {
|
||||
return {
|
||||
...this.state,
|
||||
...this.props,
|
||||
pages: this.getPagesLength(),
|
||||
sorting: this.getSorting()
|
||||
}, this)
|
||||
}
|
||||
},
|
||||
fireOnChange () {
|
||||
this.props.onChange(this.getResolvedState(), this)
|
||||
},
|
||||
getPropOrState (key) {
|
||||
return _.getFirstDefined(this.props[key], this.state[key])
|
||||
@@ -169,300 +572,35 @@ export default React.createClass({
|
||||
getMinRows () {
|
||||
return _.getFirstDefined(this.props.minRows, this.getStateOrProp('pageSize'))
|
||||
},
|
||||
render () {
|
||||
// Build Columns
|
||||
const decoratedColumns = []
|
||||
const headerGroups = []
|
||||
let currentSpan = []
|
||||
|
||||
// Determine Header Groups
|
||||
let hasHeaderGroups = false
|
||||
this.props.columns
|
||||
.forEach(column => {
|
||||
if (column.columns) {
|
||||
hasHeaderGroups = true
|
||||
}
|
||||
})
|
||||
|
||||
// A convenience function to add a header and reset the currentSpan
|
||||
const addHeader = (columns, column = {}) => {
|
||||
headerGroups.push(Object.assign({}, column, {
|
||||
columns: columns
|
||||
}))
|
||||
currentSpan = []
|
||||
}
|
||||
|
||||
// Build the columns and headers
|
||||
const visibleColumns = this.props.columns.filter(d => _.getFirstDefined(d.show, true))
|
||||
visibleColumns.forEach((column, i) => {
|
||||
if (column.columns) {
|
||||
const nestedColumns = column.columns.filter(d => _.getFirstDefined(d.show, true))
|
||||
nestedColumns.forEach(nestedColumn => {
|
||||
decoratedColumns.push(this.makeDecoratedColumn(nestedColumn))
|
||||
})
|
||||
if (hasHeaderGroups) {
|
||||
if (currentSpan.length > 0) {
|
||||
addHeader(currentSpan)
|
||||
}
|
||||
addHeader(_.takeRight(decoratedColumns, nestedColumns.length), column)
|
||||
}
|
||||
} else {
|
||||
decoratedColumns.push(this.makeDecoratedColumn(column))
|
||||
currentSpan.push(_.last(decoratedColumns))
|
||||
}
|
||||
})
|
||||
|
||||
if (hasHeaderGroups && currentSpan.length > 0) {
|
||||
addHeader(currentSpan)
|
||||
}
|
||||
|
||||
const sorting = this.getSorting(decoratedColumns)
|
||||
const accessedData = this.props.data.map((d, i) => {
|
||||
const row = {
|
||||
__original: d,
|
||||
__index: i
|
||||
}
|
||||
decoratedColumns.forEach(column => {
|
||||
row[column.id] = column.accessor(d)
|
||||
})
|
||||
return row
|
||||
})
|
||||
const data = this.props.manual ? accessedData : this.sortData(accessedData, sorting)
|
||||
|
||||
// Normalize state
|
||||
const currentPage = this.getPropOrState('page')
|
||||
const pageSize = this.getStateOrProp('pageSize')
|
||||
const pagesLength = this.getPagesLength()
|
||||
|
||||
// Pagination
|
||||
const startRow = pageSize * currentPage
|
||||
const endRow = startRow + pageSize
|
||||
const pageRows = this.props.manual ? data : data.slice(startRow, endRow)
|
||||
const minRows = this.getMinRows()
|
||||
const padRows = pagesLength > 1 ? _.range(pageSize - pageRows.length)
|
||||
: minRows ? _.range(Math.max(minRows - pageRows.length, 0))
|
||||
: []
|
||||
|
||||
const canPrevious = currentPage > 0
|
||||
const canNext = currentPage + 1 < pagesLength
|
||||
|
||||
const TableComponent = this.props.tableComponent
|
||||
const TheadComponent = this.props.theadComponent
|
||||
const TbodyComponent = this.props.tbodyComponent
|
||||
const TrComponent = this.props.trComponent
|
||||
const ThComponent = this.props.thComponent
|
||||
const TdComponent = this.props.tdComponent
|
||||
const PreviousComponent = this.props.previousComponent
|
||||
const NextComponent = this.props.nextComponent
|
||||
const LoadingComponent = this.props.loadingComponent
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(this.props.className, 'ReactTable')}
|
||||
style={this.props.style}
|
||||
>
|
||||
<TableComponent
|
||||
className={classnames(this.props.tableClassName)}
|
||||
style={this.props.tableStyle}
|
||||
>
|
||||
{hasHeaderGroups && (
|
||||
<TheadComponent
|
||||
className={classnames(this.props.theadGroupClassName, '-headerGroups')}
|
||||
style={this.props.theadStyle}
|
||||
>
|
||||
<TrComponent
|
||||
className={this.props.trClassName}
|
||||
style={this.props.trStyle}
|
||||
>
|
||||
{headerGroups.map((column, i) => {
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
colSpan={column.columns.length}
|
||||
className={classnames(this.props.thClassname, column.headerClassName)}
|
||||
style={Object.assign({}, this.props.thStyle, column.headerStyle)}
|
||||
>
|
||||
<div
|
||||
className={classnames(column.headerInnerClassName, '-th-inner')}
|
||||
style={Object.assign({}, this.props.thInnerStyle, column.headerInnerStyle)}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={this.props.data}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
</div>
|
||||
</ThComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
</TheadComponent>
|
||||
)}
|
||||
<TheadComponent
|
||||
className={classnames(this.props.theadClassName)}
|
||||
style={this.props.theadStyle}
|
||||
>
|
||||
<TrComponent
|
||||
className={this.props.trClassName}
|
||||
style={this.props.trStyle}
|
||||
>
|
||||
{decoratedColumns.map((column, i) => {
|
||||
const sort = sorting.find(d => d.id === column.id)
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
this.props.thClassname,
|
||||
column.headerClassName,
|
||||
sort ? (sort.asc ? '-sort-asc' : '-sort-desc') : '',
|
||||
{
|
||||
'-cursor-pointer': column.sortable,
|
||||
'-hidden': !show
|
||||
}
|
||||
)}
|
||||
style={Object.assign({}, this.props.thStyle, column.headerStyle)}
|
||||
toggleSort={(e) => {
|
||||
column.sortable && this.sortColumn(column, e.shiftKey)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={classnames(column.headerInnerClassName, '-th-inner')}
|
||||
style={Object.assign({}, column.headerInnerStyle, {
|
||||
minWidth: column.minWidth + 'px'
|
||||
})}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<column.header
|
||||
data={this.props.data}
|
||||
column={column}
|
||||
/>
|
||||
) : column.header}
|
||||
</div>
|
||||
</ThComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
</TheadComponent>
|
||||
<TbodyComponent
|
||||
className={classnames(this.props.tbodyClassName)}
|
||||
style={this.props.tbodyStyle}
|
||||
>
|
||||
{pageRows.map((row, i) => {
|
||||
const rowInfo = {
|
||||
row: row.__original,
|
||||
rowValues: row,
|
||||
index: row.__index,
|
||||
viewIndex: i
|
||||
}
|
||||
return (
|
||||
<TrComponent
|
||||
key={i}
|
||||
onClick={event => this.props.onTrClick(rowInfo.row, event)}
|
||||
className={classnames(this.props.trClassName, this.props.trClassCallback(rowInfo))}
|
||||
style={Object.assign({}, this.props.trStyle, this.props.trStyleCallback(rowInfo))}
|
||||
>
|
||||
{decoratedColumns.map((column, i2) => {
|
||||
const Cell = column.render
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(column.className, {hidden: !show})}
|
||||
style={Object.assign({}, this.props.tdStyle, column.style)}
|
||||
>
|
||||
<div
|
||||
className={classnames(column.innerClassName, '-td-inner')}
|
||||
style={Object.assign({}, column.innerStyle, {
|
||||
minWidth: column.minWidth + 'px'
|
||||
})}
|
||||
>
|
||||
{typeof Cell === 'function' ? (
|
||||
<Cell
|
||||
{...rowInfo}
|
||||
value={rowInfo.rowValues[column.id]}
|
||||
/>
|
||||
) : typeof Cell !== 'undefined' ? Cell
|
||||
: rowInfo.rowValues[column.id]}
|
||||
</div>
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
)
|
||||
})}
|
||||
{padRows.map((row, i) => {
|
||||
return (
|
||||
<TrComponent
|
||||
key={i}
|
||||
className={classnames(this.props.trClassName, '-padRow')}
|
||||
style={this.props.trStyle}
|
||||
>
|
||||
{decoratedColumns.map((column, i2) => {
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
return (
|
||||
<TdComponent
|
||||
key={i2}
|
||||
className={classnames(column.className, {hidden: !show})}
|
||||
style={Object.assign({}, this.props.tdStyle, column.style)}
|
||||
>
|
||||
<div
|
||||
className={classnames(column.innerClassName, '-td-inner')}
|
||||
style={Object.assign({}, column.innerStyle, {
|
||||
minWidth: column.minWidth + 'px'
|
||||
})}
|
||||
> </div>
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
</TrComponent>
|
||||
)
|
||||
})}
|
||||
</TbodyComponent>
|
||||
</TableComponent>
|
||||
{this.props.showPagination && (
|
||||
<Pagination
|
||||
currentPage={currentPage}
|
||||
pagesLength={pagesLength}
|
||||
pageSize={pageSize}
|
||||
showPageSizeOptions={this.props.showPageSizeOptions}
|
||||
pageSizeOptions={this.props.pageSizeOptions}
|
||||
showPageJump={this.props.showPageJump}
|
||||
canPrevious={canPrevious}
|
||||
canNext={canNext}
|
||||
previousText={this.props.previousText}
|
||||
nextText={this.props.nextText}
|
||||
pageText={this.props.pageText}
|
||||
ofText={this.props.ofText}
|
||||
rowsText={this.props.rowsText}
|
||||
previousComponent={PreviousComponent}
|
||||
nextComponent={NextComponent}
|
||||
//
|
||||
onChange={this.setPage}
|
||||
onPageSizeChange={this.setPageSize}
|
||||
/>
|
||||
)}
|
||||
<LoadingComponent {...this.props} />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
// User actions
|
||||
setPage (page) {
|
||||
onPageChange (page) {
|
||||
const { onPageChange } = this.props
|
||||
if (onPageChange) {
|
||||
return onPageChange(page)
|
||||
}
|
||||
this.setState({
|
||||
visibleSubComponents: [],
|
||||
page
|
||||
}, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
},
|
||||
setPageSize (pageSize) {
|
||||
const currentPageSize = this.getStateOrProp('pageSize')
|
||||
const currentPage = this.getPropOrState('page')
|
||||
const currentRow = currentPageSize * currentPage
|
||||
const page = Math.floor(currentRow / pageSize)
|
||||
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,
|
||||
page
|
||||
pageSize: newPageSize,
|
||||
page: newPage
|
||||
}, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
|
||||
+77
-94
@@ -2,90 +2,37 @@
|
||||
|
||||
$easeOutQuad = cubic-bezier(0.250, 0.460, 0.450, 0.940)
|
||||
$easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
$expandSize = 7px
|
||||
|
||||
.ReactTable
|
||||
position:relative
|
||||
table
|
||||
border: 1px solid alpha(black, .1)
|
||||
*
|
||||
box-sizing: border-box
|
||||
.rt-table
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
width: 100%
|
||||
border-collapse: collapse
|
||||
border: 1px solid alpha(black, .1)
|
||||
display: block
|
||||
overflow-x: auto
|
||||
|
||||
.-td
|
||||
.-th
|
||||
&-inner
|
||||
white-space: nowrap
|
||||
text-overflow: ellipsis
|
||||
padding: 7px 5px
|
||||
overflow: hidden
|
||||
z-index:0
|
||||
transition: .3s ease
|
||||
transition-property: width, min-width, padding, opacity
|
||||
|
||||
th
|
||||
td
|
||||
&:hover
|
||||
.-td
|
||||
.-th
|
||||
&-inner
|
||||
position:relative
|
||||
overflow:visible
|
||||
z-index:1
|
||||
text-shadow:
|
||||
0 0 1px white,
|
||||
0 0 2px white,
|
||||
1px 0 3px white,
|
||||
1px 0 4px white,
|
||||
2px 0 5px white,
|
||||
2px 0 6px white,
|
||||
3px 0 7px white,
|
||||
3px 0 8px white,
|
||||
4px 0 9px white,
|
||||
4px 0 10px white,
|
||||
5px 0 11px white,
|
||||
5px 0 12px white,
|
||||
6px 0 13px white,
|
||||
6px 0 14px white,
|
||||
7px 0 15px white,
|
||||
7px 0 16px white,
|
||||
8px 0 17px white,
|
||||
8px 0 18px white,
|
||||
9px 0 19px white,
|
||||
9px 0 20px white
|
||||
|
||||
> *
|
||||
text-shadow: none
|
||||
|
||||
&.-hidden
|
||||
border:0 !important
|
||||
opacity: 0 !important
|
||||
.-th-inner
|
||||
.-td-inner
|
||||
width: 0 !important
|
||||
min-width: 0 !important
|
||||
padding: 0 !important
|
||||
|
||||
thead
|
||||
box-shadow: 0px 5px 20px 0 alpha(black, .1)
|
||||
z-index: 0
|
||||
overflow: auto
|
||||
|
||||
.rt-thead
|
||||
display: flex
|
||||
flex-direction: column
|
||||
&.-headerGroups
|
||||
background: alpha(black, .03)
|
||||
border-bottom: 1px solid alpha(black, .05)
|
||||
|
||||
th
|
||||
td
|
||||
background: alpha(black, .03)
|
||||
&.-header
|
||||
box-shadow: 0 2px 15px 0px alpha(black, .15)
|
||||
|
||||
tr
|
||||
.rt-tr
|
||||
text-align:center
|
||||
|
||||
th
|
||||
td
|
||||
width: 1%
|
||||
background: white
|
||||
font-weight:500
|
||||
color: $darkColor
|
||||
.rt-th
|
||||
.rt-td
|
||||
color: black
|
||||
border-right: 1px solid alpha(black, .05)
|
||||
transition box-shadow .3s $easeOutBack
|
||||
box-shadow:inset 0 0 0 0 transparent
|
||||
@@ -95,40 +42,81 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
box-shadow:inset 0 -3px 0 0 alpha(black, .6)
|
||||
&.-cursor-pointer
|
||||
cursor: pointer
|
||||
|
||||
tbody
|
||||
z-index:0
|
||||
tr
|
||||
&:last-child
|
||||
border-right: 0
|
||||
.rt-tbody
|
||||
display: flex
|
||||
flex-direction: column
|
||||
// z-index:0
|
||||
.rt-tr-group
|
||||
border-bottom: solid 1px alpha(black, .05)
|
||||
&:last-child
|
||||
border-bottom: 0
|
||||
|
||||
&:first-child td
|
||||
box-shadow: inset 0 20px 20px -20px alpha(black, .2)
|
||||
td
|
||||
.rt-td
|
||||
border-right:1px solid alpha(black, .02)
|
||||
&:last-child
|
||||
border-right:0
|
||||
.rt-tr-group
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
.rt-tr
|
||||
display: inline-flex
|
||||
.rt-th
|
||||
.rt-td
|
||||
flex: 1 0 0px
|
||||
white-space: nowrap
|
||||
text-overflow: ellipsis
|
||||
padding: 7px 5px
|
||||
overflow: hidden
|
||||
transition: .3s ease
|
||||
transition-property: width, min-width, padding, opacity
|
||||
|
||||
&.striped
|
||||
tbody tr:nth-child(even)
|
||||
&.-hidden
|
||||
width: 0 !important
|
||||
min-width: 0 !important
|
||||
padding: 0 !important
|
||||
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)
|
||||
|
||||
&.-striped
|
||||
.rt-tr-group:nth-child(even)
|
||||
background: alpha(black, .03)
|
||||
&.highlight
|
||||
tbody tr:hover
|
||||
&.-highlight
|
||||
.rt-tr-group:hover
|
||||
background: alpha(black, .05)
|
||||
|
||||
.-pagination
|
||||
width:100%
|
||||
z-index: 1
|
||||
display:flex
|
||||
justify-content: space-between
|
||||
align-items: center
|
||||
align-items: stretch
|
||||
flex-wrap: wrap
|
||||
padding-top:3px
|
||||
padding: 3px
|
||||
box-shadow: 0 0px 15px 0px alpha(black, .1)
|
||||
|
||||
.-btn
|
||||
appearance:none
|
||||
display:block
|
||||
width:100%
|
||||
height: 100%
|
||||
border: 0
|
||||
border-radius: 3px
|
||||
padding: 6px
|
||||
@@ -147,11 +135,6 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
background: alpha(black, .3)
|
||||
color: white
|
||||
|
||||
.-previous
|
||||
.-center
|
||||
.-next
|
||||
margin:3px 0
|
||||
|
||||
.-previous
|
||||
.-next
|
||||
flex: 1
|
||||
@@ -169,7 +152,7 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
|
||||
.-pageInfo
|
||||
display: inline-block
|
||||
margin: 0 10px 3px
|
||||
margin: 3px 10px
|
||||
white-space: nowrap
|
||||
|
||||
.-pageJump
|
||||
@@ -179,7 +162,7 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
text-align:center
|
||||
|
||||
.-pageSizeOptions
|
||||
margin:0 10px 3px
|
||||
margin: 3px 10px
|
||||
|
||||
|
||||
.-loading
|
||||
|
||||
+16
-14
@@ -10,11 +10,11 @@ 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)
|
||||
@@ -22,39 +22,41 @@ 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()
|
||||
const page = this.state.page
|
||||
this.changePage(page === '' ? this.props.currentPage : page)
|
||||
this.changePage(page === '' ? this.props.page : page)
|
||||
},
|
||||
render () {
|
||||
const {
|
||||
currentPage,
|
||||
// Computed
|
||||
pagesLength,
|
||||
// Props
|
||||
page,
|
||||
showPageSizeOptions,
|
||||
pageSizeOptions,
|
||||
pageSize,
|
||||
showPageJump,
|
||||
canPrevious,
|
||||
canNext,
|
||||
onPageSizeChange
|
||||
onPageSizeChange,
|
||||
className,
|
||||
PreviousComponent = defaultButton,
|
||||
NextComponent = defaultButton
|
||||
} = this.props
|
||||
|
||||
const PreviousComponent = this.props.previousComponent || defaultButton
|
||||
const NextComponent = this.props.nextComponent || defaultButton
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames(this.props.paginationClassName, '-pagination')}
|
||||
className={classnames(className, '-pagination')}
|
||||
style={this.props.paginationStyle}
|
||||
>
|
||||
<div className='-previous'>
|
||||
<PreviousComponent
|
||||
onClick={(e) => {
|
||||
if (!canPrevious) return
|
||||
this.changePage(currentPage - 1)
|
||||
this.changePage(page - 1)
|
||||
}}
|
||||
disabled={!canPrevious}
|
||||
>
|
||||
@@ -81,8 +83,8 @@ export default React.createClass({
|
||||
onBlur={this.applyPage}
|
||||
/>
|
||||
</form>
|
||||
) : (
|
||||
<span className='-currentPage'>{currentPage + 1}</span>
|
||||
) : (
|
||||
<span className='-currentPage'>{page + 1}</span>
|
||||
)} {this.props.ofText} <span className='-totalPages'>{pagesLength}</span>
|
||||
</span>
|
||||
{showPageSizeOptions && (
|
||||
@@ -108,7 +110,7 @@ export default React.createClass({
|
||||
<NextComponent
|
||||
onClick={(e) => {
|
||||
if (!canNext) return
|
||||
this.changePage(currentPage + 1)
|
||||
this.changePage(page + 1)
|
||||
}}
|
||||
disabled={!canNext}
|
||||
>
|
||||
|
||||
+23
-1
@@ -1,3 +1,6 @@
|
||||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
//
|
||||
export default {
|
||||
get,
|
||||
takeRight,
|
||||
@@ -6,7 +9,9 @@ export default {
|
||||
range,
|
||||
clone,
|
||||
remove,
|
||||
getFirstDefined
|
||||
getFirstDefined,
|
||||
sum,
|
||||
makeTemplateComponent
|
||||
}
|
||||
|
||||
function remove (a, b) {
|
||||
@@ -93,3 +98,20 @@ function getFirstDefined (...args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sum (arr) {
|
||||
return arr.reduce((a, b) => {
|
||||
return a + b
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function makeTemplateComponent (compClass) {
|
||||
return ({children, className, ...rest}) => (
|
||||
<div
|
||||
className={classnames(compClass, className)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Component } from 'jumpsuit'
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from 'components/codeHighlight'
|
||||
import ReactTable from 'react-table'
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../lib/index'
|
||||
|
||||
// Let's mock some data to play around with
|
||||
const rawData = _.map(_.range(3424), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numLen: 0 }),
|
||||
@@ -39,7 +38,7 @@ const requestData = (pageSize, page, sorting) => {
|
||||
})
|
||||
}
|
||||
|
||||
export default Component({
|
||||
const ServerSide = React.createClass({
|
||||
getInitialState () {
|
||||
// To handle our data server-side, we need a few things in the state to help us out:
|
||||
return {
|
||||
@@ -86,7 +85,7 @@ export default Component({
|
||||
}]
|
||||
}]}
|
||||
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
|
||||
@@ -97,18 +96,22 @@ export default Component({
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{getCode()}</CodeHighlight>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
export default () => (
|
||||
<ServerSide />
|
||||
)
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
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 {
|
||||
@@ -0,0 +1,85 @@
|
||||
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(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
|
||||
data={data}
|
||||
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={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
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(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
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</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,14 @@
|
||||
import React from 'react'
|
||||
import banner from '../../media/Banner.png'
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<a href='https://github.com/tannerlinsley/react-table' target='_blank'>
|
||||
<img src={banner} className='logo' />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import '../utils/prism'
|
||||
|
||||
export default React.createClass({
|
||||
render () {
|
||||
const { language, children } = this.props
|
||||
return (
|
||||
<pre>
|
||||
<code className={'language-' + (language || 'jsx')}>
|
||||
{children()}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
},
|
||||
componentDidMount () {
|
||||
window.Prism.highlightAll()
|
||||
},
|
||||
componentDidUpdate () {
|
||||
window.Prism.highlightAll()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,138 @@
|
||||
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #a67f59;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"root": "dist",
|
||||
"root": "storybook-static",
|
||||
"routes": [{
|
||||
"src": "/**",
|
||||
"dest": "index.html"
|
||||
Reference in New Issue
Block a user