Compare commits

..
35 Commits
Author SHA1 Message Date
Tanner Linsley ecd660ef10 3.2.0 2017-01-09 11:57:51 -07:00
DimitryandTanner Linsley be951a3252 onTrClick (#23)
* README: correct watch command

* Add onTrClick handler

* react soften peerDependency: ^15.x.x
2017-01-09 11:38:22 -07:00
Lukas Gisder-DubéandTanner Linsley f195b3243d added props for more pagination customization (#19) 2016-12-15 07:02:25 -07:00
Tanner LinsleyandGitHub 19a0187720 Update README.md 2016-12-08 11:59:46 -07:00
Tanner Linsley d8e5188d94 3.1.4 2016-12-07 13:00:39 -07:00
Tanner Linsley 8c79bf95df Page Size fix 2016-12-07 13:00:27 -07:00
Tanner Linsley 6053c48781 3.1.3 2016-12-07 12:55:10 -07:00
Tanner Linsley 8f1c8774f2 Fixes and use Yarn 2016-12-07 12:55:03 -07:00
Tanner Linsley d5795fb5ac Readme Update 2016-12-06 23:19:00 -07:00
Tanner Linsley 8abbefa680 Readme updates 2016-12-06 13:17:38 -07:00
Tanner Linsley 4db644941a Badges 2016-12-06 13:15:55 -07:00
Pedro Tacla YamadaandTanner Linsley 6905ccae72 Fix typo when overriding pagination components (#17) 2016-11-15 08:56:05 -07:00
Tanner LinsleyandGitHub e832bf52b0 Update README.md 2016-11-07 13:44:31 -07:00
Tanner Linsley 3432fefce2 Example Update 2016-11-02 15:34:00 -06:00
Tanner Linsley 2abcc86954 3.1.2 2016-11-02 15:20:48 -06:00
Tanner Linsley 610972d99e Pagination Style fixes 2016-11-02 15:20:43 -06:00
Tanner Linsley c99796342b 3.1.1 2016-11-02 15:07:27 -06:00
Tanner Linsley 1b4d8bd45f Fix pagination not showing with 0 pagesLength 2016-11-02 15:07:20 -06:00
Tanner Linsley e922a43741 No example/dist 2016-11-02 13:08:20 -06:00
Tanner Linsley 75317c2251 Example Update 2016-11-02 13:07:05 -06:00
Tanner Linsley e531ef1f64 Readme Updates 2016-11-02 12:12:29 -06:00
Tanner Linsley 598d33410a 3.1.0 2016-11-02 12:09:57 -06:00
Tanner Linsley 57ac1f142d Pagination Features
- Page Jumping
- Page Size Changing
- Updated Examples
2016-11-02 12:09:52 -06:00
Tanner Linsley e181f8e3d1 Readme Update 2016-11-01 14:44:58 -06:00
Tanner Linsley 5e19459eba Readme updates 2016-10-31 12:20:03 -06:00
Tanner Linsley cad0ac49cb Readme updates 2016-10-31 12:17:40 -06:00
Tanner Linsley b5d17cdbce Readme Update 2016-10-31 11:12:48 -06:00
Tanner Linsley a5d9e15b5d Readme update 2016-10-31 11:11:01 -06:00
Tanner LinsleyandGitHub c9cf436576 Update async.js 2016-10-31 10:39:28 -06:00
Tanner Linsley ece0ddc8a4 Readme Updates 2016-10-31 02:00:41 -06:00
Tanner Linsley dbc90c2e63 Readme updates 2016-10-31 01:55:32 -06:00
Tanner Linsley 2b0e1eb8a7 Readme Updates 2016-10-31 01:53:54 -06:00
Tanner Linsley 3d0f38f2c5 3.0.0 2016-10-31 01:49:43 -06:00
Tanner Linsley 516b88468e Major changes for server-side data 2016-10-31 01:49:43 -06:00
Alex SimoesandTanner Linsley 07cd241ced Use curly brackets here instead of square brackets (#7) 2016-10-27 19:09:58 -06:00
21 changed files with 6933 additions and 59504 deletions
+1
View File
@@ -3,3 +3,4 @@ lib/
react-table.js
react-table.css
*.log
example/dist/
+49 -19
View File
@@ -1,17 +1,22 @@
![react-table](https://github.com/tannerlinsley/react-table/raw/master/media/Banner.png)
<div align="center">
<a href="https://github.com/tannerlinsley/react-table"><img src="https://github.com/tannerlinsley/react-table/raw/master/media/Banner.png" alt="React Table Logo" style="width:450px;"/></a>
<br />
<br />
</div>
# react-table
A fast, lightweight, opinionated table and datagrid built on React
[![Build Status](https://travis-ci.org/tannerlinsley/react-table.svg?branch=master)](https://travis-ci.org/tannerlinsley/react-table)
[![react-table on Slack](https://img.shields.io/badge/slack-react--table-blue.svg)](https://react-table-slack.herokuapp.com/)
[![Build Status](https://travis-ci.org/tannerlinsley/react-table.svg?branch=master)](https://travis-ci.org/tannerlinsley/react-table) [![npm](https://img.shields.io/npm/dm/react-table.svg)](https://npmjs.com/packag/react-table) [![react-table on Slack](https://img.shields.io/badge/slack-react--table-blue.svg)](https://react-table-slack.herokuapp.com/) [![GitHub stars](https://img.shields.io/github/stars/tannerlinsley/react-table.svg?style=social&label=Star)](https://github.com/tannerlinsley/react-table) [![Twitter Follow](https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow)](https://twitter.com/tannerlinsley)
## Features
- Lightweight at 3kb (and just 2kb more for styles)
- 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
- 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
## [Demo](http://react-table.zabapps.com)
@@ -51,27 +56,28 @@ const data = [{
const columns = [{
header: 'Name',
accessor: 'name',
accessor: 'name' // String-based value accessors !
}, {
header: 'Age',
accessor: 'age'
accessor: 'age',
render: props => <span className='number'>props.value</span> // Custom cell components!
}, {
header: 'Friend Name',
accessor: d => d.friend.name
accessor: d => d.friend.name // Custom value accessors!
}, {
header: 'Friend Age',
header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age'
}]
<ReactTable
data=[data]
data={data}
columns={columns}
/>
```
<a name="data"></a>
## Data
Every React-Table instance requires you to set the `data` prop. To use client-side 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 if 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 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!
<a name="default-props"></a>
@@ -80,12 +86,24 @@ These are the default props for the main react component `<ReactTable />`
```javascript
{
// General
pageSize: 20,
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)
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
// Callbacks
onChange: (state, instance) => null, // Anytime the internal state of the table changes, this will fire
onTrClick: (row, event) => null, // Handler for row click events
// Text
previousText: 'Previous',
nextText: 'Next'
nextText: 'Next',
pageText: 'Page',
ofText: 'of',
rowsText: 'rows',
// Classes
className: '-striped -highlight', // The most top level className for the component
@@ -132,7 +150,7 @@ Or just define them on the component per-instance
<a name="columns"></a>
## Columns
Every React-Table instance requires a `columns` prop, which is an array of objects containing the following properties
`<ReactTable/>` requires a `columns` prop, which is an array of objects with the following properties
```javascript
[{
@@ -140,8 +158,8 @@ Every React-Table instance requires a `columns` prop, which is an array of objec
accessor: 'propertyName' or Accessor eg. (row) => row.propertyName,
id: 'myProperty', // Conditional - A unique ID is required if the accessor is not a string or if you would like to override the column name used in server-side calls
sortable: true,
sort: 'asc' or 'desc',
show: 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
// Cell Options
@@ -198,7 +216,7 @@ If you want to handle pagination, and sorting on the server, `react-table` makes
1. Feed React Table `data` from somewhere dynamic. eg. `state`, a redux store, etc...
1. Add `manual` as a prop. This informs React Table that you'll be handling sorting and pagination server-side
1. Subscribe to the `onChange` prop. This function is called any time sorting or pagination is changed by the user
1. Subscribe to the `onChange` prop. This function is called at `compomentDidMount` and any time sorting or pagination is changed by the user
1. In the `onChange` callback, request your data using the provided information in the params of the function (state and instance)
1. Update your data with the rows to be displayed
1. Optionally set how many pages there are total
@@ -208,17 +226,23 @@ If you want to handle pagination, and sorting on the server, `react-table` makes
...
data={this.state.data} // should default to []
pages={this.state.pages} // should default to -1 (which means we don't know how many pages we have)
loading={this.state.loading}
manual // informs React Table that you'll be handling sorting and pagination server-side
onChange={(state, instance) => {
// show the loading overlay
this.setState({loading: true})
// fetch your data
Axios.post('mysite.com/data', {
page: state.page,
pageSize: state.pageSize,
sorting: state.sorting
})
.then((res) => {
// Update react-table
this.setState({
data: res.data.rows,
pages: res.data.pages
pages: res.data.pages,
loading: false
})
})
}}
@@ -267,7 +291,7 @@ If you would like to help develop a suggested feature follow these steps:
- Fork this repo
- `npm install`
- `npm watch`
- `npm run watch`
- Implement your changes to files in the `src/` directory
- Submit PR for review
@@ -277,6 +301,12 @@ If you would like to preview your changes, you can link and utilize the example
- `cd example`
- `npm install`
- `npm link react-table`
- `npm watch`
- `npm run watch`
- Make changes to the example in `src/screens/index.js` if needed
- View changes at `localhost:8000`
## Used By
<a href='https://nozzle.io'>
<img src='https://nozzle.io/img/logo-blue.png' alt='Nozzle Logo' style='width:300px;'/>
</a>
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

-171
View File
File diff suppressed because one or more lines are too long
-59138
View File
File diff suppressed because one or more lines are too long
-13
View File
@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<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>
+5 -3
View File
@@ -10,7 +10,8 @@
},
"scripts": {
"watch": "jumpsuit watch",
"build": "jumpsuit build"
"build": "jumpsuit build",
"deploy": "jumpsuit build && zab deploy"
},
"devDependencies": {
"nib": "^1.1.0",
@@ -18,9 +19,10 @@
"stylus": "^0.54.5"
},
"dependencies": {
"jumpsuit": "^0.7.5",
"jumpsuit": "^1.3.3",
"lodash": "^4.16.4",
"namor": "^0.3.0",
"react-table": "^2.0.0"
"react-syntax-highlighter": "^3.0.0",
"react-table": "^3.1.2"
}
}
+16 -4
View File
@@ -1,5 +1,17 @@
import { Render } from 'jumpsuit'
// import App from 'screens/async'
import App from 'screens/index'
import { Render, Router, Route, IndexRoute } from 'jumpsuit'
//
import Layout from 'components/layout'
import Simple from 'screens/simple'
import ServerSide from 'screens/serverSide'
Render(null, <App />)
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
})
+39 -6
View File
@@ -11,7 +11,7 @@ global-reset()
// vendor styles
// -----------------------------------------------------------------------------
@import '../node_modules/react-table/react-table.css'
@import '../node_modules/react-table/src/index'
// -----------------------------------------------------------------------------
// variables
@@ -34,7 +34,6 @@ body
background: white
font-family: $fnt-open-sans
font-weight: 300
padding-bottom: 50px
h1
font-size: 2.5em
@@ -50,6 +49,7 @@ strong
.logo
width: 400px
max-width: 100%
.container
display: flex
@@ -63,11 +63,34 @@ strong
font-size: 20px
padding: 10px
.table-wrap
width: 700px
.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
border-radius: 5px
box-shadow: 0 0 20px 0 alpha(black, .2)
margin: 5px
background: alpha(black, .4)
color: white
border-radius: 3px
transition: all .2s ease-out
&.active
&:hover
background: alpha(black, .9)
.ReactTable
thead
@@ -77,3 +100,13 @@ strong
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
+1
View File
@@ -2,6 +2,7 @@
<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>
+11
View File
@@ -0,0 +1,11 @@
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,43 +1,13 @@
import { Component } from 'jumpsuit'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from 'react-table'
import { Component, Link } from 'jumpsuit'
export default Component({
render () {
const data = _.map(_.range(5000), 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 className='container'>
<div style={{textAlign: 'center'}}>
<h1>
<span style={{position: 'absolute', textIndent: '-9999em'}}>
react-table <strong>demo</strong>
react-table
</span>
<img src='/Banner.png' className='logo' />
</h1>
@@ -66,15 +36,22 @@ export default Component({
<br />
<br />
</div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
/>
<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 style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
<div className='viewport'>
{this.props.children}
</div>
</div>
)
@@ -2,10 +2,11 @@ import { Component } from 'jumpsuit'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from 'components/codeHighlight'
import ReactTable from 'react-table'
// Let's mock some data to play around with
const rawData = _.map(_.range(1000), d => {
const rawData = _.map(_.range(3424), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
@@ -64,39 +65,7 @@ export default Component({
},
render () {
return (
<div className='container'>
<div style={{textAlign: 'center'}}>
<h1>
<span style={{position: 'absolute', textIndent: '-9999em'}}>
react-table <strong>server-side demo</strong>
</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>
<div className='table-wrap'>
<ReactTable
columns={[{
@@ -117,7 +86,7 @@ export default Component({
}]
}]}
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
pageSize={5}
pageSize={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
@@ -128,7 +97,75 @@ export default Component({
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{getCode()}</CodeHighlight>
</div>
)
}
})
function getCode () {
return `
import ReactTable from 'react-table'
import Axios from 'axios'
export default React.creatClass({
getInitialState () {
// To handle our data server-side, we need to keep track of our table state
return {
data: [],
pages: null,
loading: true
}
},
fetchData (state, instance) {
// Whenever the table model changes (sorting, pagination, etc), 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 loading notice, or show you're own loading bar if you want.
this.setState({loading: true})
// Request the data from a server however you want! Be sure to send the bits of the table model that it may neeed.
Axios.post('mysite.com/data', {
pageSize: state.pageSize,
page: state.page,
sorting: state.sorting
})
.then((res) => {
// Now update your state!
this.setState({
data: res.rows,
pages: res.pages,
loading: false
})
})
},
render () {
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 (
<ReactTable
columns={columns}
manual // This forces table not to paginate or sort automatically, so we can handle things server-side
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
onChange={this.fetchData} // Request new data when things change
/>
)
}
})
`
}
+103
View File
@@ -0,0 +1,103 @@
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
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -1,4 +1,8 @@
{
"name": "react-table",
"root": "dist"
"root": "dist",
"routes": [{
"src": "/**",
"dest": "index.html"
}]
}
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "3.0.0",
"version": "3.2.0",
"description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -16,6 +16,7 @@
],
"main": "lib/index.js",
"files": [
"src/",
"lib/",
"react-table.js",
"react-table.css",
@@ -34,7 +35,7 @@
"classnames": "^2.2.5"
},
"peerDependencies": {
"react": "^15.3.1"
"react": "^15.x.x"
},
"devDependencies": {
"babel-cli": "6.14.0",
+93 -62
View File
@@ -3,20 +3,19 @@ import classnames from 'classnames'
//
import _ from './utils'
const defaultButton = (props) => (
<button {...props} className='-btn'>{props.children}</button>
)
import Pagination from './pagination'
export const ReactTableDefaults = {
// State
// General
data: [],
loading: false,
pageSize: 20,
minRows: 0,
showPagination: true,
showPageSizeOptions: true,
pageSizeOptions: [5, 10, 20, 25, 50, 100],
showPageJump: true,
// Callbacks
onChange: () => null,
onPageChange: () => null,
onSort: () => null,
// Classes
className: '-striped -highlight',
tableClassName: '',
@@ -24,6 +23,7 @@ export const ReactTableDefaults = {
tbodyClassName: '',
trClassName: '',
trClassCallback: d => null,
onTrClick: () => null,
thClassName: '',
thGroupClassName: '',
tdClassName: '',
@@ -55,15 +55,32 @@ export const ReactTableDefaults = {
previousText: 'Previous',
nextText: 'Next',
loadingText: 'Loading...',
pageText: 'Page',
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) => <th {...props}>{props.children}</th>,
thComponent: (props) => {
const {toggleSort, ...rest} = props
return (
<th {...rest} onClick={e => {
toggleSort && toggleSort(e)
}}>{props.children}</th>
)
},
tdComponent: (props) => <td {...props}>{props.children}</td>,
previousComponent: null,
nextComponent: null
nextComponent: null,
loadingComponent: props => (
<div className={classnames('-loading', {'-active': props.loading})}>
<div className='-loading-inner'>
{props.loadingText}
</div>
</div>
)
}
export default React.createClass({
@@ -73,7 +90,6 @@ export default React.createClass({
getInitialState () {
return {
page: 0,
pages: -1,
sorting: false
}
},
@@ -82,12 +98,18 @@ export default React.createClass({
},
fireOnChange () {
this.props.onChange({
page: _.getFirstDefined(this.props.page, this.state.page),
pageSize: this.props.pageSize,
pages: this.props.pages,
page: this.getPropOrState('page'),
pageSize: this.getStateOrProp('pageSize'),
pages: this.getPagesLength(),
sorting: this.getSorting()
}, this)
},
getPropOrState (key) {
return _.getFirstDefined(this.props[key], this.state[key])
},
getStateOrProp (key) {
return _.getFirstDefined(this.state[key], this.props[key])
},
getInitSorting (columns) {
if (!columns) {
return []
@@ -140,6 +162,13 @@ export default React.createClass({
getSorting (columns) {
return this.props.sorting || (this.state.sorting && this.state.sorting.length ? this.state.sorting : this.getInitSorting(columns))
},
getPagesLength () {
return this.props.manual ? this.props.pages
: Math.ceil(this.props.data.length / this.getStateOrProp('pageSize'))
},
getMinRows () {
return _.getFirstDefined(this.props.minRows, this.getStateOrProp('pageSize'))
},
render () {
// Build Columns
const decoratedColumns = []
@@ -200,17 +229,22 @@ export default React.createClass({
})
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 pagesLength = this.props.manual ? this.props.pages : Math.ceil(data.length / this.props.pageSize)
const startRow = this.props.pageSize * this.state.page
const endRow = startRow + this.props.pageSize
const startRow = pageSize * currentPage
const endRow = startRow + pageSize
const pageRows = this.props.manual ? data : data.slice(startRow, endRow)
const padRows = pagesLength > 1 ? _.range(this.props.pageSize - pageRows.length)
: this.props.minRows ? _.range(Math.max(this.props.minRows - pageRows.length, 0))
const minRows = this.getMinRows()
const padRows = pagesLength > 1 ? _.range(pageSize - pageRows.length)
: minRows ? _.range(Math.max(minRows - pageRows.length, 0))
: []
const canPrevious = this.state.page > 0
const canNext = this.state.page + 1 < pagesLength
const canPrevious = currentPage > 0
const canNext = currentPage + 1 < pagesLength
const TableComponent = this.props.tableComponent
const TheadComponent = this.props.theadComponent
@@ -218,9 +252,9 @@ export default React.createClass({
const TrComponent = this.props.trComponent
const ThComponent = this.props.thComponent
const TdComponent = this.props.tdComponent
const PreviousComponent = this.props.previousComponent || defaultButton
const NextComponent = this.props.nextComponent || defaultButton
const PreviousComponent = this.props.previousComponent
const NextComponent = this.props.nextComponent
const LoadingComponent = this.props.loadingComponent
return (
<div
@@ -289,7 +323,7 @@ export default React.createClass({
}
)}
style={Object.assign({}, this.props.thStyle, column.headerStyle)}
onClick={(e) => {
toggleSort={(e) => {
column.sortable && this.sortColumn(column, e.shiftKey)
}}
>
@@ -325,6 +359,7 @@ export default React.createClass({
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))}
>
@@ -348,7 +383,7 @@ export default React.createClass({
{...rowInfo}
value={rowInfo.rowValues[column.id]}
/>
) : typeof Cell !== 'undefined' ? Cell
) : typeof Cell !== 'undefined' ? Cell
: rowInfo.rowValues[column.id]}
</div>
</TdComponent>
@@ -386,37 +421,29 @@ export default React.createClass({
})}
</TbodyComponent>
</TableComponent>
{pagesLength > 1 && (
<div
className={classnames(this.props.paginationClassName, '-pagination')}
style={this.props.paginationStyle}
>
<div className='-left'>
<PreviousComponent
onClick={canPrevious && ((e) => this.previousPage(e))}
disabled={!canPrevious}
>
{this.props.previousText}
</PreviousComponent>
</div>
<div className='-center'>
Page {this.state.page + 1} of {pagesLength}
</div>
<div className='-right'>
<NextComponent
onClick={canNext && ((e) => this.nextPage(e))}
disabled={!canNext}
>
{this.props.nextText}
</NextComponent>
</div>
</div>
{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}
/>
)}
<div className={classnames('-loading', {'-active': this.props.loading})}>
<div className='-loading-inner'>
{this.props.loadingText}
</div>
</div>
<LoadingComponent {...this.props} />
</div>
)
},
@@ -428,13 +455,17 @@ export default React.createClass({
this.fireOnChange()
})
},
nextPage (e) {
e.preventDefault()
this.setPage(this.state.page + 1)
},
previousPage (e) {
e.preventDefault()
this.setPage(this.state.page - 1)
setPageSize (pageSize) {
const currentPageSize = this.getStateOrProp('pageSize')
const currentPage = this.getPropOrState('page')
const currentRow = currentPageSize * currentPage
const page = Math.floor(currentRow / pageSize)
this.setState({
pageSize,
page
}, () => {
this.fireOnChange()
})
},
sortColumn (column, additive) {
const existingSorting = this.getSorting()
+55 -10
View File
@@ -120,10 +120,10 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
.-pagination
width:100%
display:flex
margin-top:5px
justify-content: space-between
align-items: center
flex-wrap: wrap
padding-top:3px
.-btn
appearance:none
@@ -147,21 +147,39 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
background: alpha(black, .3)
color: white
.-left
.-previous
.-center
.-right
flex: 1
// min-width:150px
margin-bottom:5px
.-next
margin:3px 0
.-left
.-right
.-previous
.-next
flex: 1
text-align: center
.-center
flex: 1.5
text-align:center
padding: 0 5px
margin-bottom:0
display: flex
flex-direction: row
flex-wrap: wrap
align-items: center
justify-content: space-around
.-pageInfo
display: inline-block
margin: 0 10px 3px
white-space: nowrap
.-pageJump
display:inline-block
input
width: 70px
text-align:center
.-pageSizeOptions
margin:0 10px 3px
.-loading
@@ -194,3 +212,30 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
pointer-events: all
> div
transform: translateY(50%)
input
select
appearance: none
border: 1px solid rgba(0,0,0,0.1)
background: white
padding: 5px 7px
font-size: inherit
border-radius: 3px
font-weight: normal
outline:none
.select-wrap
position:relative
display:inline-block
select
padding: 5px 15px 5px 7px
min-width:100px
&:after
content: ''
position: absolute
right: 8px
top: 50%
transform: translate(0, -50%)
border-color: #999 transparent transparent
border-style: solid
border-width: 5px 5px 2.5px
+121
View File
@@ -0,0 +1,121 @@
import React from 'react'
import classnames from 'classnames'
//
// import _ from './utils'
const defaultButton = (props) => (
<button {...props} className='-btn'>{props.children}</button>
)
export default React.createClass({
getInitialState () {
return {
page: this.props.currentPage
}
},
componentWillReceiveProps (nextProps) {
this.setState({page: nextProps.currentPage})
},
getSafePage (page) {
return Math.min(Math.max(page, 0), this.props.pagesLength - 1)
},
changePage (page) {
page = this.getSafePage(page)
this.setState({page})
this.props.onChange(page)
},
applyPage (e) {
e && e.preventDefault()
const page = this.state.page
this.changePage(page === '' ? this.props.currentPage : page)
},
render () {
const {
currentPage,
pagesLength,
showPageSizeOptions,
pageSizeOptions,
pageSize,
showPageJump,
canPrevious,
canNext,
onPageSizeChange
} = this.props
const PreviousComponent = this.props.previousComponent || defaultButton
const NextComponent = this.props.nextComponent || defaultButton
return (
<div
className={classnames(this.props.paginationClassName, '-pagination')}
style={this.props.paginationStyle}
>
<div className='-previous'>
<PreviousComponent
onClick={(e) => {
if (!canPrevious) return
this.changePage(currentPage - 1)
}}
disabled={!canPrevious}
>
{this.props.previousText}
</PreviousComponent>
</div>
<div className='-center'>
<span className='-pageInfo'>
{this.props.pageText} {showPageJump ? (
<form className='-pageJump'
onSubmit={this.applyPage}
>
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value
const page = val - 1
if (val === '') {
return this.setState({page: val})
}
this.setState({page: this.getSafePage(page)})
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
/>
</form>
) : (
<span className='-currentPage'>{currentPage + 1}</span>
)} {this.props.ofText} <span className='-totalPages'>{pagesLength}</span>
</span>
{showPageSizeOptions && (
<span className='select-wrap -pageSizeOptions'>
<select
onChange={(e) => onPageSizeChange(Number(e.target.value))}
value={pageSize}
>
{pageSizeOptions.map((option, i) => {
return (
<option
key={i}
value={option}>
{option} {this.props.rowsText}
</option>
)
})}
</select>
</span>
)}
</div>
<div className='-next'>
<NextComponent
onClick={(e) => {
if (!canNext) return
this.changePage(currentPage + 1)
}}
disabled={!canNext}
>
{this.props.nextText}
</NextComponent>
</div>
</div>
)
}
})
+3601
View File
File diff suppressed because it is too large Load Diff