mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1e724c483 | ||
|
|
741660c915 | ||
|
|
1f8062501f | ||
|
|
fb51afd0ae | ||
|
|
a64c6a3a76 | ||
|
|
f502ef4e2b | ||
|
|
c58c96c84f | ||
|
|
7202776c86 | ||
|
|
734ba48e9c | ||
|
|
db84ecf789 | ||
|
|
50668fe90f | ||
|
|
52f2c9fdac | ||
|
|
3b39f523be | ||
|
|
9d85981c5b | ||
|
|
b779a98d7a | ||
|
|
1f4c9afd2b | ||
|
|
cef7fbd780 | ||
|
|
e8ebf7c780 | ||
|
|
ac20220d55 | ||
|
|
9acf8f37eb | ||
|
|
64a427d91b | ||
|
|
d21ce226aa | ||
|
|
92c9ae2196 | ||
|
|
23a031b48a | ||
|
|
bd8b273dea | ||
|
|
1a9f0e57b4 | ||
|
|
4c11248c69 | ||
|
|
784311bcd6 | ||
|
|
7b232cd6b4 | ||
|
|
533bea77b6 | ||
|
|
218cf42bb2 | ||
|
|
62287d1641 | ||
|
|
10dc68acc1 | ||
|
|
bd82468852 | ||
|
|
6d28bb2c4d | ||
|
|
9e95b331df | ||
|
|
f296b075fe | ||
|
|
a948a9a41e | ||
|
|
08dbe38ced | ||
|
|
884058b459 | ||
|
|
ee37ad7101 |
@@ -3,3 +3,5 @@ lib/
|
||||
react-table.js
|
||||
react-table.css
|
||||
*.log
|
||||
.idea
|
||||
.DS_Store
|
||||
|
||||
@@ -24,6 +24,8 @@ import FunctionalRendering from '../stories/FunctionalRendering.js'
|
||||
import CustomExpanderPosition from '../stories/CustomExpanderPosition.js'
|
||||
import NoDataText from '../stories/NoDataText.js'
|
||||
import Footers from '../stories/Footers.js'
|
||||
import Filtering from '../stories/Filtering.js'
|
||||
import ControlledTable from '../stories/ControlledTable.js'
|
||||
//
|
||||
configure(() => {
|
||||
storiesOf('1. Docs')
|
||||
@@ -53,4 +55,6 @@ configure(() => {
|
||||
.add('Custom Expander Position', CustomExpanderPosition)
|
||||
.add('Custom "No Data" Text', NoDataText)
|
||||
.add('Footers', Footers)
|
||||
.add('Custom Filtering', Filtering)
|
||||
.add('Controlled Component', ControlledTable)
|
||||
}, module)
|
||||
|
||||
@@ -4,3 +4,15 @@ body {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 15px;
|
||||
line-height: 22px;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
## Problem Description
|
||||
include a detailed explanation of the problem here...
|
||||
|
||||
## Code Snippet(s)
|
||||
|
||||
## Steps to Reproduce
|
||||
1. list the steps
|
||||
2. to reproduce the issue
|
||||
|
||||
## System Information
|
||||
* **Browser & Browser Version:**
|
||||
* **Node Version:**
|
||||
* **OS Version:**
|
||||
* **NPM Version:**
|
||||
* **Yarn Version:**
|
||||
@@ -47,7 +47,7 @@
|
||||
- [Props](#props)
|
||||
- [Columns](#columns)
|
||||
- [Column Header Groups](#column-header-groups)
|
||||
- [Custom Cell and Header Rendering](#custom-cell-and-header-rendering)
|
||||
- [Custom Cell and Header and Footer Rendering](#custom-cell-header-and-footer-rendering)
|
||||
- [Styles](#styles)
|
||||
- [Custom Props](#custom-props)
|
||||
- [Pivoting and Aggregation](#pivoting-and-aggregation)
|
||||
@@ -56,6 +56,7 @@
|
||||
- [Fully Controlled Component](#fully-controlled-component)
|
||||
- [Functional Rendering](#functional-rendering)
|
||||
- [Multi-Sort](#multi-sort)
|
||||
- [Filtering](#filtering)
|
||||
- [Component Overrides](#component-overrides)
|
||||
- [Contributing](#contributing)
|
||||
- [Scripts](#scripts)
|
||||
@@ -89,36 +90,39 @@ import 'react-table/react-table.css'
|
||||
```javascript
|
||||
import ReactTable from 'react-table'
|
||||
|
||||
const data = [{
|
||||
name: 'Tanner Linsley',
|
||||
age: 26,
|
||||
friend: {
|
||||
name: 'Jason Maurer',
|
||||
age: 23,
|
||||
}
|
||||
},{
|
||||
...
|
||||
}]
|
||||
render() {
|
||||
const data = [{
|
||||
name: 'Tanner Linsley',
|
||||
age: 26,
|
||||
friend: {
|
||||
name: 'Jason Maurer',
|
||||
age: 23,
|
||||
}
|
||||
},{
|
||||
...
|
||||
}]
|
||||
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
accessor: 'name' // String-based value accessors!
|
||||
}, {
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
render: props => <span className='number'>{props.value}</span> // Custom cell components!
|
||||
}, {
|
||||
header: 'Friend Name',
|
||||
accessor: d => d.friend.name // Custom value accessors!
|
||||
}, {
|
||||
header: props => <span>Friend Age</span>, // Custom header components!
|
||||
accessor: 'friend.age'
|
||||
}]
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
accessor: 'name' // String-based value accessors!
|
||||
}, {
|
||||
header: 'Age',
|
||||
accessor: 'age',
|
||||
render: props => <span className='number'>{props.value}</span> // Custom cell components!
|
||||
}, {
|
||||
id: 'friendName', // Required because our accessor is not a string
|
||||
header: 'Friend Name',
|
||||
accessor: d => d.friend.name // Custom value accessors!
|
||||
}, {
|
||||
header: props => <span>Friend Age</span>, // Custom header components!
|
||||
accessor: 'friend.age'
|
||||
}]
|
||||
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
/>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
/>
|
||||
}
|
||||
```
|
||||
|
||||
## Data
|
||||
@@ -138,21 +142,32 @@ These are all of the available props (and their default values) for the main `<R
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: false,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
defaultSorting: [],
|
||||
showFilters: false,
|
||||
defaultFiltering: [],
|
||||
defaultFilterMethod: (filter, row, column) => {
|
||||
const id = filter.pivotId || filter.id
|
||||
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
|
||||
},
|
||||
resizable: true,
|
||||
defaultResizing: [],
|
||||
|
||||
// Controlled State Overrides (see Fully Controlled Component section)
|
||||
page: undefined,
|
||||
pageSize: undefined,
|
||||
sorting: undefined
|
||||
sorting: undefined,
|
||||
|
||||
// Controlled State Callbacks
|
||||
onExpandSubComponent: undefined,
|
||||
onPageChange: undefined,
|
||||
onPageSizeChange: undefined,
|
||||
onSortingChange: undefined,
|
||||
onFilteringChange: undefined,
|
||||
onResize: undefined,
|
||||
|
||||
// Pivoting
|
||||
pivotBy: undefined,
|
||||
@@ -183,6 +198,9 @@ These are all of the available props (and their default values) for the main `<R
|
||||
getTheadProps: () => ({}),
|
||||
getTheadTrProps: () => ({}),
|
||||
getTheadThProps: () => ({}),
|
||||
getTheadFilterProps: () => ({}),
|
||||
getTheadFilterTrProps: () => ({}),
|
||||
getTheadFilterThProps: () => ({}),
|
||||
getTbodyProps: () => ({}),
|
||||
getTrGroupProps: () => ({}),
|
||||
getTrProps: () => ({}),
|
||||
@@ -194,6 +212,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
getPaginationProps: () => ({}),
|
||||
getLoadingProps: () => ({}),
|
||||
getNoDataProps: () => ({}),
|
||||
getResizerProps: () => ({}),
|
||||
|
||||
// Global Column Defaults
|
||||
column: {
|
||||
@@ -214,7 +233,18 @@ These are all of the available props (and their default values) for the main `<R
|
||||
footer: undefined,
|
||||
footerClassName: '',
|
||||
footerStyle: {},
|
||||
getFooterProps: () => ({})
|
||||
getFooterProps: () => ({}),
|
||||
filterMethod: undefined,
|
||||
hideFilter: false,
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<input type='text'
|
||||
style={{
|
||||
width: '100%'
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => onFilterChange(event.target.value)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
// Text
|
||||
@@ -256,16 +286,16 @@ Or just define them as props
|
||||
```javascript
|
||||
[{
|
||||
// General
|
||||
accessor: 'propertyName' // or Accessor eg. (row) => row.propertyName (see "Accessors" section for more details)
|
||||
accessor: 'propertyName', // or Accessor eg. (row) => row.propertyName (see "Accessors" section for more details)
|
||||
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,
|
||||
show: true, // can be used to hide a column
|
||||
width: undefined, // A hardcoded width for the column. This overrides both min and max width options
|
||||
minWidth: 100 // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set)
|
||||
maxWidth: undefined // A maximum width for this column.
|
||||
minWidth: 100, // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set)
|
||||
maxWidth: undefined, // A maximum width for this column.
|
||||
|
||||
// Special
|
||||
expander: false // This option will override all data-related options and designates the column to be used
|
||||
expander: false, // This option will override all data-related options and designates the column to be used
|
||||
// for pivoting and sub-component expansion
|
||||
|
||||
// Cell Options
|
||||
@@ -282,17 +312,24 @@ Or just define them as props
|
||||
header: 'Header Name', a function that returns a primitive, or JSX / React Component 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
|
||||
getHeaderProps: (state, rowInfo, column, instance) => ({}) // a function that returns props to decorate the `th` element of the column
|
||||
getHeaderProps: (state, rowInfo, column, instance) => ({}), // a function that returns props to decorate the `th` element of the column
|
||||
|
||||
// Header Groups only
|
||||
columns: [...] // See Header Groups section below
|
||||
columns: [...], // See Header Groups section below
|
||||
|
||||
// Footer
|
||||
footer: 'Header Name' or JSX eg. ({data, column}) => <div>Header Name</div>,
|
||||
footer: 'Footer Name' or JSX eg. ({data, column}) => <div>Footer Name</div>,
|
||||
footerClassName: '', // Set the classname of the `td` element of the column's footer
|
||||
footerStyle: {}, // Set the style of the `td` element of the column's footer
|
||||
getFooterProps: (state, rowInfo, column, instance) => ({}) // a function that returns props to decorate the `td` element of the column's footer
|
||||
getFooterProps: (state, rowInfo, column, instance) => ({}), // A function that returns props to decorate the `td` element of the column's footer
|
||||
|
||||
// Filtering
|
||||
filterMethod: (filter, row, column) => {return true}, // A function returning a boolean that specifies the filtering logic for the column
|
||||
// filter == an object specifying which filter is being applied. Format: {id: [the filter column's id], value: [the value the user typed in the filter field], pivotId: [if filtering on a pivot column, the pivotId will be set to the pivot column's id and the `id` field will be set to the top level pivoting column]}
|
||||
// row == the row of data supplied to the table
|
||||
// column == the column that the filter is on
|
||||
hideFilter: false, // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
|
||||
filterRender: JSX // eg. ({filter, onFilterChange}) => <select onChange={event => onFilterChange(event.target.value)} value={filter ? filter.value : ''}></select> // The value passed to onFilterChange will be the value passed to filter.value of the filterMethod
|
||||
}]
|
||||
```
|
||||
|
||||
@@ -307,6 +344,7 @@ Any values that contain bracket (`[]`) will be split.
|
||||
This array is then used as the path to the value to return.
|
||||
|
||||
("$" is the placeholder value that would be returned by the default accessor)
|
||||
|
||||
| value | path | data |
|
||||
|--------------|-----------------|------------------------|
|
||||
| "a" | ["a"] | {"a": $} |
|
||||
@@ -415,14 +453,16 @@ Every single built-in component's props can be dynamically extended using any on
|
||||
getTdProps={fn}
|
||||
getPaginationProps={fn}
|
||||
getLoadingProps={fn}
|
||||
getNoDataProps: {fn},
|
||||
getResizerProps: {fn}
|
||||
/>
|
||||
```
|
||||
|
||||
These callbacks are executed with each render of the element with three parameters:
|
||||
1. Table State
|
||||
1. RowInfo (undefined if not applicable)
|
||||
1. Column (undefined if not applicable)
|
||||
1. React Table Instance
|
||||
These callbacks are executed with each render of the element with four parameters:
|
||||
1. Table State
|
||||
2. RowInfo (undefined if not applicable)
|
||||
3. Column (undefined if not applicable)
|
||||
4. React Table Instance
|
||||
|
||||
This makes it extremely easy to add, say... a row click callback!
|
||||
```javascript
|
||||
@@ -530,7 +570,7 @@ By adding a `SubComponent` props, you can easily add an expansion level to all r
|
||||
|
||||
|
||||
## Server-side Data
|
||||
If you want to handle pagination, and sorting on the server, `react-table` makes it easy on you.
|
||||
If you want to handle pagination, sorting, and filtering on the server, `react-table` makes it easy on you.
|
||||
|
||||
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
|
||||
@@ -553,7 +593,8 @@ If you want to handle pagination, and sorting on the server, `react-table` makes
|
||||
Axios.post('mysite.com/data', {
|
||||
page: state.page,
|
||||
pageSize: state.pageSize,
|
||||
sorting: state.sorting
|
||||
sorting: state.sorting,
|
||||
filtering: state.filtering
|
||||
})
|
||||
.then((res) => {
|
||||
// Update react-table
|
||||
@@ -599,6 +640,8 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data
|
||||
onSortingChange={(column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held. If the column is a pivoted column, `column` will be an array of columns
|
||||
onExpandRow={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
|
||||
onFilteringChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFilterChange handler by the filterRender option.
|
||||
onResize={(column, event, isTouch) => {...}} // Called when a user clicks on a resizing component (the right edge of a column header)
|
||||
/>
|
||||
```
|
||||
|
||||
@@ -642,6 +685,19 @@ The possibilities are endless!
|
||||
## 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!
|
||||
|
||||
## Filtering
|
||||
Filtering can be enabled by setting the `showFilters` option on the table.
|
||||
|
||||
If you don't want particular column to be filtered you can set the `hideFilter` option on the column.
|
||||
|
||||
By default the table tries to filter by checking if the row's value starts with the filter text. The default method for filtering the table can be set with the table's `defaultFilterMethod` option.
|
||||
|
||||
If you want to override a particular column's filtering method, you can set the `filterMethod` option on a column.
|
||||
|
||||
To completely override the filter that is shown, you can set the `filterRender` column option. Using this option you can specify the JSX that is shown. The option is passed an `onFilterChange` method which must be called with the the value that you wan't to pass to the `filterMethod` option whenever the filter has changed.
|
||||
|
||||
See <a href="http://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Custom%20Filtering&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel" target="\_parent">Custom Filtering</a> demo for examples.
|
||||
|
||||
## Component Overrides
|
||||
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
|
||||
@@ -662,6 +718,7 @@ Object.assign(ReactTableDefaults, {
|
||||
NextComponent: undefined,
|
||||
LoadingComponent: component,
|
||||
NoDataComponent: component,
|
||||
ResizerComponent: component
|
||||
})
|
||||
|
||||
// Or change per instance
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="error-display"></div>
|
||||
<script src="static/preview.437e4f72f80621de5f68.bundle.js"></script>
|
||||
<script src="static/preview.0cd0bb2bf09f3220bea7.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@
|
||||
</head>
|
||||
<body style="margin: 0;">
|
||||
<div id="root"></div>
|
||||
<script src="static/manager.3f690da6fe3fd9729ee0.bundle.js"></script>
|
||||
<script src="static/manager.064c8fe6b78907f0a142.bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+26
-26
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/manager.064c8fe6b78907f0a142.bundle.js","sources":["webpack:///static/manager.064c8fe6b78907f0a142.bundle.js"],"mappings":"AAAA;AAkuDA;AA84DA;AAy8DA;AA00DA;AAsyEA;AA89CA;AA+rDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAqxDA;AAsrDA;AA4yDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/manager.3f690da6fe3fd9729ee0.bundle.js","sources":["webpack:///static/manager.3f690da6fe3fd9729ee0.bundle.js"],"mappings":"AAAA;AAkuDA;AA84DA;AA28DA;AA00DA;AAsyEA;AA89CA;AA+rDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAoxDA;AAsrDA;AA4yDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"static/preview.0cd0bb2bf09f3220bea7.bundle.js","sources":["webpack:///static/preview.0cd0bb2bf09f3220bea7.bundle.js"],"mappings":"AAAA;AAkuDA;AA62DA;AAwtFA;AAsiFA;AA0uOA;AAgmGA;AA6rDA;AA0iEA;AA0xDA;AA25DA;AAmqDA;AA0vDA;AA+9CA;AAg5DA;AAwoDA;AAk7CA;AA2pDA;AAmjEA;AA27DA;AAghCA;AA4vDA;AA8kDA;AAwpEA;AAk3DA;AAy0DA;AA8xCA;AAu3EA;AAi4GA;AAwoDA;AAk+CA;AA+oCA;AAutCA;AA4jDA;AAwcA;AA+jFA","sourceRoot":""}
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/preview.437e4f72f80621de5f68.bundle.js","sources":["webpack:///static/preview.437e4f72f80621de5f68.bundle.js"],"mappings":"AAAA;AAkuDA;AAq5DA;AA8xFA;AA2+EA;AA++NA;AA06GA;AAgsDA;AA8/DA;AA4xDA;AAigEA;AAmjDA;AA4sDA;AAk8CA;AAu/DA;AA8lDA;AA09CA;AAqoDA;AAywEA;AAokDA;AAsvCA;AA2mDA;AA4tDA;AAqjEA;AAs2DA;AAmyDA;AAsnDA;AAszFA;AA65FA;AA4/CA;AAwzCA;AAmlCA;AAotDA;AAyrBA;AAkPA;AA84EA","sourceRoot":""}
|
||||
+8
-10
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "5.3.2",
|
||||
"version": "5.5.3",
|
||||
"description": "A fast, lightweight, opinionated table and datagrid built on React",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/tannerlinsley/react-table#readme",
|
||||
@@ -24,14 +24,16 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build:node": "babel src --out-dir lib --source-maps inline",
|
||||
"build:css": "rm -rf react-table.css && stylus src/index.styl --compress -o react-table.css && yarn run css:autoprefix",
|
||||
"build:css": "rimraf react-table.css && stylus src/index.styl --compress -o react-table.css && yarn run css:autoprefix",
|
||||
"css:autoprefix": "postcss --use autoprefixer react-table.css -r",
|
||||
"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",
|
||||
"umd": "rimraf react-table.js && webpack --config umd.webpack.js",
|
||||
"build": "npm-run-all build:*",
|
||||
"prepublish": "npm run build && npm run umd",
|
||||
"postpublish": "git push --tags",
|
||||
"storybook": "start-storybook -p 8000 -c .storybook",
|
||||
"docs": "build-storybook -o docs && cp .storybook/CNAME docs/CNAME"
|
||||
},
|
||||
@@ -49,8 +51,6 @@
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
"babel-preset-react": "6.11.1",
|
||||
"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",
|
||||
@@ -61,13 +61,11 @@
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"react-json-tree": "^0.10.1",
|
||||
"rimraf": "^2.6.1",
|
||||
"standard": "^8.0.0",
|
||||
"storybook": "^0.0.0",
|
||||
"stylus": "^0.54.5",
|
||||
"uglifyify": "3.0.3"
|
||||
},
|
||||
"browserify-shim": {
|
||||
"react": "global:React"
|
||||
"webpack": "^2.4.1"
|
||||
},
|
||||
"standard": {
|
||||
"parser": "babel-eslint",
|
||||
|
||||
+30
-3
@@ -16,10 +16,19 @@ export default {
|
||||
defaultPageSize: 20,
|
||||
showPageJump: true,
|
||||
expanderColumnWidth: 35,
|
||||
collapseOnSortingChange: false,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
defaultSorting: [],
|
||||
showFilters: false,
|
||||
defaultFiltering: [],
|
||||
defaultFilterMethod: (filter, row, column) => {
|
||||
const id = filter.pivotId || filter.id
|
||||
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
|
||||
},
|
||||
resizable: true,
|
||||
defaultResizing: [],
|
||||
|
||||
// Controlled State Overrides
|
||||
// page: undefined,
|
||||
@@ -31,6 +40,8 @@ export default {
|
||||
onPageChange: undefined,
|
||||
onPageSizeChange: undefined,
|
||||
onSortingChange: undefined,
|
||||
onFilteringChange: undefined,
|
||||
onResize: undefined,
|
||||
|
||||
// Pivoting
|
||||
pivotBy: undefined,
|
||||
@@ -61,6 +72,9 @@ export default {
|
||||
getTheadProps: emptyObj,
|
||||
getTheadTrProps: emptyObj,
|
||||
getTheadThProps: emptyObj,
|
||||
getTheadFilterProps: emptyObj,
|
||||
getTheadFilterTrProps: emptyObj,
|
||||
getTheadFilterThProps: emptyObj,
|
||||
getTbodyProps: emptyObj,
|
||||
getTrGroupProps: emptyObj,
|
||||
getTrProps: emptyObj,
|
||||
@@ -71,6 +85,7 @@ export default {
|
||||
getPaginationProps: emptyObj,
|
||||
getLoadingProps: emptyObj,
|
||||
getNoDataProps: emptyObj,
|
||||
getResizerProps: emptyObj,
|
||||
|
||||
// Global Column Defaults
|
||||
column: {
|
||||
@@ -91,7 +106,18 @@ export default {
|
||||
footer: undefined,
|
||||
footerClassName: '',
|
||||
footerStyle: {},
|
||||
getFooterProps: emptyObj
|
||||
getFooterProps: emptyObj,
|
||||
filterMethod: undefined,
|
||||
hideFilter: false,
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<input type='text'
|
||||
style={{
|
||||
width: '100%'
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={(event) => onFilterChange(event.target.value)}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
// Text
|
||||
@@ -148,5 +174,6 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
NoDataComponent: _.makeTemplateComponent('rt-noData')
|
||||
NoDataComponent: _.makeTemplateComponent('rt-noData'),
|
||||
ResizerComponent: _.makeTemplateComponent('rt-resizer')
|
||||
}
|
||||
|
||||
+239
-61
@@ -4,6 +4,9 @@ import classnames from 'classnames'
|
||||
import _ from './utils'
|
||||
import lifecycle from './lifecycle'
|
||||
import methods from './methods'
|
||||
import defaults from './defaultProps'
|
||||
|
||||
export const ReactTableDefaults = defaults
|
||||
|
||||
export default React.createClass({
|
||||
...lifecycle,
|
||||
@@ -23,6 +26,9 @@ export default React.createClass({
|
||||
getTheadProps,
|
||||
getTheadTrProps,
|
||||
getTheadThProps,
|
||||
getTheadFilterProps,
|
||||
getTheadFilterTrProps,
|
||||
getTheadFilterThProps,
|
||||
getTbodyProps,
|
||||
getTrGroupProps,
|
||||
getTrProps,
|
||||
@@ -33,16 +39,21 @@ export default React.createClass({
|
||||
getPaginationProps,
|
||||
getLoadingProps,
|
||||
getNoDataProps,
|
||||
getResizerProps,
|
||||
showPagination,
|
||||
expanderColumnWidth,
|
||||
manual,
|
||||
loadingText,
|
||||
noDataText,
|
||||
showFilters,
|
||||
resizable,
|
||||
// State
|
||||
loading,
|
||||
pageSize,
|
||||
page,
|
||||
sorting,
|
||||
filtering,
|
||||
resizing,
|
||||
pages,
|
||||
// Pivoting State
|
||||
pivotValKey,
|
||||
@@ -63,6 +74,7 @@ export default React.createClass({
|
||||
LoadingComponent,
|
||||
SubComponent,
|
||||
NoDataComponent,
|
||||
ResizerComponent,
|
||||
// Data model
|
||||
resolvedData,
|
||||
allVisibleColumns,
|
||||
@@ -75,32 +87,39 @@ export default React.createClass({
|
||||
// Pagination
|
||||
const startRow = pageSize * page
|
||||
const endRow = startRow + pageSize
|
||||
const pageRows = manual ? resolvedData : sortedData.slice(startRow, endRow)
|
||||
let pageRows = manual ? resolvedData : sortedData.slice(startRow, endRow)
|
||||
const minRows = this.getMinRows()
|
||||
const padRows = pages > 1 ? _.range(pageSize - pageRows.length)
|
||||
: minRows ? _.range(Math.max(minRows - pageRows.length, 0))
|
||||
: []
|
||||
const padRows = _.range(Math.max(minRows - pageRows.length, 0))
|
||||
|
||||
const hasColumnFooter = allVisibleColumns.some(d => d.footer)
|
||||
|
||||
const recurseRowsViewIndex = (rows, path = [], index = -1) => {
|
||||
rows.forEach((row, i) => {
|
||||
index++
|
||||
row._viewIndex = index
|
||||
const newPath = path.concat([i])
|
||||
if (row[subRowsKey] && _.get(expandedRows, newPath)) {
|
||||
index = recurseRowsViewIndex(row[subRowsKey], newPath, index)
|
||||
}
|
||||
})
|
||||
return index
|
||||
return [
|
||||
rows.map((row, i) => {
|
||||
index++
|
||||
const rowWithViewIndex = {
|
||||
...row,
|
||||
_viewIndex: index
|
||||
}
|
||||
const newPath = path.concat([i])
|
||||
if (rowWithViewIndex[subRowsKey] && _.get(expandedRows, newPath)) {
|
||||
[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index)
|
||||
}
|
||||
return rowWithViewIndex
|
||||
}),
|
||||
index
|
||||
]
|
||||
}
|
||||
|
||||
recurseRowsViewIndex(pageRows)
|
||||
[pageRows] = recurseRowsViewIndex(pageRows)
|
||||
|
||||
const canPrevious = page > 0
|
||||
const canNext = page + 1 < pages
|
||||
|
||||
const rowMinWidth = _.sum(allVisibleColumns.map(d => _.getFirstDefined(d.width, d.minWidth)))
|
||||
const rowMinWidth = _.sum(allVisibleColumns.map(d => {
|
||||
const resized = resizing.find(x => x.id === d.id) || {}
|
||||
return _.getFirstDefined(resized.value, d.width, d.minWidth)
|
||||
}))
|
||||
|
||||
let rowIndex = -1
|
||||
|
||||
@@ -143,9 +162,18 @@ export default React.createClass({
|
||||
}
|
||||
|
||||
const makeHeaderGroup = (column, i) => {
|
||||
const flex = _.sum(column.columns.map(d => d.width ? 0 : d.minWidth))
|
||||
const width = _.sum(column.columns.map(d => _.getFirstDefined(d.width, d.minWidth)))
|
||||
const maxWidth = _.sum(column.columns.map(d => _.getFirstDefined(d.width, d.maxWidth)))
|
||||
const flex = _.sum(column.columns.map(d => {
|
||||
const resized = resizing.find(x => x.id === d.id) || {}
|
||||
return d.width || resized.value ? 0 : d.minWidth
|
||||
}))
|
||||
const width = _.sum(column.columns.map(d => {
|
||||
const resized = resizing.find(x => x.id === d.id) || {}
|
||||
return _.getFirstDefined(resized.value, d.width, d.minWidth)
|
||||
}))
|
||||
const maxWidth = _.sum(column.columns.map(d => {
|
||||
const resized = resizing.find(x => x.id === d.id) || {}
|
||||
return _.getFirstDefined(resized.value, d.width, d.maxWidth)
|
||||
}))
|
||||
const theadGroupThProps = _.splitProps(getTheadGroupThProps(finalState, undefined, column, this))
|
||||
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
|
||||
|
||||
@@ -249,10 +277,11 @@ export default React.createClass({
|
||||
}
|
||||
|
||||
const makeHeader = (column, i) => {
|
||||
const resized = resizing.find(x => x.id === column.id) || {}
|
||||
const sort = sorting.find(d => d.id === column.id)
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
|
||||
const theadThProps = _.splitProps(getTheadThProps(finalState, undefined, column, this))
|
||||
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
|
||||
|
||||
@@ -273,6 +302,14 @@ export default React.createClass({
|
||||
...columnHeaderProps.rest
|
||||
}
|
||||
|
||||
const resizer = resizable ? (
|
||||
<ResizerComponent
|
||||
onMouseDown={e => this.resizeColumnStart(column, e, false)}
|
||||
onTouchStart={e => this.resizeColumnStart(column, e, true)}
|
||||
{...resizerProps}
|
||||
/>
|
||||
) : null
|
||||
|
||||
if (column.expander) {
|
||||
if (column.pivotColumns) {
|
||||
const pivotSort = sorting.find(d => d.id === column.id)
|
||||
@@ -281,9 +318,10 @@ export default React.createClass({
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-pivot-header',
|
||||
'rt-resizable-header',
|
||||
column.sortable && '-cursor-pointer',
|
||||
classes,
|
||||
pivotSort ? (pivotSort.desc ? '-sort-asc' : '-sort-desc') : ''
|
||||
pivotSort ? (pivotSort.desc ? '-sort-desc' : '-sort-asc') : ''
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
@@ -296,19 +334,22 @@ export default React.createClass({
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{column.pivotColumns.map((pivotColumn, i) => {
|
||||
return (
|
||||
<span key={pivotColumn.id}>
|
||||
{_.normalizeComponent(pivotColumn.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
{i < column.pivotColumns.length - 1 && (
|
||||
<ExpanderComponent />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
<div className='rt-resizable-header-content'>
|
||||
{column.pivotColumns.map((pivotColumn, i) => {
|
||||
return (
|
||||
<span key={pivotColumn.id}>
|
||||
{_.normalizeComponent(pivotColumn.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
{i < column.pivotColumns.length - 1 && (
|
||||
<ExpanderComponent />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{resizer}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
@@ -334,7 +375,8 @@ export default React.createClass({
|
||||
key={i}
|
||||
className={classnames(
|
||||
classes,
|
||||
sort ? (sort.desc ? '-sort-asc' : '-sort-desc') : '',
|
||||
'rt-resizable-header',
|
||||
sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '',
|
||||
column.sortable && '-cursor-pointer',
|
||||
!show && '-hidden',
|
||||
)}
|
||||
@@ -349,10 +391,153 @@ export default React.createClass({
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{_.normalizeComponent(column.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
<div className='rt-resizable-header-content'>
|
||||
{_.normalizeComponent(column.header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
</div>
|
||||
{resizer}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
|
||||
const makeFilters = () => {
|
||||
const theadFilterProps = _.splitProps(getTheadFilterProps(finalState, undefined, undefined, this))
|
||||
const theadFilterTrProps = _.splitProps(getTheadFilterTrProps(finalState, undefined, undefined, this))
|
||||
return (
|
||||
<TheadComponent
|
||||
className={classnames('-filters', theadFilterProps.className)}
|
||||
style={{
|
||||
...theadFilterProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
}}
|
||||
{...theadFilterProps.rest}
|
||||
>
|
||||
<TrComponent
|
||||
className={theadFilterTrProps.className}
|
||||
style={theadFilterTrProps.style}
|
||||
{...theadFilterTrProps.rest}
|
||||
>
|
||||
{allVisibleColumns.map(makeFilter)}
|
||||
</TrComponent>
|
||||
</TheadComponent>
|
||||
)
|
||||
}
|
||||
|
||||
const makeFilter = (column, i) => {
|
||||
const resized = resizing.find(x => x.id === column.id) || {}
|
||||
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
|
||||
const theadFilterThProps = _.splitProps(getTheadFilterThProps(finalState, undefined, column, this))
|
||||
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
|
||||
|
||||
const classes = [
|
||||
column.headerClassName,
|
||||
theadFilterThProps.className,
|
||||
columnHeaderProps.className
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...column.headerStyle,
|
||||
...theadFilterThProps.style,
|
||||
...columnHeaderProps.style
|
||||
}
|
||||
|
||||
const rest = {
|
||||
...theadFilterThProps.rest,
|
||||
...columnHeaderProps.rest
|
||||
}
|
||||
|
||||
if (column.expander) {
|
||||
if (column.pivotColumns) {
|
||||
const pivotCols = []
|
||||
for (let i = 0; i < column.pivotColumns.length; i++) {
|
||||
const col = column.pivotColumns[i]
|
||||
const filter = filtering.find(filter => filter.id === column.id && filter.pivotId === col.id)
|
||||
pivotCols.push(
|
||||
<span key={col.id}
|
||||
style={{flex: 1}}>
|
||||
{!col.hideFilter ? (
|
||||
_.normalizeComponent(col.filterRender,
|
||||
{
|
||||
col,
|
||||
filter,
|
||||
onFilterChange: (value) => (this.filterColumn(column, value, col))
|
||||
},
|
||||
defaults.column.filterRender
|
||||
)
|
||||
) : null}
|
||||
</span>
|
||||
)
|
||||
if (i < column.pivotColumns.length - 1) {
|
||||
pivotCols.push(<ExpanderComponent key={col.id + '-' + i} />)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-pivot-header',
|
||||
column.sortable && '-cursor-pointer',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`,
|
||||
display: 'flex'
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{pivotCols}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const filter = filtering.find(filter => filter.id === column.id)
|
||||
|
||||
return (
|
||||
<ThComponent
|
||||
key={i}
|
||||
className={classnames(
|
||||
classes
|
||||
)}
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{!column.hideFilter ? (
|
||||
_.normalizeComponent(column.filterRender,
|
||||
{
|
||||
column,
|
||||
filter,
|
||||
onFilterChange: (value) => (this.filterColumn(column, value))
|
||||
},
|
||||
defaults.column.filterRender
|
||||
)
|
||||
) : null}
|
||||
</ThComponent>
|
||||
)
|
||||
}
|
||||
@@ -385,9 +570,10 @@ export default React.createClass({
|
||||
{...trProps.rest}
|
||||
>
|
||||
{allVisibleColumns.map((column, i2) => {
|
||||
const resized = resizing.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
|
||||
const tdProps = _.splitProps(getTdProps(finalState, rowInfo, column, this))
|
||||
const columnProps = _.splitProps(column.getProps(finalState, rowInfo, column, this))
|
||||
|
||||
@@ -523,7 +709,6 @@ export default React.createClass({
|
||||
const makePadRow = (row, i) => {
|
||||
const trGroupProps = getTrGroupProps(finalState, undefined, undefined, this)
|
||||
const trProps = _.splitProps(getTrProps(finalState, undefined, undefined, this))
|
||||
const tdProps = _.splitProps(getTdProps(finalState, undefined, undefined, this))
|
||||
return (
|
||||
<TrGroupComponent
|
||||
key={i}
|
||||
@@ -536,24 +721,11 @@ export default React.createClass({
|
||||
)}
|
||||
style={trProps.style || {}}
|
||||
>
|
||||
{SubComponent && (
|
||||
<ThComponent
|
||||
className={classnames(
|
||||
'rt-expander-header',
|
||||
tdProps.className
|
||||
)}
|
||||
style={{
|
||||
...tdProps.style,
|
||||
flex: `0 0 auto`,
|
||||
width: `${expanderColumnWidth}px`
|
||||
}}
|
||||
{...tdProps.rest}
|
||||
/>
|
||||
)}
|
||||
{allVisibleColumns.map((column, i2) => {
|
||||
const resized = resizing.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
|
||||
const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this))
|
||||
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
|
||||
|
||||
@@ -613,9 +785,10 @@ export default React.createClass({
|
||||
{...tFootTrProps.rest}
|
||||
>
|
||||
{allVisibleColumns.map((column, i2) => {
|
||||
const resized = resizing.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
|
||||
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
|
||||
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
|
||||
const tFootTdProps = _.splitProps(getTfootTdProps(finalState, undefined, undefined, this))
|
||||
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
|
||||
const columnFooterProps = _.splitProps(column.getFooterProps(finalState, undefined, column, this))
|
||||
@@ -693,7 +866,10 @@ export default React.createClass({
|
||||
{...tFootTdProps.rest}
|
||||
{...columnFooterProps.rest}
|
||||
>
|
||||
{_.normalizeComponent(column.footer)}
|
||||
{_.normalizeComponent(column.footer, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
})}
|
||||
</TdComponent>
|
||||
)
|
||||
})}
|
||||
@@ -708,6 +884,7 @@ export default React.createClass({
|
||||
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
|
||||
const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
|
||||
const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
|
||||
const resizerProps = getResizerProps(finalState, undefined, undefined, this)
|
||||
|
||||
const makeTable = () => (
|
||||
<div
|
||||
@@ -729,6 +906,7 @@ export default React.createClass({
|
||||
>
|
||||
{hasHeaderGroups ? makeHeaderGroups() : null}
|
||||
{makeHeaders()}
|
||||
{showFilters ? makeFilters() : null}
|
||||
<TbodyComponent
|
||||
className={classnames(tBodyProps.className)}
|
||||
style={{
|
||||
|
||||
+39
-1
@@ -18,10 +18,21 @@ $expandSize = 7px
|
||||
.rt-thead
|
||||
display: flex
|
||||
flex-direction: column
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&.-headerGroups
|
||||
background: alpha(black, .03)
|
||||
border-bottom: 1px solid alpha(black, .05)
|
||||
|
||||
&.-filters
|
||||
border-bottom: 1px solid alpha(black, 0.05)
|
||||
|
||||
.rt-th
|
||||
border-right: 1px solid alpha(black, 0.02)
|
||||
|
||||
&.-header
|
||||
box-shadow: 0 2px 15px 0px alpha(black, .15)
|
||||
|
||||
@@ -30,6 +41,9 @@ $expandSize = 7px
|
||||
|
||||
.rt-th
|
||||
.rt-td
|
||||
padding: 5px 5px
|
||||
line-height: normal
|
||||
position: relative
|
||||
border-right: 1px solid alpha(black, .05)
|
||||
transition box-shadow .3s $easeOutBack
|
||||
box-shadow:inset 0 0 0 0 transparent
|
||||
@@ -41,6 +55,16 @@ $expandSize = 7px
|
||||
cursor: pointer
|
||||
&:last-child
|
||||
border-right: 0
|
||||
|
||||
.rt-resizable-header
|
||||
overflow: visible
|
||||
&:last-child
|
||||
overflow: hidden
|
||||
|
||||
.rt-resizable-header-content
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
||||
.rt-tbody
|
||||
display: flex
|
||||
flex-direction: column
|
||||
@@ -99,6 +123,17 @@ $expandSize = 7px
|
||||
cursor: pointer
|
||||
&.-open:after
|
||||
transform: translate(-50%, -50%) rotate(0deg)
|
||||
|
||||
.rt-resizer
|
||||
display: inline-block
|
||||
position: absolute
|
||||
width: 36px
|
||||
top: 0
|
||||
bottom: 0
|
||||
right: -18px
|
||||
cursor: col-resize
|
||||
z-index: 10
|
||||
|
||||
.rt-tfoot
|
||||
display: flex
|
||||
flex-direction: column
|
||||
@@ -225,7 +260,6 @@ $expandSize = 7px
|
||||
|
||||
input
|
||||
select
|
||||
appearance: none
|
||||
border: 1px solid rgba(0,0,0,0.1)
|
||||
background: white
|
||||
padding: 5px 7px
|
||||
@@ -234,6 +268,10 @@ $expandSize = 7px
|
||||
font-weight: normal
|
||||
outline:none
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"])
|
||||
select
|
||||
appearance: none
|
||||
|
||||
.select-wrap
|
||||
position:relative
|
||||
display:inline-block
|
||||
|
||||
+30
-10
@@ -11,22 +11,26 @@ export default {
|
||||
page: 0,
|
||||
pageSize: this.props.defaultPageSize || 10,
|
||||
sorting: this.props.defaultSorting,
|
||||
expandedRows: {}
|
||||
expandedRows: {},
|
||||
filtering: this.props.defaultFiltering,
|
||||
resizing: this.props.defaultResizing,
|
||||
currentlyResizing: undefined,
|
||||
skipNextSort: false
|
||||
}
|
||||
},
|
||||
|
||||
getResolvedState (props, state) {
|
||||
const resolvedState = {
|
||||
..._.compactObject(this.state),
|
||||
..._.compactObject(state),
|
||||
..._.compactObject(this.props),
|
||||
..._.compactObject(state),
|
||||
..._.compactObject(props)
|
||||
}
|
||||
return resolvedState
|
||||
},
|
||||
|
||||
componentWillMount () {
|
||||
this.setStateWithData(this.getDataModel())
|
||||
this.setStateWithData(this.getDataModel(this.getResolvedState()))
|
||||
},
|
||||
|
||||
componentDidMount () {
|
||||
@@ -37,21 +41,32 @@ export default {
|
||||
const oldState = this.getResolvedState()
|
||||
const newState = this.getResolvedState(nextProps, nextState)
|
||||
|
||||
if (oldState.defaultSorting !== newState.defaultSorting) {
|
||||
newState.sorting = newState.defaultSorting
|
||||
}
|
||||
|
||||
if ((oldState.showFilters !== newState.showFilters) ||
|
||||
(oldState.showFilters !== newState.showFilters)) {
|
||||
newState.filtering = newState.defaultFiltering
|
||||
}
|
||||
|
||||
// Props that trigger a data update
|
||||
if (
|
||||
oldState.data !== newState.data ||
|
||||
oldState.columns !== newState.columns ||
|
||||
oldState.pivotBy !== newState.pivotBy ||
|
||||
oldState.sorting !== newState.sorting
|
||||
oldState.sorting !== newState.sorting ||
|
||||
oldState.showFilters !== newState.showFilters ||
|
||||
oldState.filtering !== newState.filtering
|
||||
) {
|
||||
this.setStateWithData(this.getDataModel(nextProps, nextState))
|
||||
this.setStateWithData(this.getDataModel(newState))
|
||||
}
|
||||
},
|
||||
|
||||
setStateWithData (newState, cb) {
|
||||
const oldState = this.getResolvedState()
|
||||
const newResolvedState = this.getResolvedState({}, newState)
|
||||
const { freezeWhenExpanded } = newResolvedState
|
||||
const {freezeWhenExpanded} = newResolvedState
|
||||
|
||||
// Default to unfrozen state
|
||||
newResolvedState.frozen = false
|
||||
@@ -73,12 +88,16 @@ export default {
|
||||
if (
|
||||
(oldState.frozen && !newResolvedState.frozen) ||
|
||||
oldState.sorting !== newResolvedState.sorting ||
|
||||
oldState.filtering !== newResolvedState.filtering ||
|
||||
oldState.showFilters !== newResolvedState.showFilters ||
|
||||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData)
|
||||
) {
|
||||
// Handle collapseOnSortingChange & collapseOnPageChange
|
||||
// Handle collapseOnSortingChange & collapseOnDataChange
|
||||
if (
|
||||
(oldState.sorting !== newResolvedState.sorting && this.props.collapseOnSortingChange) ||
|
||||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnPageChange)
|
||||
(oldState.filtering !== newResolvedState.filtering) ||
|
||||
(oldState.showFilters !== newResolvedState.showFilters) ||
|
||||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnDataChange)
|
||||
) {
|
||||
newResolvedState.expandedRows = {}
|
||||
}
|
||||
@@ -87,8 +106,9 @@ export default {
|
||||
}
|
||||
|
||||
// Calculate pageSize all the time
|
||||
if (newResolvedState.resolvedData) {
|
||||
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.resolvedData.length / newResolvedState.pageSize)
|
||||
if (newResolvedState.sortedData) {
|
||||
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.sortedData.length / newResolvedState.pageSize)
|
||||
newResolvedState.page = Math.max(newResolvedState.page >= newResolvedState.pages ? newResolvedState.pages - 1 : newResolvedState.page, 0)
|
||||
}
|
||||
|
||||
return this.setState(newResolvedState, cb)
|
||||
|
||||
+210
-34
@@ -1,7 +1,7 @@
|
||||
import _ from './utils'
|
||||
|
||||
export default {
|
||||
getDataModel (nextProps, nextState) {
|
||||
getDataModel (newState) {
|
||||
const {
|
||||
columns,
|
||||
pivotBy = [],
|
||||
@@ -10,11 +10,8 @@ export default {
|
||||
pivotValKey,
|
||||
subRowsKey,
|
||||
expanderColumnWidth,
|
||||
SubComponent,
|
||||
page,
|
||||
pages,
|
||||
pageSize
|
||||
} = this.getResolvedState(nextProps, nextState)
|
||||
SubComponent
|
||||
} = newState
|
||||
|
||||
// Determine Header Groups
|
||||
let hasHeaderGroups = false
|
||||
@@ -192,15 +189,14 @@ export default {
|
||||
// Group the rows together for this level
|
||||
let groupedRows = Object.entries(
|
||||
_.groupBy(rows, keys[i]))
|
||||
.map(([key, value]) => {
|
||||
return {
|
||||
[pivotIDKey]: keys[i],
|
||||
[pivotValKey]: key,
|
||||
[keys[i]]: key,
|
||||
[subRowsKey]: value
|
||||
}
|
||||
}
|
||||
)
|
||||
.map(([key, value]) => {
|
||||
return {
|
||||
[pivotIDKey]: keys[i],
|
||||
[pivotValKey]: key,
|
||||
[keys[i]]: key,
|
||||
[subRowsKey]: value
|
||||
}
|
||||
})
|
||||
// Recurse into the subRows
|
||||
groupedRows = groupedRows.map(rowGroup => {
|
||||
let subRows = groupRecursively(rowGroup[subRowsKey], keys, i + 1)
|
||||
@@ -215,32 +211,32 @@ export default {
|
||||
resolvedData = groupRecursively(resolvedData, pivotBy)
|
||||
}
|
||||
|
||||
const newPages = _.getFirstDefined(pages, Math.ceil(resolvedData.length / pageSize))
|
||||
const newPage = page > newPages ? newPage - 1 : page
|
||||
|
||||
return {
|
||||
...newState,
|
||||
resolvedData,
|
||||
pivotColumn,
|
||||
allVisibleColumns,
|
||||
headerGroups,
|
||||
allDecoratedColumns,
|
||||
hasHeaderGroups,
|
||||
page: Math.max(newPage, 0)
|
||||
hasHeaderGroups
|
||||
}
|
||||
},
|
||||
getSortedData (resolvedState) {
|
||||
const {
|
||||
manual,
|
||||
sorting,
|
||||
resolvedData
|
||||
filtering,
|
||||
showFilters,
|
||||
defaultFilterMethod,
|
||||
resolvedData,
|
||||
allVisibleColumns
|
||||
} = resolvedState
|
||||
|
||||
// Resolve the data from either manual data or sorted data
|
||||
return {
|
||||
sortedData: manual ? resolvedData : this.sortData(resolvedData, sorting)
|
||||
sortedData: manual ? resolvedData : this.sortData(this.filterData(resolvedData, showFilters, filtering, defaultFilterMethod, allVisibleColumns), sorting)
|
||||
}
|
||||
},
|
||||
|
||||
fireOnChange () {
|
||||
this.props.onChange(this.getResolvedState(), this)
|
||||
},
|
||||
@@ -250,10 +246,56 @@ export default {
|
||||
getStateOrProp (key) {
|
||||
return _.getFirstDefined(this.state[key], this.props[key])
|
||||
},
|
||||
filterData (data, showFilters, filtering, defaultFilterMethod, allVisibleColumns) {
|
||||
let filteredData = data
|
||||
|
||||
if (showFilters && filtering.length) {
|
||||
filteredData = filtering.reduce(
|
||||
(filteredSoFar, nextFilter) => {
|
||||
return filteredSoFar.filter(
|
||||
(row) => {
|
||||
let column
|
||||
|
||||
if (nextFilter.pivotId) {
|
||||
const parentColumn = allVisibleColumns.find(x => x.id === nextFilter.id)
|
||||
column = parentColumn.pivotColumns.find(x => x.id === nextFilter.pivotId)
|
||||
} else {
|
||||
column = allVisibleColumns.find(x => x.id === nextFilter.id)
|
||||
}
|
||||
|
||||
const filterMethod = column.filterMethod || defaultFilterMethod
|
||||
|
||||
return filterMethod(nextFilter, row, column)
|
||||
})
|
||||
}
|
||||
, filteredData
|
||||
)
|
||||
|
||||
// Apply the filter to the subrows if we are pivoting, and then
|
||||
// filter any rows without subcolumns because it would be strange to show
|
||||
filteredData = filteredData.map(row => {
|
||||
if (!row[this.props.subRowsKey]) {
|
||||
return row
|
||||
}
|
||||
return {
|
||||
...row,
|
||||
[this.props.subRowsKey]: this.filterData(row[this.props.subRowsKey], showFilters, filtering, defaultFilterMethod, allVisibleColumns)
|
||||
}
|
||||
}).filter(row => {
|
||||
if (!row[this.props.subRowsKey]) {
|
||||
return true
|
||||
}
|
||||
return row[this.props.subRowsKey].length > 0
|
||||
})
|
||||
}
|
||||
|
||||
return filteredData
|
||||
},
|
||||
sortData (data, sorting) {
|
||||
if (!sorting.length) {
|
||||
return data
|
||||
}
|
||||
|
||||
const sorted = _.orderBy(data, sorting.map(sort => {
|
||||
return row => {
|
||||
if (row[sort.id] === null || row[sort.id] === undefined) {
|
||||
@@ -280,20 +322,23 @@ export default {
|
||||
|
||||
// User actions
|
||||
onPageChange (page) {
|
||||
const { onPageChange } = this.props
|
||||
const {onPageChange, collapseOnPageChange} = this.props
|
||||
if (onPageChange) {
|
||||
return onPageChange(page)
|
||||
}
|
||||
this.setStateWithData({
|
||||
expandedRows: {},
|
||||
page
|
||||
}, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
const newState = {page}
|
||||
if (collapseOnPageChange) {
|
||||
newState.expandedRows = {}
|
||||
}
|
||||
this.setStateWithData(
|
||||
newState
|
||||
, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
},
|
||||
onPageSizeChange (newPageSize) {
|
||||
const { onPageSizeChange } = this.props
|
||||
const { pageSize, page } = this.getResolvedState()
|
||||
const {onPageSizeChange} = this.props
|
||||
const {pageSize, page} = this.getResolvedState()
|
||||
|
||||
// Normalize the page to display
|
||||
const currentRow = pageSize * page
|
||||
@@ -311,8 +356,20 @@ export default {
|
||||
})
|
||||
},
|
||||
sortColumn (column, additive) {
|
||||
const { sorting } = this.getResolvedState()
|
||||
const { onSortingChange } = this.props
|
||||
const {sorting, skipNextSort} = this.getResolvedState()
|
||||
|
||||
// we can't stop event propagation from the column resize move handlers
|
||||
// attached to the document because of react's synthetic events
|
||||
// so we have to prevent the sort function from actually sorting
|
||||
// if we click on the column resize element within a header.
|
||||
if (skipNextSort) {
|
||||
this.setStateWithData({
|
||||
skipNextSort: false
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const {onSortingChange} = this.props
|
||||
if (onSortingChange) {
|
||||
return onSortingChange(column, additive)
|
||||
}
|
||||
@@ -394,5 +451,124 @@ export default {
|
||||
}, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
},
|
||||
filterColumn (column, value, pivotColumn) {
|
||||
const {filtering} = this.getResolvedState()
|
||||
const {onFilteringChange} = this.props
|
||||
|
||||
if (onFilteringChange) {
|
||||
return onFilteringChange(column, value, pivotColumn)
|
||||
}
|
||||
|
||||
// Remove old filter first if it exists
|
||||
const newFiltering = (filtering || []).filter(x => {
|
||||
if (x.id !== column.id) {
|
||||
return true
|
||||
}
|
||||
if (x.pivotId) {
|
||||
if (pivotColumn) {
|
||||
return x.pivotId !== pivotColumn.id
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
if (value !== '') {
|
||||
newFiltering.push({
|
||||
id: column.id,
|
||||
value: value,
|
||||
pivotId: pivotColumn ? pivotColumn.id : undefined
|
||||
})
|
||||
}
|
||||
|
||||
this.setStateWithData({
|
||||
filtering: newFiltering
|
||||
}, () => {
|
||||
this.fireOnChange()
|
||||
})
|
||||
},
|
||||
resizeColumnStart (column, event, isTouch) {
|
||||
const {onResize} = this.props
|
||||
|
||||
if (onResize) {
|
||||
return onResize(column, event, isTouch)
|
||||
}
|
||||
|
||||
const parentWidth = event.target.parentElement.getBoundingClientRect().width
|
||||
|
||||
let pageX
|
||||
if (isTouch) {
|
||||
pageX = event.changedTouches[0].pageX
|
||||
} else {
|
||||
pageX = event.pageX
|
||||
}
|
||||
|
||||
this.setStateWithData({
|
||||
currentlyResizing: {
|
||||
id: column.id,
|
||||
startX: pageX,
|
||||
parentWidth: parentWidth
|
||||
}
|
||||
}, () => {
|
||||
if (isTouch) {
|
||||
document.addEventListener('touchmove', this.resizeColumnMoving)
|
||||
document.addEventListener('touchcancel', this.resizeColumnEnd)
|
||||
document.addEventListener('touchend', this.resizeColumnEnd)
|
||||
} else {
|
||||
document.addEventListener('mousemove', this.resizeColumnMoving)
|
||||
document.addEventListener('mouseup', this.resizeColumnEnd)
|
||||
document.addEventListener('mouseleave', this.resizeColumnEnd)
|
||||
}
|
||||
})
|
||||
},
|
||||
resizeColumnEnd (event) {
|
||||
let isTouch = event.type === 'touchend' || event.type === 'touchcancel'
|
||||
|
||||
if (isTouch) {
|
||||
document.removeEventListener('touchmove', this.resizeColumnMoving)
|
||||
document.removeEventListener('touchcancel', this.resizeColumnEnd)
|
||||
document.removeEventListener('touchend', this.resizeColumnEnd)
|
||||
}
|
||||
|
||||
// If its a touch event clear the mouse one's as well because sometimes
|
||||
// the mouseDown event gets called as well, but the mouseUp event doesn't
|
||||
document.removeEventListener('mousemove', this.resizeColumnMoving)
|
||||
document.removeEventListener('mouseup', this.resizeColumnEnd)
|
||||
document.removeEventListener('mouseleave', this.resizeColumnEnd)
|
||||
|
||||
// The touch events don't propagate up to the sorting's onMouseDown event so
|
||||
// no need to prevent it from happening or else the first click after a touch
|
||||
// event resize will not sort the column.
|
||||
if (!isTouch) {
|
||||
this.setStateWithData({
|
||||
skipNextSort: true
|
||||
})
|
||||
}
|
||||
},
|
||||
resizeColumnMoving (event) {
|
||||
const {resizing, currentlyResizing} = this.getResolvedState()
|
||||
|
||||
// Delete old value
|
||||
const newResizing = resizing.filter(x => x.id !== currentlyResizing.id)
|
||||
|
||||
let pageX
|
||||
|
||||
if (event.type === 'touchmove') {
|
||||
pageX = event.changedTouches[0].pageX
|
||||
} else if (event.type === 'mousemove') {
|
||||
pageX = event.pageX
|
||||
}
|
||||
|
||||
// Set the min size to 10 to account for margin and border or else the group headers don't line up correctly
|
||||
const newWidth = Math.max(currentlyResizing.parentWidth + pageX - currentlyResizing.startX, 11)
|
||||
|
||||
newResizing.push({
|
||||
id: currentlyResizing.id,
|
||||
value: newWidth
|
||||
})
|
||||
|
||||
this.setStateWithData({
|
||||
resizing: newResizing
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+14
-6
@@ -4,7 +4,7 @@ import classnames from 'classnames'
|
||||
// import _ from './utils'
|
||||
|
||||
const defaultButton = (props) => (
|
||||
<button {...props} className='-btn'>{props.children}</button>
|
||||
<button type='button' {...props} className='-btn'>{props.children}</button>
|
||||
)
|
||||
|
||||
export default React.createClass({
|
||||
@@ -17,12 +17,17 @@ export default React.createClass({
|
||||
this.setState({page: nextProps.page})
|
||||
},
|
||||
getSafePage (page) {
|
||||
if (isNaN(page)) {
|
||||
page = this.props.page
|
||||
}
|
||||
return Math.min(Math.max(page, 0), this.props.pages - 1)
|
||||
},
|
||||
changePage (page) {
|
||||
page = this.getSafePage(page)
|
||||
this.setState({page})
|
||||
this.props.onPageChange(page)
|
||||
if (this.props.page !== page) {
|
||||
this.props.onPageChange(page)
|
||||
}
|
||||
},
|
||||
applyPage (e) {
|
||||
e && e.preventDefault()
|
||||
@@ -66,9 +71,7 @@ export default React.createClass({
|
||||
<div className='-center'>
|
||||
<span className='-pageInfo'>
|
||||
{this.props.pageText} {showPageJump ? (
|
||||
<form className='-pageJump'
|
||||
onSubmit={this.applyPage}
|
||||
>
|
||||
<div className='-pageJump'>
|
||||
<input
|
||||
type={this.state.page === '' ? 'text' : 'number'}
|
||||
onChange={e => {
|
||||
@@ -81,8 +84,13 @@ export default React.createClass({
|
||||
}}
|
||||
value={this.state.page === '' ? '' : this.state.page + 1}
|
||||
onBlur={this.applyPage}
|
||||
onKeyPress={e => {
|
||||
if (e.which === 13 || e.keyCode === 13) {
|
||||
this.applyPage()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
) : (
|
||||
<span className='-currentPage'>{page + 1}</span>
|
||||
)} {this.props.ofText} <span className='-totalPages'>{pages}</span>
|
||||
|
||||
+2
-2
@@ -80,7 +80,7 @@ function orderBy (arr, funcs, dirs) {
|
||||
}
|
||||
return dirs[0]
|
||||
? a.__index - b.__index
|
||||
: b.__index - b.__index
|
||||
: b.__index - a.__index
|
||||
})
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ function isSortingDesc (d) {
|
||||
|
||||
function normalizeComponent (Comp, params = {}, fallback = Comp) {
|
||||
return typeof Comp === 'function' ? (
|
||||
Comp.prototype.isReactComponent ? (
|
||||
Object.getPrototypeOf(Comp).isReactComponent ? (
|
||||
<Comp
|
||||
{...params}
|
||||
/>
|
||||
|
||||
@@ -161,6 +161,7 @@ const columns = [{
|
||||
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../src/index'
|
||||
|
||||
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'
|
||||
}]
|
||||
}]
|
||||
|
||||
class ControlledTable extends React.Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.sortChange = this.sortChange.bind(this)
|
||||
this.state = {
|
||||
sorting: [],
|
||||
page: 0,
|
||||
pageSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
sortChange(column, shift) {
|
||||
if(shift)
|
||||
alert('Shift click not implemented in this demo')
|
||||
var sort = {id: column.id}
|
||||
if(this.state.sorting.length && this.state.sorting[0].id == column.id)
|
||||
this.state.sorting[0].asc ? sort.desc = true : sort.asc = true
|
||||
else
|
||||
sort.asc = true
|
||||
this.setState({
|
||||
sorting: [sort]
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
sorting={this.state.sorting}
|
||||
onSortingChange={this.sortChange}
|
||||
page={this.state.page}
|
||||
onPageChange={page => this.setState({page})}
|
||||
pageSize={this.state.pageSize}
|
||||
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: For simplicity, multi-sort is not implemented in this demo</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `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'
|
||||
}]
|
||||
}]
|
||||
|
||||
class ControlledTable extends React.Component {
|
||||
constructor() {
|
||||
super()
|
||||
this.sortChange = this.sortChange.bind(this)
|
||||
this.state = {
|
||||
sorting: [],
|
||||
page: 0,
|
||||
pageSize: 10
|
||||
}
|
||||
}
|
||||
|
||||
sortChange(column, shift) {
|
||||
if(shift)
|
||||
alert('Shift click not implemented in this demo')
|
||||
var sort = {id: column.id}
|
||||
if(this.state.sorting.length && this.state.sorting[0].id == column.id)
|
||||
this.state.sorting[0].asc ? sort.desc = true : sort.asc = true
|
||||
else
|
||||
sort.asc = true
|
||||
this.setState({
|
||||
sorting: [sort]
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
sorting={this.state.sorting}
|
||||
onSortingChange={this.sortChange}
|
||||
page={this.state.page}
|
||||
onPageChange={page => this.setState({page})}
|
||||
pageSize={this.state.pageSize}
|
||||
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}`
|
||||
}
|
||||
|
||||
export default () => <ControlledTable />
|
||||
@@ -0,0 +1,264 @@
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../src/index'
|
||||
|
||||
class Filtering extends React.Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
||||
this.state = {
|
||||
tableOptions: {
|
||||
loading: false,
|
||||
showPagination: true,
|
||||
showPageSizeOptions: true,
|
||||
showPageJump: true,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
showFilters: true
|
||||
},
|
||||
data: data
|
||||
}
|
||||
|
||||
this.setTableOption = this.setTableOption.bind(this)
|
||||
}
|
||||
|
||||
render () {
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
filterMethod: (filter, row) => (row[filter.id].startsWith(filter.value) && row[filter.id].endsWith(filter.value))
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
filterMethod: (filter, row) => (row[filter.id].includes(filter.value))
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}, {
|
||||
header: 'Over 21',
|
||||
accessor: 'age',
|
||||
id: 'over',
|
||||
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
|
||||
filterMethod: (filter, row) => {
|
||||
if (filter.value === 'all') {
|
||||
return true
|
||||
}
|
||||
if (filter.value === 'true') {
|
||||
return row[filter.id] >= 21
|
||||
}
|
||||
return row[filter.id] < 21
|
||||
},
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<select
|
||||
onChange={event => onFilterChange(event.target.value)}
|
||||
style={{width: '100%'}}
|
||||
value={filter ? filter.value : 'all'}>
|
||||
<option value="all"></option>
|
||||
<option value="true">Can Drink</option>
|
||||
<option value="false">Can't Drink</option>
|
||||
</select>
|
||||
)
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{float: 'left'}}>
|
||||
<h1>Table Options</h1>
|
||||
<table>
|
||||
<tbody>
|
||||
{
|
||||
Object.keys(this.state.tableOptions).map(optionKey => {
|
||||
const optionValue = this.state.tableOptions[optionKey]
|
||||
return (
|
||||
<tr key={optionKey}>
|
||||
<td>{optionKey}</td>
|
||||
<td style={{paddingLeft: 10, paddingTop: 5}}>
|
||||
<input type="checkbox"
|
||||
name={optionKey}
|
||||
checked={optionValue}
|
||||
onChange={this.setTableOption}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className='table-wrap' style={{paddingLeft: 240}}>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={this.state.data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
defaultFilterMethod={(filter, row) => (String(row[filter.id]) === filter.value)}
|
||||
{...this.state.tableOptions}
|
||||
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={this.state.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>
|
||||
<div>
|
||||
<h1>Custom Filters In This Example</h1>
|
||||
<p>The default filter for all columns of a table if it is not specified in the configuration is set to match
|
||||
on values that start with the filter text. Example: age.startsWith("2").</p>
|
||||
<p>This example overrides the default filter behavior by setting
|
||||
the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the
|
||||
filter text. Example: age == "23")</p>
|
||||
<p>Each column can also be customized with the column <strong>filterMethod</strong> option:</p>
|
||||
<p>In this example the firstName column filters on the value starting with and ending with the filter
|
||||
value.</p>
|
||||
<p>In this example the lastName column filters on the value including the filter value anywhere in its
|
||||
text.</p>
|
||||
<p>To completely override the filter that is shown, you can set the <strong>filterRender</strong> column
|
||||
option. Using this option you can specify the JSX that is shown. The option is passed
|
||||
an <strong>onFilterChange</strong> method that must be called with the value that you wan't to
|
||||
pass to the <strong>filterMethod</strong> option whenever the filter has changed.</p>
|
||||
</div>
|
||||
<CodeHighlight>{() => this.getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
setTableOption (event) {
|
||||
const target = event.target
|
||||
const value = target.type === 'checkbox' ? target.checked : target.value
|
||||
const name = target.name
|
||||
this.setState({
|
||||
tableOptions: {
|
||||
...this.state.tableOptions,
|
||||
[name]: value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getCode () {
|
||||
return `
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
filterMethod: (filter, row) => (row[filter.id].startsWith(filter.value) && row[filter.id].endsWith(filter.value))
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
filterMethod: (filter, row) => (row[filter.id].includes(filter.value))
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}, {
|
||||
header: 'Over 21',
|
||||
accessor: 'age',
|
||||
id: 'over',
|
||||
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
|
||||
filterMethod: (filter, row) => {
|
||||
if (filter.value === 'all') {
|
||||
return true
|
||||
}
|
||||
if (filter.value === 'true') {
|
||||
return row[filter.id] >= 21
|
||||
}
|
||||
return row[filter.id] < 21
|
||||
},
|
||||
filterRender: ({filter, onFilterChange}) => (
|
||||
<select
|
||||
onChange={event => onFilterChange(event.target.value)}
|
||||
style={{width: '100%'}}
|
||||
value={filter ? filter.value : 'all'}>
|
||||
<option value="all"></option>
|
||||
<option value="true">Can Drink</option>
|
||||
<option value="false">Can't Drink</option>
|
||||
</select>
|
||||
)
|
||||
}]
|
||||
}]
|
||||
|
||||
export default (
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
defaultFilterMethod={(filter, row) => (String(row[filter.id]) === filter.value)}
|
||||
{...otherOptions}
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <Filtering />
|
||||
+32
-3
@@ -88,23 +88,52 @@ const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
accessor: 'firstName',
|
||||
footer: (
|
||||
<span><strong>Popular:</strong> {
|
||||
_.first(
|
||||
_.reduce(
|
||||
_.map(
|
||||
_.groupBy(
|
||||
data, d => d.firstName
|
||||
)
|
||||
),
|
||||
(a, b) => a.length > b.length ? a : b
|
||||
)
|
||||
).firstName}
|
||||
</span>
|
||||
)
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
accessor: d => d.lastName,
|
||||
footer: (
|
||||
<span><strong>Longest:</strong> {
|
||||
_.reduce(
|
||||
_.map(
|
||||
_.groupBy(
|
||||
data, d => d.lastName
|
||||
),
|
||||
(d, key) => key
|
||||
),
|
||||
(a, b) => a.length > b.length ? a : b
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
accessor: 'age',
|
||||
footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
|
||||
}]
|
||||
}]
|
||||
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
|
||||
@@ -33,11 +33,13 @@ export default () => {
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
|
||||
}
|
||||
},
|
||||
filterMethod: (filter, row) => (filter.value == `${row[filter.id]} (avg)`)
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
aggregate: vals => _.sum(vals),
|
||||
hideFilter: true
|
||||
}]
|
||||
}]
|
||||
|
||||
@@ -50,6 +52,7 @@ export default () => {
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
showFilters={true}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
@@ -104,11 +107,13 @@ const columns = [{
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
render: row => {
|
||||
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
|
||||
}
|
||||
},
|
||||
filterMethod: (filter, row) => (filter.value == \`\${row[filter.id]} (avg)\`)
|
||||
}, {
|
||||
header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
aggregate: vals => _.sum(vals),
|
||||
hideFilter: true
|
||||
}]
|
||||
}]
|
||||
|
||||
@@ -119,6 +124,7 @@ return (
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
showFilters={true}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
|
||||
+21
-7
@@ -14,23 +14,34 @@ const rawData = _.map(_.range(3424), d => {
|
||||
})
|
||||
|
||||
// Now let's mock the server. It's job is simple: use the table model to sort and return the page data
|
||||
const requestData = (pageSize, page, sorting) => {
|
||||
const requestData = (pageSize, page, sorting, filtering) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// On the server, you'll likely use SQL or noSQL or some other query language to do this.
|
||||
// For this mock, we'll just use lodash
|
||||
const sortedData = _.orderBy(rawData, sorting.map(sort => {
|
||||
let filteredData = rawData;
|
||||
if (filtering.length) {
|
||||
filteredData = filtering.reduce(
|
||||
(filteredSoFar, nextFilter) => {
|
||||
return filteredSoFar.filter(
|
||||
(row) => {
|
||||
return (row[nextFilter.id]+"").includes(nextFilter.value)
|
||||
})
|
||||
}
|
||||
, filteredData)
|
||||
}
|
||||
const sortedData = _.orderBy(filteredData, sorting.map(sort => {
|
||||
return row => {
|
||||
if (row[sort.id] === null || row[sort.id] === undefined) {
|
||||
return -Infinity
|
||||
}
|
||||
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id]
|
||||
}
|
||||
}), sorting.map(d => d.asc ? 'asc' : 'desc'))
|
||||
}), sorting.map(d => d.desc ? 'desc' : 'asc'))
|
||||
|
||||
// Be sure to send back the rows to be displayed and any other pertinent information, like how many pages there are total.
|
||||
const res = {
|
||||
rows: sortedData.slice(pageSize * page, (pageSize * page) + pageSize),
|
||||
pages: Math.ceil(rawData.length / pageSize)
|
||||
pages: Math.ceil(filteredData.length / pageSize)
|
||||
}
|
||||
|
||||
// Here we'll simulate a server response with 500ms of delay.
|
||||
@@ -48,13 +59,13 @@ const ServerSide = React.createClass({
|
||||
}
|
||||
},
|
||||
fetchData (state, instance) {
|
||||
console.log(state, instance)
|
||||
// Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model.
|
||||
// You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want.
|
||||
this.setState({loading: true})
|
||||
// Request the data however you want. Here, we'll use our mocked service we created earlier
|
||||
requestData(state.pageSize, state.page, state.sorting)
|
||||
requestData(state.pageSize, state.page, state.sorting, state.filtering)
|
||||
.then((res) => {
|
||||
console.log(res.rows)
|
||||
// Now just get the rows of data to your React Table (and update anything else like total pages or loading)
|
||||
this.setState({
|
||||
data: res.rows,
|
||||
@@ -82,6 +93,7 @@ const ServerSide = React.createClass({
|
||||
}]}
|
||||
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
|
||||
defaultPageSize={10}
|
||||
showFilters={true}
|
||||
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
|
||||
@@ -124,7 +136,8 @@ export default React.createClass({
|
||||
Axios.post('mysite.com/data', {
|
||||
pageSize: state.pageSize,
|
||||
page: state.page,
|
||||
sorting: state.sorting
|
||||
sorting: state.sorting,
|
||||
filtering: state.filtering
|
||||
})
|
||||
.then((res) => {
|
||||
// Now update your state!
|
||||
@@ -151,6 +164,7 @@ export default React.createClass({
|
||||
}]}
|
||||
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
|
||||
defaultPageSize={10}
|
||||
showFilters={true}
|
||||
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
|
||||
|
||||
@@ -77,6 +77,7 @@ const columns = [{
|
||||
// Display your table!
|
||||
return (
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
|
||||
+131
-65
@@ -5,77 +5,139 @@ import namor from 'namor'
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
import ReactTable from '../src/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)
|
||||
class SubComponents extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
||||
this.state = {
|
||||
tableOptions: {
|
||||
loading: false,
|
||||
showPagination: true,
|
||||
showPageSizeOptions: true,
|
||||
showPageJump: true,
|
||||
collapseOnSortingChange: true,
|
||||
collapseOnPageChange: true,
|
||||
collapseOnDataChange: true,
|
||||
freezeWhenExpanded: false,
|
||||
showFilters: false
|
||||
},
|
||||
data: data
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
this.setTableOption = this.setTableOption.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
header: 'Info',
|
||||
columns: [{
|
||||
header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
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>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
return (
|
||||
<div>
|
||||
<div style={{float: "left"}}>
|
||||
<h1>Table Options</h1>
|
||||
<table>
|
||||
<tbody>
|
||||
{
|
||||
Object.keys(this.state.tableOptions).map(optionKey => {
|
||||
const optionValue = this.state.tableOptions[optionKey];
|
||||
return (
|
||||
<tr key={optionKey}>
|
||||
<td>{optionKey}</td>
|
||||
<td style={{paddingLeft: 10, paddingTop: 5}}>
|
||||
<input type="checkbox"
|
||||
name={optionKey}
|
||||
checked={optionValue}
|
||||
onChange={this.setTableOption}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className='table-wrap' style={{paddingLeft: 240}}>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={this.state.data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
{...this.state.tableOptions}
|
||||
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={this.state.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>{() => this.getCode()}</CodeHighlight>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
<CodeHighlight>{() => getCode()}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function getCode () {
|
||||
return `
|
||||
setTableOption(event) {
|
||||
const target = event.target;
|
||||
const value = target.type === 'checkbox' ? target.checked : target.value;
|
||||
const name = target.name;
|
||||
this.setState({
|
||||
tableOptions: {
|
||||
...this.state.tableOptions,
|
||||
[name]: value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getCode() {
|
||||
return `
|
||||
const columns = [{
|
||||
header: 'Name',
|
||||
columns: [{
|
||||
@@ -99,6 +161,7 @@ export default (
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
{...otherOptions}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
@@ -125,4 +188,7 @@ export default (
|
||||
/>
|
||||
)
|
||||
`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default () => <SubComponents/>
|
||||
@@ -0,0 +1,20 @@
|
||||
const webpack = require('webpack')
|
||||
module.exports = {
|
||||
entry: './lib/index.js',
|
||||
output: {
|
||||
filename: './react-table.js',
|
||||
libraryTarget: 'umd',
|
||||
library: 'ReactTable'
|
||||
},
|
||||
externals: {
|
||||
react: {
|
||||
root: 'React',
|
||||
commonjs2: 'react',
|
||||
commonjs: 'react',
|
||||
amd: 'react'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin()
|
||||
]
|
||||
}
|
||||
@@ -121,6 +121,12 @@ accepts@~1.3.3:
|
||||
mime-types "~2.1.11"
|
||||
negotiator "0.6.1"
|
||||
|
||||
acorn-dynamic-import@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
|
||||
dependencies:
|
||||
acorn "^4.0.3"
|
||||
|
||||
acorn-globals@^1.0.4:
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf"
|
||||
@@ -145,10 +151,14 @@ acorn@^3.0.0, acorn@^3.0.4, acorn@^3.1.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
|
||||
|
||||
acorn@^4.0.1:
|
||||
acorn@^4.0.1, acorn@^4.0.3:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
|
||||
|
||||
acorn@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
|
||||
|
||||
airbnb-js-shims@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-1.0.1.tgz#7d5a7d772c8c6fdeb624ea3cef62506091b180b5"
|
||||
@@ -162,7 +172,7 @@ airbnb-js-shims@^1.0.1:
|
||||
string.prototype.padend "^3.0.0"
|
||||
string.prototype.padstart "^3.0.0"
|
||||
|
||||
ajv-keywords@^1.0.0:
|
||||
ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
||||
|
||||
@@ -344,6 +354,12 @@ async@^1.3.0, async@^1.4.2:
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||
|
||||
async@^2.1.2:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
async@~0.2.6:
|
||||
version "0.2.10"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
||||
@@ -1445,7 +1461,7 @@ buffer-xor@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
|
||||
|
||||
buffer@^4.1.0, buffer@^4.9.0:
|
||||
buffer@^4.1.0, buffer@^4.3.0, buffer@^4.9.0:
|
||||
version "4.9.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
|
||||
dependencies:
|
||||
@@ -1550,7 +1566,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
|
||||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
chokidar@^1.0.0, chokidar@^1.5.1, chokidar@~1.6.0:
|
||||
chokidar@^1.0.0, chokidar@^1.4.3, chokidar@^1.5.1, chokidar@~1.6.0:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
|
||||
dependencies:
|
||||
@@ -1845,7 +1861,7 @@ crypto-browserify@3.3.0:
|
||||
ripemd160 "0.2.0"
|
||||
sha.js "2.2.6"
|
||||
|
||||
crypto-browserify@^3.0.0:
|
||||
crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
|
||||
version "3.11.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522"
|
||||
dependencies:
|
||||
@@ -2175,6 +2191,15 @@ encoding@^0.1.11:
|
||||
dependencies:
|
||||
iconv-lite "~0.4.13"
|
||||
|
||||
enhanced-resolve@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
memory-fs "^0.4.0"
|
||||
object-assign "^4.0.1"
|
||||
tapable "^0.2.5"
|
||||
|
||||
enhanced-resolve@~0.9.0:
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
|
||||
@@ -2998,7 +3023,7 @@ indexof@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
|
||||
|
||||
inflight@^1.0.4, inflight@^1.0.6:
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
dependencies:
|
||||
@@ -3355,7 +3380,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
|
||||
json5@^0.5.0:
|
||||
json5@^0.5.0, json5@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
|
||||
@@ -3437,6 +3462,10 @@ load-json-file@^1.0.0:
|
||||
pinkie-promise "^2.0.0"
|
||||
strip-bom "^2.0.0"
|
||||
|
||||
loader-runner@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
|
||||
|
||||
loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.7, loader-utils@~0.2.2, loader-utils@~0.2.5:
|
||||
version "0.2.16"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d"
|
||||
@@ -3514,7 +3543,7 @@ lodash.uniq@^4.3.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
lodash@4.x.x, lodash@^4.0.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
|
||||
lodash@4.x.x, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
|
||||
version "4.17.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||
|
||||
@@ -3598,16 +3627,16 @@ memory-fs@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
|
||||
|
||||
memory-fs@~0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
|
||||
memory-fs@^0.4.0, memory-fs@~0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
|
||||
dependencies:
|
||||
errno "^0.1.3"
|
||||
readable-stream "^2.0.1"
|
||||
|
||||
memory-fs@~0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
|
||||
memory-fs@~0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
|
||||
dependencies:
|
||||
errno "^0.1.3"
|
||||
readable-stream "^2.0.1"
|
||||
@@ -3817,6 +3846,34 @@ node-libs-browser@^0.7.0:
|
||||
util "^0.10.3"
|
||||
vm-browserify "0.0.4"
|
||||
|
||||
node-libs-browser@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646"
|
||||
dependencies:
|
||||
assert "^1.1.1"
|
||||
browserify-zlib "^0.1.4"
|
||||
buffer "^4.3.0"
|
||||
console-browserify "^1.1.0"
|
||||
constants-browserify "^1.0.0"
|
||||
crypto-browserify "^3.11.0"
|
||||
domain-browser "^1.1.1"
|
||||
events "^1.0.0"
|
||||
https-browserify "0.0.1"
|
||||
os-browserify "^0.2.0"
|
||||
path-browserify "0.0.0"
|
||||
process "^0.11.0"
|
||||
punycode "^1.2.4"
|
||||
querystring-es3 "^0.2.0"
|
||||
readable-stream "^2.0.5"
|
||||
stream-browserify "^2.0.1"
|
||||
stream-http "^2.3.1"
|
||||
string_decoder "^0.10.25"
|
||||
timers-browserify "^2.0.2"
|
||||
tty-browserify "0.0.0"
|
||||
url "^0.11.0"
|
||||
util "^0.10.3"
|
||||
vm-browserify "0.0.4"
|
||||
|
||||
node-pre-gyp@^0.6.29:
|
||||
version "0.6.32"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5"
|
||||
@@ -4958,7 +5015,13 @@ right-align@^0.1.1:
|
||||
dependencies:
|
||||
align-text "^0.1.1"
|
||||
|
||||
rimraf@2, rimraf@^2.2.8, rimraf@~2.5.1, rimraf@~2.5.4:
|
||||
rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
|
||||
dependencies:
|
||||
glob "^7.0.5"
|
||||
|
||||
rimraf@~2.5.1, rimraf@~2.5.4:
|
||||
version "2.5.4"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
|
||||
dependencies:
|
||||
@@ -5154,6 +5217,10 @@ source-list-map@^0.1.4, source-list-map@~0.1.7:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
|
||||
|
||||
source-list-map@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.1.tgz#1a33ac210ca144d1e561f906ebccab5669ff4cb4"
|
||||
|
||||
source-map-support@^0.4.2:
|
||||
version "0.4.10"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.10.tgz#d7b19038040a14c0837a18e630a196453952b378"
|
||||
@@ -5293,7 +5360,7 @@ strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
|
||||
string-width@^1.0.1:
|
||||
string-width@^1.0.1, string-width@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||
dependencies:
|
||||
@@ -5436,6 +5503,10 @@ tapable@^0.1.8, tapable@~0.1.8:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
|
||||
|
||||
tapable@^0.2.5, tapable@~0.2.5:
|
||||
version "0.2.6"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
|
||||
|
||||
tar-pack@~3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae"
|
||||
@@ -5556,6 +5627,15 @@ uglify-js@2.7.x, uglify-js@2.x.x, uglify-js@~2.7.3:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
yargs "~3.10.0"
|
||||
|
||||
uglify-js@^2.8.5:
|
||||
version "2.8.22"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
|
||||
dependencies:
|
||||
source-map "~0.5.1"
|
||||
yargs "~3.10.0"
|
||||
optionalDependencies:
|
||||
uglify-to-browserify "~1.0.0"
|
||||
|
||||
uglify-to-browserify@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
|
||||
@@ -5687,6 +5767,14 @@ watchpack@^0.2.1:
|
||||
chokidar "^1.0.0"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
watchpack@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87"
|
||||
dependencies:
|
||||
async "^2.1.2"
|
||||
chokidar "^1.4.3"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
webidl-conversions@^3.0.0, webidl-conversions@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
@@ -5716,6 +5804,13 @@ webpack-hot-middleware@^2.13.2:
|
||||
querystring "^0.2.0"
|
||||
strip-ansi "^3.0.0"
|
||||
|
||||
webpack-sources@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb"
|
||||
dependencies:
|
||||
source-list-map "^1.1.1"
|
||||
source-map "~0.5.3"
|
||||
|
||||
webpack@^1.13.1:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.14.0.tgz#54f1ffb92051a328a5b2057d6ae33c289462c823"
|
||||
@@ -5736,6 +5831,32 @@ webpack@^1.13.1:
|
||||
watchpack "^0.2.1"
|
||||
webpack-core "~0.6.9"
|
||||
|
||||
webpack@^2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.4.1.tgz#15a91dbe34966d8a4b99c7d656efd92a2e5a6f6a"
|
||||
dependencies:
|
||||
acorn "^5.0.0"
|
||||
acorn-dynamic-import "^2.0.0"
|
||||
ajv "^4.7.0"
|
||||
ajv-keywords "^1.1.1"
|
||||
async "^2.1.2"
|
||||
enhanced-resolve "^3.0.0"
|
||||
interpret "^1.0.0"
|
||||
json-loader "^0.5.4"
|
||||
json5 "^0.5.1"
|
||||
loader-runner "^2.3.0"
|
||||
loader-utils "^0.2.16"
|
||||
memory-fs "~0.4.1"
|
||||
mkdirp "~0.5.0"
|
||||
node-libs-browser "^2.0.0"
|
||||
source-map "^0.5.3"
|
||||
supports-color "^3.1.0"
|
||||
tapable "~0.2.5"
|
||||
uglify-js "^2.8.5"
|
||||
watchpack "^1.3.1"
|
||||
webpack-sources "^0.2.3"
|
||||
yargs "^6.0.0"
|
||||
|
||||
whatwg-encoding@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4"
|
||||
@@ -5851,6 +5972,12 @@ yargs-parser@^2.4.1:
|
||||
camelcase "^3.0.0"
|
||||
lodash.assign "^4.0.6"
|
||||
|
||||
yargs-parser@^4.2.0:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
|
||||
dependencies:
|
||||
camelcase "^3.0.0"
|
||||
|
||||
yargs@^4.7.1:
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
|
||||
@@ -5870,6 +5997,24 @@ yargs@^4.7.1:
|
||||
y18n "^3.2.1"
|
||||
yargs-parser "^2.4.1"
|
||||
|
||||
yargs@^6.0.0:
|
||||
version "6.6.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
|
||||
dependencies:
|
||||
camelcase "^3.0.0"
|
||||
cliui "^3.2.0"
|
||||
decamelize "^1.1.1"
|
||||
get-caller-file "^1.0.1"
|
||||
os-locale "^1.4.0"
|
||||
read-pkg-up "^1.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^1.0.1"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^1.0.2"
|
||||
which-module "^1.0.0"
|
||||
y18n "^3.2.1"
|
||||
yargs-parser "^4.2.0"
|
||||
|
||||
yargs@~3.10.0:
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
|
||||
|
||||
Reference in New Issue
Block a user