New core styling, sub-components, React-Storybook instead of jumpsuit example

This commit is contained in:
Tanner Linsley
2017-01-11 16:23:49 -07:00
parent dd433f7d9c
commit e5689bc9d4
31 changed files with 3113 additions and 3391 deletions
+2
View File
@@ -4,3 +4,5 @@ react-table.js
react-table.css
*.log
example/dist/
storybook-static
+34
View File
@@ -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)
+6
View File
@@ -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;
}
+3
View File
@@ -0,0 +1,3 @@
body{
padding: 20px;
}
+48
View File
@@ -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;
}
+27
View File
@@ -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
}
+25 -9
View File
@@ -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
[![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)
@@ -16,9 +16,9 @@ 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)
@@ -28,6 +28,7 @@ A fast, lightweight, opinionated table and datagrid built on React
- [Columns](#columns)
- [Styles](#styles)
- [Header Groups](#header-groups)
- [Sub Tables & Components](#sub-tables--components)
- [Server-side Data](#server-side-data)
- [Multi-sort](#multi-sort)
- [Component Overrides](#component-overrides)
@@ -93,6 +94,7 @@ These are the default props for the main react component `<ReactTable />`
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
@@ -160,13 +162,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
// 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 +178,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
@@ -210,6 +208,24 @@ const columns = [{
}]
```
## 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}
pageSize={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>
)
}}
/>
```
<a name="server-side-data"></a>
## Server-side Data
If you want to handle pagination, and sorting on the server, `react-table` makes it easy on you.
-1
View File
@@ -1 +0,0 @@
# Jumpsuit Getting Started
-28
View File
@@ -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)
})
})
}
-28
View File
@@ -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"
}
}
-17
View File
@@ -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
})
-112
View File
@@ -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

-14
View File
@@ -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>
-11
View File
@@ -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>
)
}
})
-59
View File
@@ -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>
)
}
})
-103
View File
@@ -1,103 +0,0 @@
import { Component } from 'jumpsuit'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from 'components/codeHighlight'
import ReactTable from '../../../lib/index'
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
+14 -3
View File
@@ -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"
+214 -103
View File
@@ -1,10 +1,20 @@
import React from 'react'
import classnames from 'classnames'
import prefixAll from 'inline-style-prefixer/static'
//
import _ from './utils'
import Pagination from './pagination'
const makeTemplateComponent = (compClass) => ({children, className, ...rest}) => (
<div
className={classnames(compClass, className)}
{...rest}
>
{children}
</div>
)
export const ReactTableDefaults = {
// General
data: [],
@@ -14,6 +24,7 @@ export const ReactTableDefaults = {
showPageSizeOptions: true,
pageSizeOptions: [5, 10, 20, 25, 50, 100],
showPageJump: true,
expanderColumnWidth: 30,
// Callbacks
onChange: () => null,
onTrClick: () => null,
@@ -44,12 +55,11 @@ export const ReactTableDefaults = {
show: true,
className: '',
style: {},
innerClassName: '',
innerStyle: {},
headerClassName: '',
headerStyle: {},
headerInnerClassName: '',
headerInnerStyle: {}
headerInnerStyle: {},
minWidth: 100
},
// Text
previousText: 'Previous',
@@ -59,19 +69,33 @@ 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: makeTemplateComponent('rt-td'),
expanderComponent: ({isOpen, toggle, ...rest}) => {
return (
<div
className={classnames('rt-expander', isOpen && '-open')}
{...rest}
/>
)
},
tdComponent: (props) => <td {...props}>{props.children}</td>,
paginationComponent: Pagination,
previousComponent: null,
nextComponent: null,
@@ -91,7 +115,8 @@ export default React.createClass({
getInitialState () {
return {
page: 0,
sorting: false
sorting: false,
visibleSubComponents: {}
}
},
componentDidMount () {
@@ -171,6 +196,39 @@ export default React.createClass({
return _.getFirstDefined(this.props.minRows, this.getStateOrProp('pageSize'))
},
render () {
const {visibleSubComponents} = this.state
const {
className,
style,
tableClassName,
tableStyle,
theadGroupClassName,
theadStyle,
trClassName,
trStyle,
thClassname,
thStyle,
data,
theadClassName,
tbodyClassName,
tbodyStyle,
onTrClick,
trClassCallback,
trStyleCallback,
tdStyle,
showPagination,
showPageSizeOptions,
pageSizeOptions,
showPageJump,
previousText,
nextText,
pageText,
ofText,
rowsText,
paginationClassName,
expanderColumnWidth
} = this.props
// Build Columns
const decoratedColumns = []
const headerGroups = []
@@ -213,6 +271,8 @@ export default React.createClass({
}
})
const columnPercentage = 100 / decoratedColumns.length
if (hasHeaderGroups && currentSpan.length > 0) {
addHeader(currentSpan)
}
@@ -228,7 +288,7 @@ export default React.createClass({
})
return row
})
const data = this.props.manual ? accessedData : this.sortData(accessedData, sorting)
const resolvedData = this.props.manual ? accessedData : this.sortData(accessedData, sorting)
// Normalize state
const currentPage = this.getPropOrState('page')
@@ -238,7 +298,7 @@ export default React.createClass({
// Pagination
const startRow = pageSize * currentPage
const endRow = startRow + pageSize
const pageRows = this.props.manual ? data : data.slice(startRow, endRow)
const pageRows = this.props.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))
@@ -247,54 +307,67 @@ export default React.createClass({
const canPrevious = currentPage > 0
const canNext = currentPage + 1 < pagesLength
const PaginationComponent = this.props.paginationComponent
const TableComponent = this.props.tableComponent
const TheadComponent = this.props.theadComponent
const TbodyComponent = this.props.tbodyComponent
const TrGroupComponent = this.props.trGroupComponent
const TrComponent = this.props.trComponent
const ThComponent = this.props.thComponent
const TdComponent = this.props.tdComponent
const ExpanderComponent = this.props.expanderComponent
const PaginationComponent = this.props.paginationComponent
const PreviousComponent = this.props.previousComponent
const NextComponent = this.props.nextComponent
const LoadingComponent = this.props.loadingComponent
const SubComponent = this.props.subComponent
const rowWidth = (SubComponent ? expanderColumnWidth : 0) + _.sum(decoratedColumns.map(d => d.minWidth))
return (
<div
className={classnames(this.props.className, 'ReactTable')}
style={this.props.style}
className={classnames(className, 'ReactTable')}
style={style}
>
<TableComponent
className={classnames(this.props.tableClassName)}
style={this.props.tableStyle}
className={classnames(tableClassName)}
style={tableStyle}
>
{hasHeaderGroups && (
<TheadComponent
className={classnames(this.props.theadGroupClassName, '-headerGroups')}
style={this.props.theadStyle}
className={classnames(theadGroupClassName, '-headerGroups')}
style={Object.assign({}, theadStyle, {
minWidth: `${rowWidth}px`
})}
>
<TrComponent
className={this.props.trClassName}
style={this.props.trStyle}
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}
colSpan={column.columns.length}
className={classnames(this.props.thClassname, column.headerClassName)}
style={Object.assign({}, this.props.thStyle, column.headerStyle)}
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`
}))}
>
<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>
{typeof column.header === 'function' ? (
<column.header
data={resolvedData}
column={column}
/>
) : column.header}
</ThComponent>
)
})}
@@ -302,13 +375,24 @@ export default React.createClass({
</TheadComponent>
)}
<TheadComponent
className={classnames(this.props.theadClassName)}
style={this.props.theadStyle}
className={classnames(theadClassName, '-header')}
style={Object.assign({}, theadStyle, {
minWidth: `${rowWidth}px`
})}
>
<TrComponent
className={this.props.trClassName}
style={this.props.trStyle}
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
@@ -316,7 +400,7 @@ export default React.createClass({
<ThComponent
key={i}
className={classnames(
this.props.thClassname,
thClassname,
column.headerClassName,
sort ? (sort.asc ? '-sort-asc' : '-sort-desc') : '',
{
@@ -324,32 +408,30 @@ export default React.createClass({
'-hidden': !show
}
)}
style={Object.assign({}, this.props.thStyle, column.headerStyle)}
style={Object.assign({}, thStyle, column.headerStyle, prefixAll({
flex: `${columnPercentage} 0 auto`,
width: `${column.minWidth}px`
}))}
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>
{typeof column.header === 'function' ? (
<column.header
data={resolvedData}
column={column}
/>
) : column.header}
</ThComponent>
)
})}
</TrComponent>
</TheadComponent>
<TbodyComponent
className={classnames(this.props.tbodyClassName)}
style={this.props.tbodyStyle}
className={classnames(tbodyClassName)}
style={Object.assign({}, tbodyStyle, {
minWidth: `${rowWidth}px`
})}
>
{pageRows.map((row, i) => {
const rowInfo = {
@@ -359,26 +441,44 @@ export default React.createClass({
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)}
<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={() => {
this.setState({
visibleSubComponents: {
...visibleSubComponents,
[i]: !visibleSubComponents[i]
}
})
}}
>
<div
className={classnames(column.innerClassName, '-td-inner')}
style={Object.assign({}, column.innerStyle, {
minWidth: column.minWidth + 'px'
})}
<ExpanderComponent
isOpen={visibleSubComponents[i]}
/>
</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
@@ -387,34 +487,44 @@ export default React.createClass({
/>
) : typeof Cell !== 'undefined' ? Cell
: rowInfo.rowValues[column.id]}
</div>
</TdComponent>
)
})}
</TrComponent>
</TdComponent>
)
})}
</TrComponent>
{SubComponent && visibleSubComponents[i] ? (
SubComponent(rowInfo)
) : null}
</TrGroupComponent>
)
})}
{padRows.map((row, i) => {
return (
<TrComponent
key={i}
className={classnames(this.props.trClassName, '-padRow')}
style={this.props.trStyle}
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({}, this.props.tdStyle, column.style)}
style={Object.assign({}, tdStyle, column.style, {
flex: `${columnPercentage} 0 auto`,
width: `${column.minWidth}px`
})}
>
<div
className={classnames(column.innerClassName, '-td-inner')}
style={Object.assign({}, column.innerStyle, {
minWidth: column.minWidth + 'px'
})}
>&nbsp;</div>
&nbsp;
</TdComponent>
)
})}
@@ -423,28 +533,28 @@ export default React.createClass({
})}
</TbodyComponent>
</TableComponent>
{this.props.showPagination && (
{showPagination && (
<PaginationComponent
currentPage={currentPage}
pagesLength={pagesLength}
pageSize={pageSize}
showPageSizeOptions={this.props.showPageSizeOptions}
pageSizeOptions={this.props.pageSizeOptions}
showPageJump={this.props.showPageJump}
showPageSizeOptions={showPageSizeOptions}
pageSizeOptions={pageSizeOptions}
showPageJump={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}
previousText={previousText}
nextText={nextText}
pageText={pageText}
ofText={ofText}
rowsText={rowsText}
previousComponent={PreviousComponent}
nextComponent={NextComponent}
//
onChange={this.setPage}
onPageSizeChange={this.setPageSize}
//
className={this.props.paginationClassName}
className={paginationClassName}
/>
)}
<LoadingComponent {...this.props} />
@@ -454,6 +564,7 @@ export default React.createClass({
// User actions
setPage (page) {
this.setState({
visibleSubComponents: {},
page
}, () => {
this.fireOnChange()
+77 -94
View File
@@ -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
+8 -1
View File
@@ -6,7 +6,8 @@ export default {
range,
clone,
remove,
getFirstDefined
getFirstDefined,
sum
}
function remove (a, b) {
@@ -93,3 +94,9 @@ function getFirstDefined (...args) {
}
}
}
function sum (arr) {
return arr.reduce((a, b) => {
return a + b
}, 0)
}
@@ -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 {
@@ -97,12 +96,16 @@ 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'
+85
View File
@@ -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}
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'
// 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}
/>
)
`
}
+107
View File
@@ -0,0 +1,107 @@
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}
pageSize={10}
subComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!. It has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
<ReactTable
data={data}
columns={columns}
pageSize={10}
subComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table! It even has access to the row data: </em>
<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}
pageSize={10}
subComponent={(row) => {
return (
<code><pre>{JSON.stringify(row, null, 2)}</pre></code>
)
}}
/>
)
`
}
+14
View File
@@ -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>
)
+21
View File
@@ -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()
}
})
+138
View File
@@ -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
+2271 -60
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"root": "dist",
"root": "storybook-static",
"routes": [{
"src": "/**",
"dest": "index.html"