mirror of
https://github.com/gosticks/react-table.git
synced 2026-08-19 08:20:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adc07de817 | ||
|
|
e94e88849a | ||
|
|
2dcfef884f | ||
|
|
d798584208 | ||
|
|
5759885983 | ||
|
|
e59ddc1f8d | ||
|
|
35e8636fd1 | ||
|
|
bb2f969db9 | ||
|
|
cd0222fcd2 | ||
|
|
93ceffbf26 | ||
|
|
879a6ac273 | ||
|
|
b285288849 | ||
|
|
05f4aaef2e | ||
|
|
2b9c546132 | ||
|
|
55ef8a9e7d | ||
|
|
189ee436f9 | ||
|
|
225a74770b | ||
|
|
fa425a162a | ||
|
|
e42b7bbd7d | ||
|
|
9efee144a8 | ||
|
|
56b721c185 | ||
|
|
e91bb91ea1 | ||
|
|
dadfcc121c | ||
|
|
8cec156d13 | ||
|
|
5c531095a9 | ||
|
|
8d4deb3496 | ||
|
|
646b701f93 | ||
|
|
3043cbe4b4 | ||
|
|
fcb82694bb | ||
|
|
e8c557d70e | ||
|
|
ff95c21440 | ||
|
|
2630161222 | ||
|
|
e67072edae | ||
|
|
fb569ad592 | ||
|
|
b957503612 | ||
|
|
3d9b7b1186 | ||
|
|
e3528fef38 | ||
|
|
6b192bd363 | ||
|
|
0725f2159d | ||
|
|
5d2deda246 | ||
|
|
2961eb8a18 | ||
|
|
d170adb6a7 | ||
|
|
d8aec06496 | ||
|
|
8efeef3b8b | ||
|
|
8004e7a85f | ||
|
|
84af88916a | ||
|
|
9846bf1905 | ||
|
|
bf88dda5dc | ||
|
|
7f5779a833 | ||
|
|
8792bd95a0 | ||
|
|
098b1fec51 | ||
|
|
750cfe3ac4 | ||
|
|
370f443347 | ||
|
|
67f8c9adf1 | ||
|
|
867cc25899 | ||
|
|
639630946c | ||
|
|
688afd2947 | ||
|
|
bbebf02a55 | ||
|
|
f4d3c2d7bb | ||
|
|
f8634e771e | ||
|
|
ba74ab3ce8 | ||
|
|
30ed0c82fc | ||
|
|
62f19aecf0 | ||
|
|
8dc4caff45 | ||
|
|
c2e935d75b | ||
|
|
f9a1cfae1e | ||
|
|
5ac2c1779d | ||
|
|
3b2432f535 | ||
|
|
7aa98887ef | ||
|
|
d26d82ecfb | ||
|
|
b76f9c956d | ||
|
|
2e3743b75f |
+1
-72
@@ -1,74 +1,3 @@
|
||||
module.exports = {
|
||||
parserOptions: {
|
||||
ecmaVersion: 8,
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true,
|
||||
node: false
|
||||
},
|
||||
sourceType: 'module'
|
||||
},
|
||||
|
||||
extends: ['standard'],
|
||||
|
||||
plugins: ['react'],
|
||||
|
||||
rules: {
|
||||
// Nozzle
|
||||
'jsx-quotes': [2, 'prefer-single'],
|
||||
'comma-dangle': [2, 'always-multiline'],
|
||||
|
||||
// // React
|
||||
'react/jsx-boolean-value': 2,
|
||||
'react/jsx-curly-spacing': [2, 'never'],
|
||||
'react/jsx-equals-spacing': [2, 'never'],
|
||||
// 'react/jsx-indent': 2,
|
||||
'react/jsx-indent-props': [2, 2],
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-tag-spacing': [
|
||||
2,
|
||||
{
|
||||
closingSlash: 'never',
|
||||
beforeSelfClosing: 'always',
|
||||
afterOpening: 'never'
|
||||
}
|
||||
],
|
||||
'react/jsx-uses-react': 2,
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/jsx-no-bind': [
|
||||
2,
|
||||
{
|
||||
allowArrowFunctions: true,
|
||||
allowBind: false,
|
||||
ignoreRefs: true
|
||||
}
|
||||
],
|
||||
'react/no-did-update-set-state': 2,
|
||||
'react/no-unknown-property': 2,
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/jsx-closing-bracket-location': [2, 'tag-aligned'],
|
||||
'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
|
||||
'react/jsx-wrap-multilines': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/jsx-key': 2,
|
||||
'react/jsx-no-comment-textnodes': 2,
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-target-blank': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-uses-react': 2,
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/no-danger-with-children': 2,
|
||||
'react/no-deprecated': 2,
|
||||
'react/no-direct-mutation-state': 2,
|
||||
'react/no-find-dom-node': 2,
|
||||
'react/no-is-mounted': 2,
|
||||
'react/no-render-return-value': 2,
|
||||
'react/no-string-refs': 2,
|
||||
'react/no-unknown-property': 2,
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/require-render-return': 2
|
||||
// 'react/jsx-max-props-per-line': [2, { maximum: 1 }]
|
||||
}
|
||||
extends: 'react-tools'
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 6.5.0
|
||||
##### New Features
|
||||
- `column.filterAll` - defaults to `false`, but when set to `true` will provide the entire array of rows to `filterMethod` as opposed to one row at a time. This allows for more fine-grained filtering using any method you can dream up. See the [Custom Filtering example](https://react-table.js.org/#/story/custom-filtering) for more info.
|
||||
|
||||
## 6.4.0
|
||||
##### New Features
|
||||
- `PadRowComponent` - the content rendered inside of a padding row. Defaults to a react component that renders ` `
|
||||
|
||||
## 6.3.0
|
||||
##### New Features
|
||||
- `defaultSortDesc` - allows you to set the default sorting direction for all columns to descending.
|
||||
|
||||
+11
-12
@@ -1,15 +1,14 @@
|
||||
## Problem Description
|
||||
include a detailed explanation of the problem here...
|
||||
## What version of React-Table are you using?
|
||||
Your bug may already be fixed in the latest release. Run `yarn upgrade react-table`!
|
||||
Place your version here...
|
||||
|
||||
## Code Snippet(s) or Codepen (http://codepen.io/tannerlinsley/pen/QpeZBa?editors=0010)
|
||||
## What bug are you experiencing, or what feature are you proposing?
|
||||
Please include a detailed explanation here...
|
||||
|
||||
## Steps to Reproduce
|
||||
## Use https://codesandbox.io/s/X6npLXPRW (by clicking the "Fork" button) to reproduce the issue.
|
||||
Then paste a link to your newly forked codesandbox here...
|
||||
|
||||
## What are the steps to reproduce the issue?
|
||||
1. list the steps
|
||||
2. to reproduce the issue
|
||||
|
||||
## System Information
|
||||
* **Browser & Browser Version:**
|
||||
* **Node Version:**
|
||||
* **OS Version:**
|
||||
* **NPM Version:**
|
||||
* **Yarn Version:**
|
||||
2. to reproduce
|
||||
3. the issue
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
<div align="center">
|
||||
<a href="https://github.com/tannerlinsley/react-table" target="\_parent"><img src="https://github.com/tannerlinsley/react-table/raw/master/media/Banner.png" alt="React Table Logo" style="width:450px;"/></a>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div style="text-align:center;">
|
||||
<a href="https://github.com/react-tools/react-table" target="\_parent"><img src="https://github.com/react-tools/media/raw/master/logo-react-table.png" alt="React Table Logo" style="width:450px;"/></a>
|
||||
</div>
|
||||
|
||||
# React Table
|
||||
`react-table` is a **lightweight, fast and extendable datagrid** built for React
|
||||
|
||||
|
||||
<a href="https://travis-ci.org/tannerlinsley/react-table" target="\_parent">
|
||||
<img alt="" src="https://travis-ci.org/tannerlinsley/react-table.svg?branch=master" />
|
||||
<a href="https://travis-ci.org/react-tools/react-table" target="\_parent">
|
||||
<img alt="" src="https://travis-ci.org/react-tools/react-table.svg?branch=master" />
|
||||
</a>
|
||||
<a href="https://npmjs.com/package/react-table" target="\_parent">
|
||||
<img alt="" src="https://img.shields.io/npm/dm/react-table.svg" />
|
||||
@@ -18,8 +14,8 @@
|
||||
<a href="https://react-chat-signup.herokuapp.com/" target="\_parent">
|
||||
<img alt="" src="https://img.shields.io/badge/slack-react--chat-blue.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/tannerlinsley/react-table" target="\_parent">
|
||||
<img alt="" src="https://img.shields.io/github/stars/tannerlinsley/react-table.svg?style=social&label=Star" />
|
||||
<a href="https://github.com/react-tools/react-table" target="\_parent">
|
||||
<img alt="" src="https://img.shields.io/github/stars/react-tools/react-table.svg?style=social&label=Star" />
|
||||
</a>
|
||||
<a href="https://twitter.com/tannerlinsley" target="\_parent">
|
||||
<img alt="" src="https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow" />
|
||||
@@ -28,25 +24,29 @@
|
||||
<img alt="" src="https://img.shields.io/badge/%24-Donate-brightgreen.svg" />
|
||||
</a>
|
||||
|
||||
## Versions
|
||||
This document refers to version 6.x.x of react-table.
|
||||
<br />
|
||||
<br />
|
||||
|
||||
Previous versions:
|
||||
|
||||
[5.x.x Readme](https://github.com/tannerlinsley/react-table/blob/ad7d31cd3978eb45da7c6194dbab93c1e9a8594d/README.md)
|
||||
[](https://app.codesponsor.io/link/zpmS8V9r31sBSCeVzP7Wm6Sr/react-tools/react-table)
|
||||
|
||||
## Features
|
||||
- Lightweight at 7kb (and just 2kb more for styles)
|
||||
- Fully customizable JSX templating
|
||||
- Supports both Client-side & Server-side pagination and multi-sorting
|
||||
- Column Pivoting & Aggregation
|
||||
- Lightweight at 11kb (and just 2kb more for styles)
|
||||
- Fully customizable (JSX, templates, state, styles, callbacks)
|
||||
- Client-side & Server-side pagination
|
||||
- Multi-sort
|
||||
- Filters
|
||||
- Pivoting & Aggregation
|
||||
- Minimal design & easily themeable
|
||||
- Fully controllable via optional props and callbacks
|
||||
- <a href="https://medium.com/@tannerlinsley/why-i-wrote-react-table-and-the-problems-it-has-solved-for-nozzle-others-445c4e93d4a8#.axza4ixba" target="\_parent">"Why I wrote React Table and the problems it has solved for Nozzle.io</a> by Tanner Linsley
|
||||
|
||||
## Demos and examples
|
||||
- <a href="http://codepen.io/tannerlinsley/pen/QpeZBa?editors=0010" target="\_blank">Codepen</a>
|
||||
- <a href="http://react-table.js.org/#/story/simple-table" target="\_parent">Storybook</a>
|
||||
## [Demos and examples](http://react-table.js.org/#/story/simple-table)
|
||||
|
||||
## Versions
|
||||
- This documentation is for version 6 of react-table.
|
||||
- [View the Changelog](https://github.com/react-tools/react-table/blob/master/CHANGELOG.md)
|
||||
- Previous versions:
|
||||
- [5.x.x Readme](https://github.com/react-tools/react-table/blob/ad7d31cd3978eb45da7c6194dbab93c1e9a8594d/README.md)
|
||||
|
||||
## Table of Contents
|
||||
- [Installation](#installation)
|
||||
@@ -74,7 +74,11 @@ Previous versions:
|
||||
## Installation
|
||||
1. Install React Table as a dependency
|
||||
```bash
|
||||
# Yarn
|
||||
$ yarn add react-table
|
||||
|
||||
# NPM
|
||||
$ npm install react-table
|
||||
```
|
||||
2. Import the `react-table` module
|
||||
```javascript
|
||||
@@ -178,7 +182,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
const id = filter.pivotId || filter.id
|
||||
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
|
||||
},
|
||||
defaultSortMethod: (a, b) => {
|
||||
defaultSortMethod: (a, b, desc) => {
|
||||
// force null and undefined to the bottom
|
||||
a = (a === null || a === undefined) ? -Infinity : a
|
||||
b = (b === null || b === undefined) ? -Infinity : b
|
||||
@@ -195,6 +199,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
// returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker
|
||||
return 0
|
||||
},
|
||||
PadRowComponent: () => <span> </span>, // the content rendered inside of a padding row
|
||||
|
||||
// Controlled State Overrides (see Fully Controlled Component section)
|
||||
page: undefined,
|
||||
@@ -286,6 +291,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
footerClassName: '',
|
||||
footerStyle: {},
|
||||
getFooterProps: () => ({}),
|
||||
filterAll: false,
|
||||
filterMethod: undefined,
|
||||
sortMethod: undefined,
|
||||
defaultSortDesc: undefined,
|
||||
@@ -306,7 +312,7 @@ These are all of the available props (and their default values) for the main `<R
|
||||
previousText: 'Previous',
|
||||
nextText: 'Next',
|
||||
loadingText: 'Loading...',
|
||||
noDataText: 'No rows found',
|
||||
noDataText: 'No rows found',
|
||||
pageText: 'Page',
|
||||
ofText: 'of',
|
||||
rowsText: 'rows',
|
||||
@@ -396,10 +402,11 @@ Or just define them as props
|
||||
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
|
||||
filterMethod: (filter, row || rows, 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' || 'rows' == the row (or rows, if filterAll is set to true) of data supplied to the table
|
||||
// 'column' == the column that the filter is on
|
||||
filterAll: false
|
||||
}]
|
||||
```
|
||||
|
||||
@@ -483,7 +490,7 @@ const columns = [{
|
||||
}, {
|
||||
Header: 'Food',
|
||||
accessor: 'favorites.food'
|
||||
} {
|
||||
}, {
|
||||
Header: 'Actor',
|
||||
accessor: 'favorites.actor'
|
||||
}]
|
||||
@@ -573,6 +580,8 @@ Every single built-in component's props can be dynamically extended using any on
|
||||
/>
|
||||
```
|
||||
|
||||
If used, **a callback prop must return an valid object**, even if it's an empty one.
|
||||
|
||||
These callbacks are executed with each render of the element with four parameters:
|
||||
1. Table State
|
||||
2. RowInfo (undefined if not applicable)
|
||||
@@ -585,12 +594,21 @@ This makes it extremely easy to add, say... a row click callback!
|
||||
<ReactTable
|
||||
getTdProps={(state, rowInfo, column, instance) => {
|
||||
return {
|
||||
onClick: e => {
|
||||
onClick: (e, handleOriginal) => {
|
||||
console.log('A Td Element was clicked!')
|
||||
console.log('it produced this event:', e)
|
||||
console.log('It was in this column:', column)
|
||||
console.log('It was in this row:', rowInfo)
|
||||
console.log('It was in this table instance:', instance)
|
||||
|
||||
// IMPORTANT! React-Table uses onClick internally to trigger
|
||||
// events like expanding SubComponents and pivots.
|
||||
// By default a custom 'onClick' handler will override this functionality.
|
||||
// If you want to fire the original onClick handler, call the
|
||||
// 'handleOriginal' function.
|
||||
if (handleOriginal) {
|
||||
handleOriginal()
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -723,7 +741,7 @@ If you want to handle pagination, sorting, and filtering on the server, `react-t
|
||||
/>
|
||||
```
|
||||
|
||||
For a detailed example, take a peek at our <a href="https://github.com/tannerlinsley/react-table/blob/master/stories/ServerSide.js" target="\_parent">async table mockup</a>
|
||||
For a detailed example, take a peek at our <a href="https://github.com/react-tools/react-table/blob/master/stories/ServerSide.js" target="\_parent">async table mockup</a>
|
||||
|
||||
## Fully Controlled Component
|
||||
React Table by default works fantastically out of the box, but you can achieve even more control and customization if you choose to maintain the state yourself. It is very easy to do, even if you only want to manage *parts* of the state.
|
||||
@@ -741,7 +759,7 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
id: 'firstName',
|
||||
desc: true
|
||||
}]}
|
||||
expandedRows={{ // The nested row indexes on the current page that should appear expanded
|
||||
expanded={{ // The nested row indexes on the current page that should appear expanded
|
||||
1: true,
|
||||
4: true,
|
||||
5: {
|
||||
@@ -749,11 +767,11 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
3: true
|
||||
}
|
||||
}}
|
||||
filters={[{ // the current filters model
|
||||
filtered={[{ // the current filters model
|
||||
id: 'lastName',
|
||||
value: 'linsley'
|
||||
}]}
|
||||
resizing={[{ // the current resized column model
|
||||
resized={[{ // the current resized column model
|
||||
"id": "lastName",
|
||||
"value": 446.25
|
||||
}]}
|
||||
@@ -762,8 +780,8 @@ Here are the props and their corresponding callbacks that control the state of t
|
||||
onPageChange={(pageIndex) => {...}} // Called when the page index is changed by the user
|
||||
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data
|
||||
onSortedChange={(newSorted, 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
|
||||
onExpandedChange={(newExpanded, index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
|
||||
onFilteredChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFiltersChange handler by the filterRender option.
|
||||
onExpandedChange={(newExpanded, index, event) => {...}} // Called when an expander is clicked. Use this to manage `expanded`
|
||||
onFilteredChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFiltersChange handler by the Filter option.
|
||||
onResizedChange={(newResized, event) => {...}} // Called when a user clicks on a resizing component (the right edge of a column header)
|
||||
/>
|
||||
```
|
||||
@@ -823,9 +841,9 @@ To override the sorting algorithm for a single column, use the `sortMethod` colu
|
||||
Supply a function that implements the native javascript [`Array.sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) interface. This is React Table's default sorting algorithm:
|
||||
- `a` the first value to compare
|
||||
- `b` the second value to compare
|
||||
- `dir` the
|
||||
- `desc` true if sort is descending, false if ascending
|
||||
```javascript
|
||||
defaultSortMethod = (a, b) => {
|
||||
defaultSortMethod = (a, b, desc) => {
|
||||
// force null and undefined to the bottom
|
||||
a = (a === null || a === undefined) ? -Infinity : a
|
||||
b = (b === null || b === undefined) ? -Infinity : b
|
||||
@@ -853,7 +871,11 @@ By default the table tries to filter by checking if the row's value starts with
|
||||
|
||||
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 `Filter` column option. Using this option you can specify the JSX that is shown. The option is passed an `onChange` method which must be called with the the value that you wan't to pass to the `filterMethod` option whenever the filter has changed.
|
||||
By default, `filterMethod` is passed a single row of data at a time, and you are responsible for returning `true` or `false`, indicating whether it should be shown.
|
||||
|
||||
Alternatively, you can set `filterAll` to `true`, and `filterMethod` will be passed the entire array of rows to be filtered, and you will then be responsible for returning the new filtered array. This is extremely handy when you need to utilize a utility like fuzzy matching that requires the entire array of items.
|
||||
|
||||
To completely override the filter that is shown, you can set the `Filter` column option. Using this option you can specify the JSX that is shown. The option is passed an `onChange` method which must be called with the the value that you want to pass to the `filterMethod` option whenever the filter has changed.
|
||||
|
||||
See <a href="http://react-table.js.org/#/story/custom-filtering" target="\_parent">Custom Filtering</a> demo for examples.
|
||||
|
||||
@@ -868,7 +890,7 @@ Object.assign(ReactTableDefaults, {
|
||||
TbodyComponent: component,
|
||||
TrGroupComponent: component,
|
||||
TrComponent: component,
|
||||
ThComponent: component
|
||||
ThComponent: component,
|
||||
TdComponent: component,
|
||||
TfootComponent: component,
|
||||
ExpanderComponent: component,
|
||||
@@ -892,7 +914,7 @@ Object.assign(ReactTableDefaults, {
|
||||
/>
|
||||
```
|
||||
|
||||
If you choose to change the core components React-Table uses to render, you must make sure your replacement components consume and utilize all of the supplied and inherited props that are needed for that component to function properly. We would suggest investigating <a href="https://github.com/tannerlinsley/react-table/blob/master/src/index.js" target="\_parent">the source</a> for the component you wish to replace.
|
||||
If you choose to change the core components React-Table uses to render, you must make sure your replacement components consume and utilize all of the supplied and inherited props that are needed for that component to function properly. We would suggest investigating <a href="https://github.com/react-tools/react-table/blob/master/src/index.js" target="\_parent">the source</a> for the component you wish to replace.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
module.exports = {
|
||||
parserOptions: {
|
||||
ecmaVersion: 8,
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true,
|
||||
node: false,
|
||||
classes: true
|
||||
},
|
||||
sourceType: 'module'
|
||||
},
|
||||
|
||||
parser: 'babel-eslint',
|
||||
|
||||
extends: ['standard'],
|
||||
|
||||
plugins: ['react'],
|
||||
|
||||
rules: {
|
||||
// Nozzle
|
||||
'jsx-quotes': [2, 'prefer-single'],
|
||||
'comma-dangle': [2, 'always-multiline'],
|
||||
|
||||
// // React
|
||||
'react/jsx-boolean-value': 2,
|
||||
'react/jsx-curly-spacing': [2, 'never'],
|
||||
'react/jsx-equals-spacing': [2, 'never'],
|
||||
// 'react/jsx-indent': 2,
|
||||
'react/jsx-indent-props': [2, 2],
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-tag-spacing': [
|
||||
2,
|
||||
{
|
||||
closingSlash: 'never',
|
||||
beforeSelfClosing: 'always',
|
||||
afterOpening: 'never'
|
||||
}
|
||||
],
|
||||
'react/jsx-uses-react': 2,
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/jsx-no-bind': [
|
||||
2,
|
||||
{
|
||||
allowArrowFunctions: true,
|
||||
allowBind: false,
|
||||
ignoreRefs: true
|
||||
}
|
||||
],
|
||||
'react/no-did-update-set-state': 2,
|
||||
'react/no-unknown-property': 2,
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/jsx-closing-bracket-location': [0, 'tag-aligned'],
|
||||
'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
|
||||
'react/jsx-wrap-multilines': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/jsx-key': 2,
|
||||
'react/jsx-no-comment-textnodes': 2,
|
||||
'react/jsx-no-duplicate-props': 2,
|
||||
'react/jsx-no-target-blank': 2,
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-uses-react': 2,
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/no-danger-with-children': 2,
|
||||
'react/no-deprecated': 2,
|
||||
'react/no-direct-mutation-state': 2,
|
||||
'react/no-find-dom-node': 2,
|
||||
'react/no-is-mounted': 2,
|
||||
'react/no-render-return-value': 2,
|
||||
'react/no-string-refs': 2,
|
||||
'react/no-unknown-property': 2,
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/require-render-return': 2
|
||||
// 'react/jsx-max-props-per-line': [2, { maximum: 1 }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
react-table.js.org
|
||||
+20
-2
@@ -3,10 +3,26 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"react-scripts": "0.9.5",
|
||||
"standard": "^10.0.2"
|
||||
"autoprefixer": "^6.7.0",
|
||||
"babel-cli": "6.14.0",
|
||||
"babel-eslint": "6.1.2",
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
"babel-preset-react": "6.11.1",
|
||||
"babel-preset-stage-2": "6.13.0",
|
||||
"eslint": "^4.1.1",
|
||||
"match-sorter": "^1.8.0",
|
||||
"npm-run-all": "^3.1.1",
|
||||
"onchange": "^3.0.2",
|
||||
"postcss-cli": "^2.6.0",
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"react-json-tree": "^0.10.9",
|
||||
"rimraf": "^2.6.1",
|
||||
"standard": "^10.0.2",
|
||||
"stylus": "^0.54.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"eslint-config-react-tools": "^1.0.10",
|
||||
"github-markdown-css": "^2.6.0",
|
||||
"marked": "^0.3.6",
|
||||
"namor": "^1.0.1",
|
||||
@@ -14,6 +30,8 @@
|
||||
"react": "^15.5.4",
|
||||
"react-dom": "^15.5.4",
|
||||
"react-json-tree": "^0.10.9",
|
||||
"react-script": "^2.0.5",
|
||||
"react-scripts": "^0.9.5",
|
||||
"react-story": "^0.0.10"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
+62
-68
@@ -1,109 +1,103 @@
|
||||
import React from 'react'
|
||||
//
|
||||
import ReactStory, { defaultProps } from 'react-story'
|
||||
|
||||
import CodeSandbox from './CodeSandbox.js'
|
||||
import './stories/utils/prism.css'
|
||||
import '../../react-table.css'
|
||||
|
||||
import Readme from './stories/Readme.js'
|
||||
import Simple from './stories/Simple.js'
|
||||
import CellRenderers from './stories/CellRenderers.js'
|
||||
import DefaultSorting from './stories/DefaultSorting.js'
|
||||
import CustomSorting from './stories/CustomSorting.js'
|
||||
import CustomWidths from './stories/CustomWidths.js'
|
||||
import CustomComponentProps from './stories/CustomComponentProps.js'
|
||||
import ServerSide from './stories/ServerSide.js'
|
||||
import SubComponents from './stories/SubComponents.js'
|
||||
import Pivoting from './stories/Pivoting.js'
|
||||
import PivotingSubComponents from './stories/PivotingSubComponents.js'
|
||||
import OneHundredKRows from './stories/OneHundredKRows.js'
|
||||
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'
|
||||
import PivotingOptions from './stories/PivotingOptions.js'
|
||||
import EditableTable from './stories/EditableTable.js'
|
||||
import FixedHeader from './stories/FixedHeader.js'
|
||||
import MultiplePagers from './stories/MultiplePagers';
|
||||
|
||||
const stories = [
|
||||
{ name: 'Readme', component: Readme },
|
||||
{ name: 'Simple Table', component: CodeSandbox('X6npLXPRW') },
|
||||
{
|
||||
name: 'Cell Renderers & Custom Components',
|
||||
component: CodeSandbox('OyRL04Z4Y'),
|
||||
},
|
||||
{ name: 'Default Sorting', component: CodeSandbox('gLwmmjzA3') },
|
||||
{
|
||||
name: 'Custom Sorting',
|
||||
component: CodeSandbox('VGx67J35'),
|
||||
},
|
||||
{ name: 'Custom Column Widths', component: CodeSandbox('o2OORXNXN') },
|
||||
{ name: 'Custom Component Props', component: CodeSandbox('nZW3L0wp4') },
|
||||
{ name: 'Server-side Data', component: CodeSandbox('wjrn8wy3R') },
|
||||
{ name: 'Sub Components', component: CodeSandbox('n2gqAxl7') },
|
||||
{ name: 'Pivoting & Aggregation', component: CodeSandbox('oNY9z8xN') },
|
||||
{
|
||||
name: 'Pivoting & Aggregation w/ Sub Components',
|
||||
component: CodeSandbox('p0kEVBgQ'),
|
||||
},
|
||||
{
|
||||
name: '100k Rows w/ Pivoting & Sub Components',
|
||||
component: CodeSandbox('DRmKj0XyK'),
|
||||
},
|
||||
{ name: 'Pivoting Options', component: CodeSandbox('kZKmNBK6r') },
|
||||
{ name: 'Functional Rendering', component: CodeSandbox('VPZ0Bzv8X') },
|
||||
{
|
||||
name: 'Custom Expander Position',
|
||||
component: CodeSandbox('1jj2XrPEV'),
|
||||
},
|
||||
{ name: 'Custom "No Data" Text', component: CodeSandbox('RgRpRDv80') },
|
||||
{ name: 'Footers', component: CodeSandbox('KOqQXn3p8') },
|
||||
{ name: 'Custom Filtering', component: CodeSandbox('5Eyxxxyx') },
|
||||
{ name: 'Controlled Component', component: CodeSandbox('r7XEZRK2') },
|
||||
{ name: 'Editable Table', component: CodeSandbox('n5r19gzQP') },
|
||||
{
|
||||
name: 'Fixed Header w/ Vertical Scroll',
|
||||
component: CodeSandbox('7LY0gjA8O'),
|
||||
},
|
||||
{
|
||||
name: 'Multiple Pagers (Top and Bottom)',
|
||||
component: CodeSandbox('VEZ8OgvX'),
|
||||
},
|
||||
]
|
||||
|
||||
export default class App extends React.Component {
|
||||
render() {
|
||||
render () {
|
||||
return (
|
||||
<ReactStory
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
height: '100%',
|
||||
}}
|
||||
pathPrefix="story/"
|
||||
pathPrefix='story/'
|
||||
StoryWrapper={props => (
|
||||
<defaultProps.StoryWrapper
|
||||
css={{
|
||||
padding: 0
|
||||
padding: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href="//github.com/tannerlinsley/react-table"
|
||||
href='//github.com/react-tools/react-table'
|
||||
style={{
|
||||
display: 'block',
|
||||
textAlign: 'center',
|
||||
borderBottom: 'solid 3px #cccccc'
|
||||
borderBottom: 'solid 3px #cccccc',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src="//npmcdn.com/react-table/media/Banner.png"
|
||||
alt="React Table Logo"
|
||||
src='https://github.com/react-tools/media/raw/master/logo-react-table.png'
|
||||
alt='React Table Logo'
|
||||
style={{
|
||||
width: '100px'
|
||||
width: '150px',
|
||||
padding: '10px',
|
||||
}}
|
||||
/>
|
||||
</a>
|
||||
<div
|
||||
{...props}
|
||||
style={{
|
||||
padding: '10px'
|
||||
flex: '1 0 auto',
|
||||
position: 'relative',
|
||||
}}
|
||||
/>
|
||||
</defaultProps.StoryWrapper>
|
||||
)}
|
||||
stories={[
|
||||
{ name: 'Readme', component: Readme },
|
||||
{ name: 'Simple Table', component: Simple },
|
||||
{
|
||||
name: 'Cell Renderers & Custom Components',
|
||||
component: CellRenderers
|
||||
},
|
||||
{ name: 'Default Sorting', component: DefaultSorting },
|
||||
{ name: 'Custom Sorting', component: CustomSorting },
|
||||
{ name: 'Custom Column Widths', component: CustomWidths },
|
||||
{ name: 'Custom Component Props', component: CustomComponentProps },
|
||||
{ name: 'Server-side Data', component: ServerSide },
|
||||
{ name: 'Sub Components', component: SubComponents },
|
||||
{ name: 'Pivoting & Aggregation', component: Pivoting },
|
||||
{
|
||||
name: 'Pivoting & Aggregation w/ Sub Components',
|
||||
component: PivotingSubComponents
|
||||
},
|
||||
{
|
||||
name: '100k Rows w/ Pivoting & Sub Components',
|
||||
component: OneHundredKRows
|
||||
},
|
||||
{ name: 'Pivoting Options', component: PivotingOptions },
|
||||
{ name: 'Functional Rendering', component: FunctionalRendering },
|
||||
{
|
||||
name: 'Custom Expander Position',
|
||||
component: CustomExpanderPosition
|
||||
},
|
||||
{ name: 'Custom "No Data" Text', component: NoDataText },
|
||||
{ name: 'Footers', component: Footers },
|
||||
{ name: 'Custom Filtering', component: Filtering },
|
||||
{ name: 'Controlled Component', component: ControlledTable },
|
||||
{ name: 'Editable Table', component: EditableTable },
|
||||
{ name: 'Fixed Header w/ Vertical Scroll', component: FixedHeader },
|
||||
{ name: 'Multiple Pagers (Top and Bottom)', component: MultiplePagers}
|
||||
]}
|
||||
stories={stories}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react'
|
||||
|
||||
export default id => () => {
|
||||
return (
|
||||
<iframe
|
||||
src={`https://codesandbox.io/embed/${id}?autoresize=1&hidenavigation=1&view=${global.innerWidth <
|
||||
1000
|
||||
? 'preview'
|
||||
: 'split'}`}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: `100%`,
|
||||
height: `100%`,
|
||||
border: 0,
|
||||
overflow: `hidden`,
|
||||
}}
|
||||
sandbox='allow-modals allow-forms allow-popups allow-scripts allow-same-origin'
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
const statusChance = Math.random()
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
progress: Math.floor(Math.random() * 100),
|
||||
status: statusChance > 0.66 ? 'relationship'
|
||||
: statusChance > 0.33 ? 'complicated'
|
||||
: 'single'
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Profile Progress',
|
||||
accessor: 'progress',
|
||||
Cell: row => (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: '#dadada',
|
||||
borderRadius: '2px'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: `${row.value}%`,
|
||||
height: '100%',
|
||||
backgroundColor: row.value > 66 ? '#85cc00'
|
||||
: row.value > 33 ? '#ffbf00'
|
||||
: '#ff2e00',
|
||||
borderRadius: '2px',
|
||||
transition: 'all .2s ease-out'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}, {
|
||||
Header: 'Status',
|
||||
accessor: 'status',
|
||||
Cell: row => (
|
||||
<span>
|
||||
<span style={{
|
||||
color: row.value === 'relationship' ? '#ff2e00'
|
||||
: row.value === 'complicated' ? '#ffbf00'
|
||||
: '#57d500',
|
||||
transition: 'all .3s ease'
|
||||
}}>
|
||||
●
|
||||
</span> {
|
||||
row.value === 'relationship' ? 'In a relationship'
|
||||
: row.value === 'complicated' ? `It's complicated`
|
||||
: 'Single'
|
||||
}
|
||||
</span>
|
||||
)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./CellRenderers')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,89 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 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 Story extends React.PureComponent {
|
||||
constructor () {
|
||||
super()
|
||||
this.state = {
|
||||
sorted: [],
|
||||
page: 0,
|
||||
pageSize: 10,
|
||||
expanded: {},
|
||||
resized: [],
|
||||
filtered: []
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
pivotBy={['lastName']}
|
||||
filterable
|
||||
// Controlled Props
|
||||
sorted={this.state.sorted}
|
||||
page={this.state.page}
|
||||
pageSize={this.state.pageSize}
|
||||
expanded={this.state.expanded}
|
||||
resized={this.state.resized}
|
||||
filtered={this.state.filtered}
|
||||
// Callbacks
|
||||
onSortedChange={sorted => this.setState({sorted})}
|
||||
onPageChange={page => this.setState({page})}
|
||||
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
|
||||
onExpandedChange={expanded => this.setState({expanded})}
|
||||
onResizedChange={resized => this.setState({resized})}
|
||||
onFilteredChange={filtered => this.setState({filtered})}
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<pre><code><strong>this.state ===</strong> {JSON.stringify(this.state, null, 2)}</code></pre>
|
||||
<br />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./ControlledTable')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,76 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<strong>Hey!</strong> Open your console! :)
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
getTdProps={(state, rowInfo, column, instance) => {
|
||||
return {
|
||||
onMouseEnter: e => console.log('Cell - onMouseEnter', {
|
||||
state,
|
||||
rowInfo,
|
||||
column,
|
||||
instance,
|
||||
event: e
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./CustomComponentProps')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,81 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({words: 1, numbers: 0}),
|
||||
lastName: namor.generate({words: 1, numbers: 0}),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
Footer: () => <div style={{textAlign: 'center'}}>First Name</div>
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
accessor: 'lastName',
|
||||
Footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
Footer: () => <div style={{textAlign: 'center'}}>Age</div>
|
||||
}]
|
||||
}, {
|
||||
Header: 'Expand',
|
||||
columns: [{
|
||||
expander: true,
|
||||
Header: () => (<strong>More</strong>),
|
||||
width: 65,
|
||||
Expander: ({isExpanded, ...rest}) => (
|
||||
<div>
|
||||
{isExpanded ? <span>⊙</span> : <span>⊕</span>}
|
||||
</div>
|
||||
),
|
||||
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
|
||||
Footer: () => <span>♥</span>
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
SubComponent={() => <span>Hello</span>}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./CustomExpanderPosition')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,78 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name (Sorted by Length, A-Z)',
|
||||
accessor: 'firstName',
|
||||
sortMethod: (a, b) => {
|
||||
if (a.length === b.length) {
|
||||
return a > b ? 1 : -1
|
||||
}
|
||||
return a.length > b.length ? 1 : -1
|
||||
}
|
||||
}, {
|
||||
Header: 'Last Name (Sorted in reverse, A-Z)',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
sortMethod: (a, b) => {
|
||||
if (a === b) {
|
||||
return 0
|
||||
}
|
||||
const aReverse = a.split('').reverse().join('')
|
||||
const bReverse = b.split('').reverse().join('')
|
||||
return aReverse > bReverse ? 1 : -1
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./CustomSorting')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,67 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
maxWidth: 200
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
width: 300
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
minWidth: 400
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./CustomWidths')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,68 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
defaultSorted={[{
|
||||
id: 'age',
|
||||
desc: true
|
||||
}]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./DefaultSorting')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,70 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
constructor (props, context) {
|
||||
super(props, context)
|
||||
this.renderEditable = this.renderEditable.bind(this)
|
||||
|
||||
this.state = {
|
||||
data: [
|
||||
{ firstName: 'Lucy', lastName: 'Marks' },
|
||||
{ firstName: 'Bejamin', lastName: 'Pike' }
|
||||
]
|
||||
}
|
||||
|
||||
this.columns = [
|
||||
{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
Cell: this.renderEditable
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
accessor: 'lastName',
|
||||
Cell: this.renderEditable
|
||||
},
|
||||
{
|
||||
Header: 'Full Name',
|
||||
id: 'full',
|
||||
accessor: d => d.firstName + ' ' + d.lastName
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
renderEditable (cellInfo) {
|
||||
return (<div style={{ backgroundColor: '#fafafa' }} contentEditable suppressContentEditableWarning onBlur={(e) => {
|
||||
const data = [...this.state.data]
|
||||
data[cellInfo.index][cellInfo.column.id] = e.target.textContent
|
||||
this.setState({data: data})
|
||||
}}>{this.state.data[cellInfo.index][cellInfo.column.id]}</div>)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='table-wrap' style={{marginBottom: '20px'}}>
|
||||
<p>First two columns are editable just by clicking into them using the <code>contentEditable</code> attribute. Last column (Full Name) is computed from the first two.</p>
|
||||
<ReactTable
|
||||
data={this.state.data}
|
||||
columns={this.columns}
|
||||
defaultPageSize={2}
|
||||
showPageSizeOptions={false}
|
||||
showPagination={false}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./EditableTable')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,194 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import CodeHighlight from './components/codeHighlight'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({words: 1, numbers: 0}),
|
||||
lastName: namor.generate({words: 1, numbers: 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,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
resizable: 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',
|
||||
Cell: ({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
|
||||
},
|
||||
Filter: ({filter, onChange}) => (
|
||||
<select
|
||||
onChange={event => onChange(event.target.value)}
|
||||
style={{width: '100%'}}
|
||||
value={filter ? filter.value : 'all'}
|
||||
>
|
||||
<option value='all' />
|
||||
<option value='true'>Can Drink</option>
|
||||
<option value='false'>Can't Drink</option>
|
||||
</select>
|
||||
)
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<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'>
|
||||
<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>Filter</strong> column
|
||||
option. Using this option you can specify the JSX that is shown. The option is passed
|
||||
an <strong>onChange</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>
|
||||
</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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const source = require('!raw!./Filtering')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,81 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render() {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
children: _.map(_.range(10), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{
|
||||
Header: 'Name',
|
||||
columns: [
|
||||
{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
Header: 'Info',
|
||||
columns: [
|
||||
{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="table-wrap">
|
||||
<ReactTable
|
||||
className="-striped -highlight"
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={20}
|
||||
style={{
|
||||
height: '400px' // This will force the table body to overflow and scroll, since there is not enough room
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./Simple')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,92 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
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,
|
||||
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',
|
||||
Footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./Footers')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,137 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
import JSONTree from 'react-json-tree'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
const JSONtheme = {
|
||||
scheme: 'monokai',
|
||||
author: 'wimer hazenberg (http://www.monokai.nl)',
|
||||
base00: '#272822',
|
||||
base01: '#383830',
|
||||
base02: '#49483e',
|
||||
base03: '#75715e',
|
||||
base04: '#a59f85',
|
||||
base05: '#f8f8f2',
|
||||
base06: '#f5f4f1',
|
||||
base07: '#f9f8f5',
|
||||
base08: '#f92672',
|
||||
base09: '#fd971f',
|
||||
base0A: '#f4bf75',
|
||||
base0B: '#a6e22e',
|
||||
base0C: '#a1efe4',
|
||||
base0D: '#66d9ef',
|
||||
base0E: '#ae81ff',
|
||||
base0F: '#cc6633'
|
||||
}
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
Footer: 'Footer'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
Footer: 'Footer'
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
Footer: 'Footer'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<strong>Functional rendering</strong> simply means that you have all of the building blocks to render your own React Table however you'd like.
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<strong>Decorating the standard table output</strong>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
>
|
||||
{(state, makeTable, instance) => {
|
||||
return (
|
||||
<div style={{
|
||||
background: '#ffcf00',
|
||||
borderRadius: '5px',
|
||||
overflow: 'hidden',
|
||||
padding: '5px'
|
||||
}}>
|
||||
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
|
||||
{makeTable()}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<strong>Need more control? This is the entire table state and component instance at your disposal!</strong>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
>
|
||||
{(state, StandardTable, instance) => {
|
||||
return (
|
||||
<div>
|
||||
<JSONTree
|
||||
data={Object.assign({}, state, {children: 'function () {...}'})}
|
||||
theme={JSONtheme}
|
||||
invertTheme
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</ReactTable>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./FunctionalRendering')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,73 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
children: _.map(_.range(10), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
showPagination
|
||||
showPaginationTop
|
||||
showPaginationBottom
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./MultiplePagers')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,57 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={[]}
|
||||
noDataText='Oh Noes!'
|
||||
// noDataText={() => 'Oh Noes!'} // Supports functions
|
||||
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./NoDataText')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,97 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(100000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
Aggregated: row => {
|
||||
return <span>{row.value} (avg)</span>
|
||||
}
|
||||
}, {
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
className='-striped -highlight'
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>You can put any component you want here, even another React Table!</em>
|
||||
<br />
|
||||
<br />
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={3}
|
||||
showPagination={false}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>It even has access to the row data: </em>
|
||||
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./OneHundredKRows')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,74 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(1000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
Aggregated: row => {
|
||||
return <span>{row.value} (avg)</span>
|
||||
}
|
||||
}, {
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals)
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
className='-striped -highlight'
|
||||
defaultPageSize={10}
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./Pivoting')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,132 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(1000), d => {
|
||||
return {
|
||||
firstName: namor.generate({words: 1, numbers: 0}),
|
||||
lastName: namor.generate({words: 1, numbers: 0}),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
PivotValue: ({value}) => <span style={{color: 'darkred'}}>{value}</span>
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName,
|
||||
PivotValue: ({value}) => <span style={{color: 'darkblue'}}>{value}</span>,
|
||||
Footer: () => <div style={{textAlign: 'center'}}><strong>Pivot Column Footer</strong></div>
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => {
|
||||
return _.round(_.mean(vals))
|
||||
},
|
||||
Aggregated: row => <span>{row.value} (avg)</span>
|
||||
}, {
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals),
|
||||
filterable: false
|
||||
}]
|
||||
}, {
|
||||
pivot: true,
|
||||
Header: () => <strong>Overridden Pivot Column Header Group</strong>
|
||||
}, {
|
||||
expander: true
|
||||
}]
|
||||
|
||||
const subtableColumns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName'
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}, {
|
||||
Header: 'Visits',
|
||||
accessor: 'visits'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
defaultSorted={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]}
|
||||
collapseOnSortingChange={false}
|
||||
filterable
|
||||
ExpanderComponent={({isExpanded, ...rest}) => (
|
||||
isExpanded ? <span> ➘ </span> : <span> ➙ </span>
|
||||
)}
|
||||
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={subtableColumns}
|
||||
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>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./PivotingOptions')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,100 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(1000), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
visits: Math.floor(Math.random() * 100)
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age',
|
||||
aggregate: vals => _.round(_.mean(vals)),
|
||||
Aggregated: row => {
|
||||
return <span>{row.value} (avg)</span>
|
||||
},
|
||||
filterMethod: (filter, row) => (filter.value === `${row[filter.id]} (avg)`)
|
||||
}, {
|
||||
Header: 'Visits',
|
||||
accessor: 'visits',
|
||||
aggregate: vals => _.sum(vals),
|
||||
filterable: false
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
className='-striped -highlight'
|
||||
pivotBy={['firstName', 'lastName']}
|
||||
filterable
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>You can put any component you want here, even another React Table!</em>
|
||||
<br />
|
||||
<br />
|
||||
<ReactTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={3}
|
||||
showPagination={false}
|
||||
SubComponent={(row) => {
|
||||
return (
|
||||
<div style={{padding: '20px'}}>
|
||||
<em>It even has access to the row data: </em>
|
||||
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./PivotingSubComponents')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -4,17 +4,20 @@ import marked from 'marked'
|
||||
//
|
||||
import Readme from '!raw!../../../README.md'
|
||||
import 'github-markdown-css/github-markdown.css'
|
||||
import './utils/prism.js'
|
||||
|
||||
export default class Story extends React.Component {
|
||||
render() {
|
||||
render () {
|
||||
return (
|
||||
<span
|
||||
className="markdown-body"
|
||||
dangerouslySetInnerHTML={{ __html: marked(Readme) }}
|
||||
/>
|
||||
<div style={{ padding: '10px' }}>
|
||||
<span
|
||||
className='markdown-body'
|
||||
dangerouslySetInnerHTML={{ __html: marked(Readme) }}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
componentDidMount() {
|
||||
global.Prism.highlightAll()
|
||||
componentDidMount () {
|
||||
global.Prism && global.Prism.highlightAll()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
const rawData = _.map(_.range(3424), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
|
||||
// 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, sorted, filtered) => {
|
||||
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
|
||||
let filteredData = rawData
|
||||
if (filtered.length) {
|
||||
filteredData = filtered.reduce(
|
||||
(filteredSoFar, nextFilter) => {
|
||||
return filteredSoFar.filter(
|
||||
(row) => {
|
||||
return (row[nextFilter.id] + '').includes(nextFilter.value)
|
||||
})
|
||||
}
|
||||
, filteredData)
|
||||
}
|
||||
const sortedData = _.orderBy(filteredData, sorted.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]
|
||||
}
|
||||
}), sorted.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(filteredData.length / pageSize)
|
||||
}
|
||||
|
||||
// Here we'll simulate a server response with 500ms of delay.
|
||||
setTimeout(() => resolve(res), 500)
|
||||
})
|
||||
}
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
constructor () {
|
||||
super()
|
||||
this.state = {
|
||||
data: [],
|
||||
pages: null,
|
||||
loading: true
|
||||
}
|
||||
this.fetchData = this.fetchData.bind(this)
|
||||
}
|
||||
fetchData (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.sorted, state.filtered)
|
||||
.then((res) => {
|
||||
// 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,
|
||||
pages: res.pages,
|
||||
loading: false
|
||||
})
|
||||
})
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
columns={[{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}, {
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]}
|
||||
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
|
||||
defaultPageSize={10}
|
||||
filterable
|
||||
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
|
||||
onFetchData={this.fetchData} // Request new data when things change
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./ServerSide')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,77 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render() {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
children: _.map(_.range(10), d => {
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{
|
||||
Header: 'Name',
|
||||
columns: [
|
||||
{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName'
|
||||
},
|
||||
{
|
||||
Header: 'Last Name',
|
||||
id: 'lastName',
|
||||
accessor: d => d.lastName
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
Header: 'Info',
|
||||
columns: [
|
||||
{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="table-wrap">
|
||||
<ReactTable
|
||||
className="-striped -highlight"
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./Simple')
|
||||
|
||||
export default () =>
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
@@ -1,146 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
const data = _.map(_.range(5553), d => {
|
||||
return {
|
||||
firstName: namor.generate({words: 1, numbers: 0}),
|
||||
lastName: namor.generate({words: 1, numbers: 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,
|
||||
filterable: false,
|
||||
sortable: true,
|
||||
resizable: true
|
||||
},
|
||||
data: data
|
||||
}
|
||||
|
||||
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: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<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'>
|
||||
<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>
|
||||
</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
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./SubComponents')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,78 +0,0 @@
|
||||
/* eslint-disable import/no-webpack-loader-syntax */
|
||||
import React from 'react'
|
||||
import _ from 'lodash'
|
||||
import namor from 'namor'
|
||||
|
||||
import ReactTable from '../../../lib/index'
|
||||
|
||||
class Story extends React.PureComponent {
|
||||
render () {
|
||||
const data = _.map(_.range(5553), d => {
|
||||
const children = _.map(_.range(10), d => {
|
||||
const grandChildren = _.map(_.range(10), d => {
|
||||
return {
|
||||
age: Math.floor(Math.random() * 30)
|
||||
}
|
||||
})
|
||||
return {
|
||||
firstName: namor.generate({ words: 1, numbers: 0 }),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
children: grandChildren
|
||||
}
|
||||
})
|
||||
return {
|
||||
lastName: namor.generate({ words: 1, numbers: 0 }),
|
||||
firstName: children.map(d => d.firstName),
|
||||
age: Math.floor(Math.random() * 30),
|
||||
children
|
||||
}
|
||||
})
|
||||
|
||||
const columns = [{
|
||||
Header: 'Name',
|
||||
columns: [{
|
||||
Header: 'First Name',
|
||||
accessor: 'firstName',
|
||||
expander: true
|
||||
}, {
|
||||
Header: 'Last Name',
|
||||
accessor: 'lastName'
|
||||
}]
|
||||
}, {
|
||||
Header: 'Info',
|
||||
columns: [{
|
||||
Header: 'Age',
|
||||
accessor: 'age'
|
||||
}]
|
||||
}]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='table-wrap'>
|
||||
<ReactTable
|
||||
className='-striped -highlight'
|
||||
data={data}
|
||||
columns={columns}
|
||||
defaultPageSize={10}
|
||||
subRowsKey='children'
|
||||
/>
|
||||
</div>
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<br />
|
||||
<em>Tip: Hold shift when sorting to multi-sort!</em>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Source Code
|
||||
const CodeHighlight = require('./components/codeHighlight').default
|
||||
const source = require('!raw!./SubRows')
|
||||
|
||||
export default () => (
|
||||
<div>
|
||||
<Story />
|
||||
<CodeHighlight>{() => source}</CodeHighlight>
|
||||
</div>
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from 'react'
|
||||
import '../utils/prism'
|
||||
|
||||
export default class CodeHighlight extends React.Component {
|
||||
render () {
|
||||
const { language, children } = this.props
|
||||
return (
|
||||
<pre>
|
||||
<code className={'language-' + (language || 'jsx')}>
|
||||
{children()}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
componentDidMount () {
|
||||
window.Prism.highlightAll()
|
||||
}
|
||||
componentDidUpdate () {
|
||||
window.Prism.highlightAll()
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
+1900
-413
File diff suppressed because it is too large
Load Diff
+17
-20
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "react-table",
|
||||
"version": "6.3.0",
|
||||
"version": "6.7.4",
|
||||
"description": "A fast, lightweight, opinionated table and datagrid built on React",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/tannerlinsley/react-table#readme",
|
||||
"homepage": "https://github.com/react-tools/react-table#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tannerlinsley/react-table.git"
|
||||
"url": "git+https://github.com/react-tools/react-table.git"
|
||||
},
|
||||
"keywords": [
|
||||
"react",
|
||||
@@ -29,20 +29,20 @@
|
||||
"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",
|
||||
"test": "eslint src",
|
||||
"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",
|
||||
"docs": "yarn watch & cd docs && yarn && yarn start",
|
||||
"docs:build": "yarn build && cd docs && yarn && yarn run build"
|
||||
"docs:build": "yarn build && cd docs && yarn && yarn build"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5",
|
||||
"react-json-tree": "^0.10.9"
|
||||
"classnames": "^2.2.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.x.x"
|
||||
"react": "^15.x.x || ^16.x.x",
|
||||
"eslint-config-react-tools": "^1.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.7.0",
|
||||
@@ -51,28 +51,25 @@
|
||||
"babel-preset-es2015": "6.14.0",
|
||||
"babel-preset-react": "6.11.1",
|
||||
"babel-preset-stage-2": "6.13.0",
|
||||
"eslint": "^4.1.1",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-node": "^5.2.0",
|
||||
"eslint-plugin-react": "^7.4.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"match-sorter": "^1.8.0",
|
||||
"npm-run-all": "^3.1.1",
|
||||
"onchange": "^3.0.2",
|
||||
"postcss-cli": "^2.6.0",
|
||||
"prop-types": "^15.6.0",
|
||||
"react": "^15.4.2",
|
||||
"react-dom": "^15.4.2",
|
||||
"react-json-tree": "^0.10.9",
|
||||
"rimraf": "^2.6.1",
|
||||
"standard": "^10.0.2",
|
||||
"stylus": "^0.54.5",
|
||||
"webpack": "^2.5.1"
|
||||
},
|
||||
"standard": {
|
||||
"parser": "babel-eslint",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"lib",
|
||||
"example",
|
||||
"react-table.js",
|
||||
"stories",
|
||||
"docs"
|
||||
]
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"es2015",
|
||||
|
||||
+35
-22
@@ -35,7 +35,7 @@ export default {
|
||||
? String(row[id]).startsWith(filter.value)
|
||||
: true
|
||||
},
|
||||
defaultSortMethod: (a, b) => {
|
||||
defaultSortMethod: (a, b, desc) => {
|
||||
// force null and undefined to the bottom
|
||||
a = a === null || a === undefined ? '' : a
|
||||
b = b === null || b === undefined ? '' : b
|
||||
@@ -145,6 +145,7 @@ export default {
|
||||
footerStyle: {},
|
||||
getFooterProps: emptyObj,
|
||||
filterMethod: undefined,
|
||||
filterAll: false,
|
||||
sortMethod: undefined,
|
||||
},
|
||||
|
||||
@@ -170,11 +171,11 @@ export default {
|
||||
rowsText: 'rows',
|
||||
|
||||
// Components
|
||||
TableComponent: _.makeTemplateComponent('rt-table'),
|
||||
TheadComponent: _.makeTemplateComponent('rt-thead'),
|
||||
TbodyComponent: _.makeTemplateComponent('rt-tbody'),
|
||||
TrGroupComponent: _.makeTemplateComponent('rt-tr-group'),
|
||||
TrComponent: _.makeTemplateComponent('rt-tr'),
|
||||
TableComponent: _.makeTemplateComponent('rt-table', 'Table'),
|
||||
TheadComponent: _.makeTemplateComponent('rt-thead', 'Thead'),
|
||||
TbodyComponent: _.makeTemplateComponent('rt-tbody', 'Tbody'),
|
||||
TrGroupComponent: _.makeTemplateComponent('rt-tr-group', 'TrGroup'),
|
||||
TrComponent: _.makeTemplateComponent('rt-tr', 'Tr'),
|
||||
ThComponent: ({ toggleSort, className, children, ...rest }) => {
|
||||
return (
|
||||
<div
|
||||
@@ -188,9 +189,9 @@ export default {
|
||||
</div>
|
||||
)
|
||||
},
|
||||
TdComponent: _.makeTemplateComponent('rt-td'),
|
||||
TfootComponent: _.makeTemplateComponent('rt-tfoot'),
|
||||
FilterComponent: ({ filter, onChange }) =>
|
||||
TdComponent: _.makeTemplateComponent('rt-td', 'Td'),
|
||||
TfootComponent: _.makeTemplateComponent('rt-tfoot', 'Tfoot'),
|
||||
FilterComponent: ({ filter, onChange }) => (
|
||||
<input
|
||||
type='text'
|
||||
style={{
|
||||
@@ -198,29 +199,39 @@ export default {
|
||||
}}
|
||||
value={filter ? filter.value : ''}
|
||||
onChange={event => onChange(event.target.value)}
|
||||
/>,
|
||||
ExpanderComponent: ({ isExpanded }) =>
|
||||
/>
|
||||
),
|
||||
ExpanderComponent: ({ isExpanded }) => (
|
||||
<div className={classnames('rt-expander', isExpanded && '-open')}>
|
||||
•
|
||||
</div>,
|
||||
PivotValueComponent: ({ subRows, value }) =>
|
||||
<span>{value} {subRows && `(${subRows.length})`}</span>,
|
||||
</div>
|
||||
),
|
||||
PivotValueComponent: ({ subRows, value }) => (
|
||||
<span>
|
||||
{value} {subRows && `(${subRows.length})`}
|
||||
</span>
|
||||
),
|
||||
AggregatedComponent: ({ subRows, column }) => {
|
||||
const previewValues = subRows
|
||||
.filter(d => typeof d[column.id] !== 'undefined')
|
||||
.map((row, i) =>
|
||||
.map((row, i) => (
|
||||
<span key={i}>
|
||||
{row[column.id]}{i < subRows.length - 1 ? ', ' : ''}
|
||||
{row[column.id]}
|
||||
{i < subRows.length - 1 ? ', ' : ''}
|
||||
</span>
|
||||
)
|
||||
return <span>{previewValues}</span>
|
||||
))
|
||||
return (
|
||||
<span>
|
||||
{previewValues}
|
||||
</span>
|
||||
)
|
||||
},
|
||||
PivotComponent: undefined, // this is a computed default generated using
|
||||
// the ExpanderComponent and PivotValueComponent at run-time in methods.js
|
||||
PaginationComponent: Pagination,
|
||||
PreviousComponent: undefined,
|
||||
NextComponent: undefined,
|
||||
LoadingComponent: ({ className, loading, loadingText, ...rest }) =>
|
||||
LoadingComponent: ({ className, loading, loadingText, ...rest }) => (
|
||||
<div
|
||||
className={classnames('-loading', { '-active': loading }, className)}
|
||||
{...rest}
|
||||
@@ -228,7 +239,9 @@ export default {
|
||||
<div className='-loading-inner'>
|
||||
{loadingText}
|
||||
</div>
|
||||
</div>,
|
||||
NoDataComponent: _.makeTemplateComponent('rt-noData'),
|
||||
ResizerComponent: _.makeTemplateComponent('rt-resizer'),
|
||||
</div>
|
||||
),
|
||||
NoDataComponent: _.makeTemplateComponent('rt-noData', 'NoData'),
|
||||
ResizerComponent: _.makeTemplateComponent('rt-resizer', 'Resizer'),
|
||||
PadRowComponent: () => <span> </span>,
|
||||
}
|
||||
|
||||
+114
-96
@@ -5,13 +5,15 @@ import _ from './utils'
|
||||
import Lifecycle from './lifecycle'
|
||||
import Methods from './methods'
|
||||
import defaultProps from './defaultProps'
|
||||
import propTypes from './propTypes'
|
||||
|
||||
export const ReactTableDefaults = defaultProps
|
||||
|
||||
export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
static propTypes = propTypes
|
||||
static defaultProps = defaultProps
|
||||
|
||||
constructor(props) {
|
||||
constructor (props) {
|
||||
super()
|
||||
|
||||
this.getResolvedState = this.getResolvedState.bind(this)
|
||||
@@ -39,11 +41,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
filtered: props.defaultFiltered,
|
||||
resized: props.defaultResized,
|
||||
currentlyResizing: false,
|
||||
skipNextSort: false
|
||||
skipNextSort: false,
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
render () {
|
||||
const resolvedState = this.getResolvedState()
|
||||
const {
|
||||
children,
|
||||
@@ -118,6 +120,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
PivotComponent,
|
||||
AggregatedComponent,
|
||||
FilterComponent,
|
||||
PadRowComponent,
|
||||
// Data model
|
||||
resolvedData,
|
||||
allVisibleColumns,
|
||||
@@ -125,7 +128,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
hasHeaderGroups,
|
||||
// Sorted Data
|
||||
sortedData,
|
||||
currentlyResizing
|
||||
currentlyResizing,
|
||||
} = resolvedState
|
||||
|
||||
// Pagination
|
||||
@@ -144,7 +147,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
index++
|
||||
const rowWithViewIndex = {
|
||||
...row,
|
||||
_viewIndex: index
|
||||
_viewIndex: index,
|
||||
}
|
||||
const newPath = path.concat([i])
|
||||
if (rowWithViewIndex[subRowsKey] && _.get(expanded, newPath)) {
|
||||
@@ -156,10 +159,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
}
|
||||
return rowWithViewIndex
|
||||
}),
|
||||
index
|
||||
index,
|
||||
]
|
||||
}
|
||||
|
||||
;[pageRows] = recurseRowsViewIndex(pageRows)
|
||||
|
||||
const canPrevious = page > 0
|
||||
@@ -184,7 +186,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
hasColumnFooter,
|
||||
canPrevious,
|
||||
canNext,
|
||||
rowMinWidth
|
||||
rowMinWidth,
|
||||
}
|
||||
|
||||
// Visual Components
|
||||
@@ -201,7 +203,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames('-headerGroups', theadGroupProps.className)}
|
||||
style={{
|
||||
...theadGroupProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
minWidth: `${rowMinWidth}px`,
|
||||
}}
|
||||
{...theadGroupProps.rest}
|
||||
>
|
||||
@@ -245,24 +247,24 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const classes = [
|
||||
column.headerClassName,
|
||||
theadGroupThProps.className,
|
||||
columnHeaderProps.className
|
||||
columnHeaderProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...column.headerStyle,
|
||||
...theadGroupThProps.style,
|
||||
...columnHeaderProps.style
|
||||
...columnHeaderProps.style,
|
||||
}
|
||||
|
||||
const rest = {
|
||||
...theadGroupThProps.rest,
|
||||
...columnHeaderProps.rest
|
||||
...columnHeaderProps.rest,
|
||||
}
|
||||
|
||||
const flexStyles = {
|
||||
flex: `${flex} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -271,13 +273,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames(classes)}
|
||||
style={{
|
||||
...styles,
|
||||
...flexStyles
|
||||
...flexStyles,
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{_.normalizeComponent(column.Header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
column: column,
|
||||
})}
|
||||
</ThComponent>
|
||||
)
|
||||
@@ -295,7 +297,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames('-header', theadProps.className)}
|
||||
style={{
|
||||
...theadProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
minWidth: `${rowMinWidth}px`,
|
||||
}}
|
||||
{...theadProps.rest}
|
||||
>
|
||||
@@ -313,9 +315,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const makeHeader = (column, i) => {
|
||||
const resizedCol = resized.find(x => x.id === column.id) || {}
|
||||
const sort = sorted.find(d => d.id === column.id)
|
||||
const show = typeof column.show === 'function'
|
||||
? column.show()
|
||||
: column.show
|
||||
const show =
|
||||
typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(
|
||||
resizedCol.value,
|
||||
column.width,
|
||||
@@ -336,27 +337,27 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const classes = [
|
||||
column.headerClassName,
|
||||
theadThProps.className,
|
||||
columnHeaderProps.className
|
||||
columnHeaderProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...column.headerStyle,
|
||||
...theadThProps.style,
|
||||
...columnHeaderProps.style
|
||||
...columnHeaderProps.style,
|
||||
}
|
||||
|
||||
const rest = {
|
||||
...theadThProps.rest,
|
||||
...columnHeaderProps.rest
|
||||
...columnHeaderProps.rest,
|
||||
}
|
||||
|
||||
const isResizable = _.getFirstDefined(column.resizable, resizable, false)
|
||||
const resizer = isResizable
|
||||
? <ResizerComponent
|
||||
onMouseDown={e => this.resizeColumnStart(column, e, false)}
|
||||
onTouchStart={e => this.resizeColumnStart(column, e, true)}
|
||||
{...resizerProps}
|
||||
/>
|
||||
? (<ResizerComponent
|
||||
onMouseDown={e => this.resizeColumnStart(e, column, false)}
|
||||
onTouchStart={e => this.resizeColumnStart(e, column, true)}
|
||||
{...resizerProps}
|
||||
/>)
|
||||
: null
|
||||
|
||||
const isSortable = _.getFirstDefined(column.sortable, sortable, false)
|
||||
@@ -366,7 +367,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
key={i + '-' + column.id}
|
||||
className={classnames(
|
||||
classes,
|
||||
'rt-resizable-header',
|
||||
isResizable && 'rt-resizable-header',
|
||||
sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '',
|
||||
isSortable && '-cursor-pointer',
|
||||
!show && '-hidden',
|
||||
@@ -377,18 +378,18 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}}
|
||||
toggleSort={e => {
|
||||
isSortable && this.sortColumn(column, e.shiftKey)
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
<div className="rt-resizable-header-content">
|
||||
<div className={classnames(isResizable && 'rt-resizable-header-content')}>
|
||||
{_.normalizeComponent(column.Header, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
column: column,
|
||||
})}
|
||||
</div>
|
||||
{resizer}
|
||||
@@ -408,7 +409,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames('-filters', theadFilterProps.className)}
|
||||
style={{
|
||||
...theadFilterProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
minWidth: `${rowMinWidth}px`,
|
||||
}}
|
||||
{...theadFilterProps.rest}
|
||||
>
|
||||
@@ -445,18 +446,18 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const classes = [
|
||||
column.headerClassName,
|
||||
theadFilterThProps.className,
|
||||
columnHeaderProps.className
|
||||
columnHeaderProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...column.headerStyle,
|
||||
...theadFilterThProps.style,
|
||||
...columnHeaderProps.style
|
||||
...columnHeaderProps.style,
|
||||
}
|
||||
|
||||
const rest = {
|
||||
...theadFilterThProps.rest,
|
||||
...columnHeaderProps.rest
|
||||
...columnHeaderProps.rest,
|
||||
}
|
||||
|
||||
const filter = filtered.find(filter => filter.id === column.id)
|
||||
@@ -476,21 +477,21 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{isFilterable
|
||||
? _.normalizeComponent(
|
||||
ResolvedFilterComponent,
|
||||
{
|
||||
column,
|
||||
filter,
|
||||
onChange: value => this.filterColumn(column, value)
|
||||
},
|
||||
defaultProps.column.Filter
|
||||
)
|
||||
ResolvedFilterComponent,
|
||||
{
|
||||
column,
|
||||
filter,
|
||||
onChange: value => this.filterColumn(column, value),
|
||||
},
|
||||
defaultProps.column.Filter
|
||||
)
|
||||
: null}
|
||||
</ThComponent>
|
||||
)
|
||||
@@ -502,11 +503,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
row: row,
|
||||
index: row[indexKey],
|
||||
viewIndex: ++rowIndex,
|
||||
pageSize: pageSize,
|
||||
page: page,
|
||||
level: path.length,
|
||||
nestingPath: path.concat([i]),
|
||||
aggregated: row[aggregatedKey],
|
||||
groupedByPivot: row[groupedByPivotKey],
|
||||
subRows: row[subRowsKey]
|
||||
subRows: row[subRowsKey],
|
||||
}
|
||||
const isExpanded = _.get(expanded, rowInfo.nestingPath)
|
||||
const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this)
|
||||
@@ -525,9 +528,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
>
|
||||
{allVisibleColumns.map((column, i2) => {
|
||||
const resizedCol = resized.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function'
|
||||
? column.show()
|
||||
: column.show
|
||||
const show =
|
||||
typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(
|
||||
resizedCol.value,
|
||||
column.width,
|
||||
@@ -548,13 +550,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const classes = [
|
||||
tdProps.className,
|
||||
column.className,
|
||||
columnProps.className
|
||||
columnProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...tdProps.style,
|
||||
...column.style,
|
||||
...columnProps.style
|
||||
...columnProps.style,
|
||||
}
|
||||
|
||||
const cellInfo = {
|
||||
@@ -571,12 +573,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
tdProps,
|
||||
columnProps,
|
||||
classes,
|
||||
styles
|
||||
styles,
|
||||
}
|
||||
|
||||
const value = cellInfo.value
|
||||
|
||||
let interactionProps
|
||||
let useOnExpanderClick
|
||||
let isBranch
|
||||
let isPreview
|
||||
|
||||
@@ -590,7 +592,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
|
||||
return this.setStateWithData(
|
||||
{
|
||||
expanded: newExpanded
|
||||
expanded: newExpanded,
|
||||
},
|
||||
() => {
|
||||
onExpandedChange &&
|
||||
@@ -616,11 +618,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
column.PivotValue || PivotValueComponent
|
||||
const DefaultResolvedPivotComponent =
|
||||
PivotComponent ||
|
||||
(props =>
|
||||
(props => (
|
||||
<div>
|
||||
<ResolvedExpanderComponent {...props} />
|
||||
<ResolvedPivotValueComponent {...props} />
|
||||
</div>)
|
||||
</div>
|
||||
))
|
||||
const ResolvedPivotComponent =
|
||||
column.Pivot || DefaultResolvedPivotComponent
|
||||
|
||||
@@ -628,17 +631,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
if (cellInfo.pivoted || cellInfo.expander) {
|
||||
// Make it expandable by defualt
|
||||
cellInfo.expandable = true
|
||||
interactionProps = {
|
||||
onClick: onExpanderClick
|
||||
}
|
||||
useOnExpanderClick = true
|
||||
// If pivoted, has no subRows, and does not have a subComponent, do not make expandable
|
||||
if (cellInfo.pivoted) {
|
||||
if (!cellInfo.subRows) {
|
||||
if (!SubComponent) {
|
||||
cellInfo.expandable = false
|
||||
interactionProps = {}
|
||||
}
|
||||
}
|
||||
if (cellInfo.pivoted && !cellInfo.subRows && !SubComponent) {
|
||||
cellInfo.expandable = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,7 +653,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
ResolvedPivotComponent,
|
||||
{
|
||||
...cellInfo,
|
||||
value: row[pivotValKey]
|
||||
value: row[pivotValKey],
|
||||
},
|
||||
row[pivotValKey]
|
||||
)
|
||||
@@ -695,6 +691,27 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
}
|
||||
}
|
||||
|
||||
const resolvedOnExpanderClick = useOnExpanderClick
|
||||
? onExpanderClick
|
||||
: () => {}
|
||||
|
||||
// If there are multiple onClick events, make sure they don't override eachother. This should maybe be expanded to handle all function attributes
|
||||
const interactionProps = {
|
||||
onClick: resolvedOnExpanderClick,
|
||||
}
|
||||
|
||||
if (tdProps.rest.onClick) {
|
||||
interactionProps.onClick = e => {
|
||||
tdProps.rest.onClick(e, () => resolvedOnExpanderClick(e))
|
||||
}
|
||||
}
|
||||
|
||||
if (columnProps.rest.onClick) {
|
||||
interactionProps.onClick = e => {
|
||||
columnProps.rest.onClick(e, () => resolvedOnExpanderClick(e))
|
||||
}
|
||||
}
|
||||
|
||||
// Return the cell
|
||||
return (
|
||||
<TdComponent
|
||||
@@ -708,10 +725,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}}
|
||||
{...tdProps.rest}
|
||||
{...columnProps.rest}
|
||||
{...interactionProps}
|
||||
>
|
||||
{resolvedCell}
|
||||
@@ -760,9 +778,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
|
||||
const makePadColumn = (column, i) => {
|
||||
const resizedCol = resized.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function'
|
||||
? column.show()
|
||||
: column.show
|
||||
const show =
|
||||
typeof column.show === 'function' ? column.show() : column.show
|
||||
let width = _.getFirstDefined(
|
||||
resizedCol.value,
|
||||
column.width,
|
||||
@@ -784,13 +801,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
const classes = [
|
||||
tdProps.className,
|
||||
column.className,
|
||||
columnProps.className
|
||||
columnProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...tdProps.style,
|
||||
...column.style,
|
||||
...columnProps.style
|
||||
...columnProps.style,
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -800,11 +817,13 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${flex} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}}
|
||||
{...tdProps.rest}
|
||||
/>
|
||||
>
|
||||
{_.normalizeComponent(PadRowComponent)}
|
||||
</TdComponent>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -818,7 +837,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={tFootProps.className}
|
||||
style={{
|
||||
...tFootProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
minWidth: `${rowMinWidth}px`,
|
||||
}}
|
||||
{...tFootProps.rest}
|
||||
>
|
||||
@@ -835,9 +854,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
|
||||
const makeColumnFooter = (column, i) => {
|
||||
const resizedCol = resized.find(x => x.id === column.id) || {}
|
||||
const show = typeof column.show === 'function'
|
||||
? column.show()
|
||||
: column.show
|
||||
const show =
|
||||
typeof column.show === 'function' ? column.show() : column.show
|
||||
const width = _.getFirstDefined(
|
||||
resizedCol.value,
|
||||
column.width,
|
||||
@@ -862,14 +880,14 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
tFootTdProps.className,
|
||||
column.className,
|
||||
columnProps.className,
|
||||
columnFooterProps.className
|
||||
columnFooterProps.className,
|
||||
]
|
||||
|
||||
const styles = {
|
||||
...tFootTdProps.style,
|
||||
...column.style,
|
||||
...columnProps.style,
|
||||
...columnFooterProps.style
|
||||
...columnFooterProps.style,
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -879,8 +897,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
style={{
|
||||
...styles,
|
||||
flex: `${width} 0 auto`,
|
||||
width: `${width}px`,
|
||||
maxWidth: `${maxWidth}px`
|
||||
width: _.asPx(width),
|
||||
maxWidth: _.asPx(maxWidth),
|
||||
}}
|
||||
{...columnProps.rest}
|
||||
{...tFootTdProps.rest}
|
||||
@@ -888,7 +906,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
>
|
||||
{_.normalizeComponent(column.Footer, {
|
||||
data: sortedData,
|
||||
column: column
|
||||
column: column,
|
||||
})}
|
||||
</TdComponent>
|
||||
)
|
||||
@@ -933,14 +951,14 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames('ReactTable', className, rootProps.className)}
|
||||
style={{
|
||||
...style,
|
||||
...rootProps.style
|
||||
...rootProps.style,
|
||||
}}
|
||||
{...rootProps.rest}
|
||||
>
|
||||
{showPagination && showPaginationTop
|
||||
? <div className="pagination-top">
|
||||
{pagination}
|
||||
</div>
|
||||
? <div className='pagination-top'>
|
||||
{pagination}
|
||||
</div>
|
||||
: null}
|
||||
<TableComponent
|
||||
className={classnames(
|
||||
@@ -957,7 +975,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
className={classnames(tBodyProps.className)}
|
||||
style={{
|
||||
...tBodyProps.style,
|
||||
minWidth: `${rowMinWidth}px`
|
||||
minWidth: `${rowMinWidth}px`,
|
||||
}}
|
||||
{...tBodyProps.rest}
|
||||
>
|
||||
@@ -967,9 +985,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
|
||||
{hasColumnFooter ? makeColumnFooters() : null}
|
||||
</TableComponent>
|
||||
{showPagination && showPaginationBottom
|
||||
? <div className="pagination-bottom">
|
||||
{pagination}
|
||||
</div>
|
||||
? <div className='pagination-bottom'>
|
||||
{pagination}
|
||||
</div>
|
||||
: null}
|
||||
{!pageRows.length &&
|
||||
<NoDataComponent {...noDataProps}>
|
||||
|
||||
+21
-35
@@ -2,6 +2,15 @@ $easeOutQuad = cubic-bezier(0.250, 0.460, 0.450, 0.940)
|
||||
$easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
$expandSize = 7px
|
||||
|
||||
input-select-style()
|
||||
border: 1px solid rgba(0,0,0,0.1)
|
||||
background: white
|
||||
padding: 5px 7px
|
||||
font-size: inherit
|
||||
border-radius: 3px
|
||||
font-weight: normal
|
||||
outline:none
|
||||
|
||||
.ReactTable
|
||||
position:relative
|
||||
display: flex
|
||||
@@ -10,7 +19,7 @@ $expandSize = 7px
|
||||
*
|
||||
box-sizing: border-box
|
||||
.rt-table
|
||||
flex: 1
|
||||
flex: auto 1
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
@@ -21,7 +30,6 @@ $expandSize = 7px
|
||||
.rt-thead
|
||||
flex: 1 0 auto
|
||||
display: flex
|
||||
// overflow-y: scroll
|
||||
flex-direction: column
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
@@ -35,6 +43,10 @@ $expandSize = 7px
|
||||
&.-filters
|
||||
border-bottom: 1px solid alpha(black, 0.05)
|
||||
|
||||
input
|
||||
select
|
||||
input-select-style();
|
||||
|
||||
.rt-th
|
||||
border-right: 1px solid alpha(black, 0.02)
|
||||
|
||||
@@ -169,6 +181,7 @@ $expandSize = 7px
|
||||
z-index: 10
|
||||
|
||||
.rt-tfoot
|
||||
flex: 1 0 auto
|
||||
display: flex
|
||||
flex-direction: column
|
||||
box-shadow: 0 0px 15px 0px alpha(black, .15)
|
||||
@@ -196,6 +209,10 @@ $expandSize = 7px
|
||||
box-shadow: 0 0px 15px 0px alpha(black, .1)
|
||||
border-top: 2px solid alpha(black, .1)
|
||||
|
||||
input
|
||||
select
|
||||
input-select-style()
|
||||
|
||||
.-btn
|
||||
appearance:none
|
||||
display:block
|
||||
@@ -270,7 +287,7 @@ $expandSize = 7px
|
||||
bottom:0
|
||||
background: alpha(white, .8)
|
||||
transition: all .3s ease
|
||||
z-index: 2
|
||||
z-index: -1
|
||||
opacity: 0
|
||||
pointer-events: none
|
||||
|
||||
@@ -288,42 +305,11 @@ $expandSize = 7px
|
||||
|
||||
&.-active
|
||||
opacity: 1
|
||||
z-index: 2
|
||||
pointer-events: all
|
||||
> div
|
||||
transform: translateY(50%)
|
||||
|
||||
input
|
||||
select
|
||||
border: 1px solid rgba(0,0,0,0.1)
|
||||
background: white
|
||||
padding: 5px 7px
|
||||
font-size: inherit
|
||||
border-radius: 3px
|
||||
font-weight: normal
|
||||
outline:none
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"])
|
||||
select
|
||||
appearance: none
|
||||
&::-ms-expand
|
||||
display: none
|
||||
|
||||
.select-wrap
|
||||
position:relative
|
||||
display:inline-block
|
||||
select
|
||||
padding: 5px 15px 5px 7px
|
||||
min-width:100px
|
||||
&:after
|
||||
content: ''
|
||||
position: absolute
|
||||
right: 8px
|
||||
top: 50%
|
||||
transform: translate(0, -50%)
|
||||
border-color: #999 transparent transparent
|
||||
border-style: solid
|
||||
border-width: 5px 5px 2.5px
|
||||
|
||||
.rt-resizing
|
||||
.rt-th
|
||||
.rt-td
|
||||
|
||||
+20
-4
@@ -88,7 +88,8 @@ export default Base =>
|
||||
this.props.collapseOnSortingChange) ||
|
||||
oldState.filtered !== newResolvedState.filtered ||
|
||||
oldState.showFilters !== newResolvedState.showFilters ||
|
||||
(!newResolvedState.frozen &&
|
||||
(oldState.sortedData &&
|
||||
!newResolvedState.frozen &&
|
||||
oldState.resolvedData !== newResolvedState.resolvedData &&
|
||||
this.props.collapseOnDataChange)
|
||||
) {
|
||||
@@ -98,13 +99,18 @@ export default Base =>
|
||||
Object.assign(newResolvedState, this.getSortedData(newResolvedState))
|
||||
}
|
||||
|
||||
// Set page to 0 if filters change
|
||||
if (oldState.filtered !== newResolvedState.filtered) {
|
||||
newResolvedState.page = 0
|
||||
}
|
||||
|
||||
// Calculate pageSize all the time
|
||||
if (newResolvedState.sortedData) {
|
||||
newResolvedState.pages = newResolvedState.manual
|
||||
? newResolvedState.pages
|
||||
: Math.ceil(
|
||||
newResolvedState.sortedData.length / newResolvedState.pageSize
|
||||
)
|
||||
newResolvedState.sortedData.length / newResolvedState.pageSize
|
||||
)
|
||||
newResolvedState.page = Math.max(
|
||||
newResolvedState.page >= newResolvedState.pages
|
||||
? newResolvedState.pages - 1
|
||||
@@ -113,6 +119,16 @@ export default Base =>
|
||||
)
|
||||
}
|
||||
|
||||
return this.setState(newResolvedState, cb)
|
||||
return this.setState(newResolvedState, () => {
|
||||
cb && cb()
|
||||
if (
|
||||
oldState.page !== newResolvedState.page ||
|
||||
oldState.pageSize !== newResolvedState.pageSize ||
|
||||
oldState.sorted !== newResolvedState.sorted ||
|
||||
oldState.filtered !== newResolvedState.filtered
|
||||
) {
|
||||
this.fireFetchData()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+86
-66
@@ -55,7 +55,7 @@ export default Base =>
|
||||
columnsWithExpander = [expanderColumn, ...columnsWithExpander]
|
||||
}
|
||||
|
||||
const makeDecoratedColumn = column => {
|
||||
const makeDecoratedColumn = (column, parentColumn) => {
|
||||
let dcol
|
||||
if (column.expander) {
|
||||
dcol = {
|
||||
@@ -70,6 +70,16 @@ export default Base =>
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure minWidth is not greater than maxWidth if set
|
||||
if (dcol.maxWidth < dcol.minWidth) {
|
||||
dcol.minWidth = dcol.maxWidth
|
||||
}
|
||||
|
||||
if (parentColumn) {
|
||||
dcol.parentColumn = parentColumn
|
||||
}
|
||||
|
||||
// First check for string accessor
|
||||
if (typeof dcol.accessor === 'string') {
|
||||
dcol.id = dcol.id || dcol.accessor
|
||||
const accessorString = dcol.accessor
|
||||
@@ -77,6 +87,7 @@ export default Base =>
|
||||
return dcol
|
||||
}
|
||||
|
||||
// Fall back to functional accessor (but require an ID)
|
||||
if (dcol.accessor && !dcol.id) {
|
||||
console.warn(dcol)
|
||||
throw new Error(
|
||||
@@ -84,30 +95,26 @@ export default Base =>
|
||||
)
|
||||
}
|
||||
|
||||
// Fall back to an undefined accessor
|
||||
if (!dcol.accessor) {
|
||||
dcol.accessor = d => undefined
|
||||
}
|
||||
|
||||
// Ensure minWidth is not greater than maxWidth if set
|
||||
if (dcol.maxWidth < dcol.minWidth) {
|
||||
dcol.minWidth = dcol.maxWidth
|
||||
}
|
||||
|
||||
return dcol
|
||||
}
|
||||
|
||||
// Decorate the columns
|
||||
const decorateAndAddToAll = col => {
|
||||
const decoratedColumn = makeDecoratedColumn(col)
|
||||
const decorateAndAddToAll = (column, parentColumn) => {
|
||||
const decoratedColumn = makeDecoratedColumn(column, parentColumn)
|
||||
allDecoratedColumns.push(decoratedColumn)
|
||||
return decoratedColumn
|
||||
}
|
||||
let allDecoratedColumns = []
|
||||
const allDecoratedColumns = []
|
||||
const decoratedColumns = columnsWithExpander.map((column, i) => {
|
||||
if (column.columns) {
|
||||
return {
|
||||
...column,
|
||||
columns: column.columns.map(decorateAndAddToAll),
|
||||
columns: column.columns.map(d => decorateAndAddToAll(d, column)),
|
||||
}
|
||||
} else {
|
||||
return decorateAndAddToAll(column)
|
||||
@@ -156,8 +163,17 @@ export default Base =>
|
||||
}
|
||||
})
|
||||
|
||||
let PivotParentColumn = pivotColumns.reduce(
|
||||
(prev, current) =>
|
||||
prev && prev === current.parentColumn && current.parentColumn,
|
||||
pivotColumns[0].parentColumn
|
||||
)
|
||||
|
||||
let PivotGroupHeader = hasHeaderGroups && PivotParentColumn.Header
|
||||
PivotGroupHeader = PivotGroupHeader || (() => <strong>Pivoted</strong>)
|
||||
|
||||
let pivotColumnGroup = {
|
||||
header: () => <strong>Group</strong>,
|
||||
Header: PivotGroupHeader,
|
||||
columns: pivotColumns.map(col => ({
|
||||
...this.props.pivotDefaults,
|
||||
...col,
|
||||
@@ -309,15 +325,15 @@ export default Base =>
|
||||
sortedData: manual
|
||||
? resolvedData
|
||||
: this.sortData(
|
||||
this.filterData(
|
||||
resolvedData,
|
||||
filtered,
|
||||
defaultFilterMethod,
|
||||
allVisibleColumns
|
||||
),
|
||||
sorted,
|
||||
sortMethodsByColumnID
|
||||
this.filterData(
|
||||
resolvedData,
|
||||
filtered,
|
||||
defaultFilterMethod,
|
||||
allVisibleColumns
|
||||
),
|
||||
sorted,
|
||||
sortMethodsByColumnID
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,20 +354,23 @@ export default Base =>
|
||||
|
||||
if (filtered.length) {
|
||||
filteredData = filtered.reduce((filteredSoFar, nextFilter) => {
|
||||
return filteredSoFar.filter(row => {
|
||||
let column
|
||||
const column = allVisibleColumns.find(x => x.id === nextFilter.id)
|
||||
|
||||
column = allVisibleColumns.find(x => x.id === nextFilter.id)
|
||||
// Don't filter hidden columns or columns that have had their filters disabled
|
||||
if (!column || column.filterable === false) {
|
||||
return filteredSoFar
|
||||
}
|
||||
|
||||
// Don't filter hidden columns or columns that have had their filters disabled
|
||||
if (!column || column.filterable === false) {
|
||||
return true
|
||||
}
|
||||
const filterMethod = column.filterMethod || defaultFilterMethod
|
||||
|
||||
const filterMethod = column.filterMethod || defaultFilterMethod
|
||||
|
||||
return filterMethod(nextFilter, row, column)
|
||||
})
|
||||
// If 'filterAll' is set to true, pass the entire dataset to the filter method
|
||||
if (column.filterAll) {
|
||||
return filterMethod(nextFilter, filteredSoFar, column)
|
||||
} else {
|
||||
return filteredSoFar.filter(row => {
|
||||
return filterMethod(nextFilter, row, column)
|
||||
})
|
||||
}
|
||||
}, filteredData)
|
||||
|
||||
// Apply the filter to the subrows if we are pivoting, and then
|
||||
@@ -393,11 +412,11 @@ export default Base =>
|
||||
// Support custom sorting methods for each column
|
||||
if (sortMethodsByColumnID[sort.id]) {
|
||||
return (a, b) => {
|
||||
return sortMethodsByColumnID[sort.id](a[sort.id], b[sort.id])
|
||||
return sortMethodsByColumnID[sort.id](a[sort.id], b[sort.id], sort.desc)
|
||||
}
|
||||
}
|
||||
return (a, b) => {
|
||||
return this.props.defaultSortMethod(a[sort.id], b[sort.id])
|
||||
return this.props.defaultSortMethod(a[sort.id], b[sort.id], sort.desc)
|
||||
}
|
||||
}),
|
||||
sorted.map(d => !d.desc),
|
||||
@@ -435,7 +454,6 @@ export default Base =>
|
||||
}
|
||||
this.setStateWithData(newState, () => {
|
||||
onPageChange && onPageChange(page)
|
||||
this.fireFetchData()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -454,7 +472,6 @@ export default Base =>
|
||||
},
|
||||
() => {
|
||||
onPageSizeChange && onPageSizeChange(newPageSize, newPage)
|
||||
this.fireFetchData()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -559,14 +576,14 @@ export default Base =>
|
||||
|
||||
this.setStateWithData(
|
||||
{
|
||||
page: (!sorted.length && newSorted.length) || !additive
|
||||
? 0
|
||||
: this.state.page,
|
||||
page:
|
||||
(!sorted.length && newSorted.length) || !additive
|
||||
? 0
|
||||
: this.state.page,
|
||||
sorted: newSorted,
|
||||
},
|
||||
() => {
|
||||
onSortedChange && onSortedChange(newSorted, column, additive)
|
||||
this.fireFetchData()
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -595,12 +612,12 @@ export default Base =>
|
||||
},
|
||||
() => {
|
||||
onFilteredChange && onFilteredChange(newFiltering, column, value)
|
||||
this.fireFetchData()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
resizeColumnStart (column, event, isTouch) {
|
||||
resizeColumnStart (event, column, isTouch) {
|
||||
event.stopPropagation()
|
||||
const parentWidth = event.target.parentElement.getBoundingClientRect()
|
||||
.width
|
||||
|
||||
@@ -611,6 +628,7 @@ export default Base =>
|
||||
pageX = event.pageX
|
||||
}
|
||||
|
||||
this.trapEvents = true
|
||||
this.setStateWithData(
|
||||
{
|
||||
currentlyResizing: {
|
||||
@@ -633,33 +651,8 @@ export default Base =>
|
||||
)
|
||||
}
|
||||
|
||||
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,
|
||||
currentlyResizing: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resizeColumnMoving (event) {
|
||||
event.stopPropagation()
|
||||
const { onResizedChange } = this.props
|
||||
const { resized, currentlyResizing } = this.getResolvedState()
|
||||
|
||||
@@ -694,4 +687,31 @@ export default Base =>
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
resizeColumnEnd (event) {
|
||||
event.stopPropagation()
|
||||
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,
|
||||
currentlyResizing: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-22
@@ -3,8 +3,11 @@ import classnames from 'classnames'
|
||||
//
|
||||
// import _ from './utils'
|
||||
|
||||
const defaultButton = props =>
|
||||
<button type='button' {...props} className='-btn'>{props.children}</button>
|
||||
const defaultButton = props => (
|
||||
<button type='button' {...props} className='-btn'>
|
||||
{props.children}
|
||||
</button>
|
||||
)
|
||||
|
||||
export default class ReactTablePagination extends Component {
|
||||
constructor (props) {
|
||||
@@ -83,26 +86,28 @@ export default class ReactTablePagination extends Component {
|
||||
{this.props.pageText}{' '}
|
||||
{showPageJump
|
||||
? <div className='-pageJump'>
|
||||
<input
|
||||
type={this.state.page === '' ? 'text' : 'number'}
|
||||
onChange={e => {
|
||||
const val = e.target.value
|
||||
const page = val - 1
|
||||
if (val === '') {
|
||||
return this.setState({ page: val })
|
||||
}
|
||||
this.setState({ page: this.getSafePage(page) })
|
||||
}}
|
||||
value={this.state.page === '' ? '' : this.state.page + 1}
|
||||
onBlur={this.applyPage}
|
||||
onKeyPress={e => {
|
||||
if (e.which === 13 || e.keyCode === 13) {
|
||||
this.applyPage()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
: <span className='-currentPage'>{page + 1}</span>}{' '}
|
||||
<input
|
||||
type={this.state.page === '' ? 'text' : 'number'}
|
||||
onChange={e => {
|
||||
const val = e.target.value
|
||||
const page = val - 1
|
||||
if (val === '') {
|
||||
return this.setState({ page: val })
|
||||
}
|
||||
this.setState({ page: this.getSafePage(page) })
|
||||
}}
|
||||
value={this.state.page === '' ? '' : this.state.page + 1}
|
||||
onBlur={this.applyPage}
|
||||
onKeyPress={e => {
|
||||
if (e.which === 13 || e.keyCode === 13) {
|
||||
this.applyPage()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
: <span className='-currentPage'>
|
||||
{page + 1}
|
||||
</span>}{' '}
|
||||
{this.props.ofText}{' '}
|
||||
<span className='-totalPages'>{pages || 1}</span>
|
||||
</span>
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
export default {
|
||||
// General
|
||||
data: PropTypes.array,
|
||||
loading: PropTypes.bool,
|
||||
showPagination: PropTypes.bool,
|
||||
showPaginationTop: PropTypes.bool,
|
||||
showPaginationBottom: PropTypes.bool,
|
||||
showPageSizeOptions: PropTypes.bool,
|
||||
pageSizeOptions: PropTypes.array,
|
||||
defaultPageSize: PropTypes.number,
|
||||
showPageJump: PropTypes.bool,
|
||||
collapseOnSortingChange: PropTypes.bool,
|
||||
collapseOnPageChange: PropTypes.bool,
|
||||
collapseOnDataChange: PropTypes.bool,
|
||||
freezeWhenExpanded: PropTypes.bool,
|
||||
sortable: PropTypes.bool,
|
||||
resizable: PropTypes.bool,
|
||||
filterable: PropTypes.bool,
|
||||
defaultSortDesc: PropTypes.bool,
|
||||
defaultSorted: PropTypes.array,
|
||||
defaultFiltered: PropTypes.array,
|
||||
defaultResized: PropTypes.array,
|
||||
defaultExpanded: PropTypes.object,
|
||||
defaultFilterMethod: PropTypes.func,
|
||||
defaultSortMethod: PropTypes.func,
|
||||
|
||||
// Controlled State Callbacks
|
||||
onPageChange: PropTypes.func,
|
||||
onPageSizeChange: PropTypes.func,
|
||||
onSortedChange: PropTypes.func,
|
||||
onFilteredChange: PropTypes.func,
|
||||
onResizedChange: PropTypes.func,
|
||||
onExpandedChange: PropTypes.func,
|
||||
|
||||
// Pivoting
|
||||
pivotBy: PropTypes.array,
|
||||
|
||||
// Key Constants
|
||||
pivotValKey: PropTypes.string,
|
||||
pivotIDKey: PropTypes.string,
|
||||
subRowsKey: PropTypes.string,
|
||||
aggregatedKey: PropTypes.string,
|
||||
nestingLevelKey: PropTypes.string,
|
||||
originalKey: PropTypes.string,
|
||||
indexKey: PropTypes.string,
|
||||
groupedByPivotKey: PropTypes.string,
|
||||
|
||||
// Server-side Callbacks
|
||||
onFetchData: PropTypes.func,
|
||||
|
||||
// Classes
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
|
||||
// Component decorators
|
||||
getProps: PropTypes.func,
|
||||
getTableProps: PropTypes.func,
|
||||
getTheadGroupProps: PropTypes.func,
|
||||
getTheadGroupTrProps: PropTypes.func,
|
||||
getTheadGroupThProps: PropTypes.func,
|
||||
getTheadProps: PropTypes.func,
|
||||
getTheadTrProps: PropTypes.func,
|
||||
getTheadThProps: PropTypes.func,
|
||||
getTheadFilterProps: PropTypes.func,
|
||||
getTheadFilterTrProps: PropTypes.func,
|
||||
getTheadFilterThProps: PropTypes.func,
|
||||
getTbodyProps: PropTypes.func,
|
||||
getTrGroupProps: PropTypes.func,
|
||||
getTrProps: PropTypes.func,
|
||||
getTdProps: PropTypes.func,
|
||||
getTfootProps: PropTypes.func,
|
||||
getTfootTrProps: PropTypes.func,
|
||||
getTfootTdProps: PropTypes.func,
|
||||
getPaginationProps: PropTypes.func,
|
||||
getLoadingProps: PropTypes.func,
|
||||
getNoDataProps: PropTypes.func,
|
||||
getResizerProps: PropTypes.func,
|
||||
|
||||
// Global Column Defaults
|
||||
columns: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
// Renderers
|
||||
Cell: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Header: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Footer: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Aggregated: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Pivot: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
PivotValue: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Expander: PropTypes.oneOfType([
|
||||
PropTypes.element,
|
||||
PropTypes.string,
|
||||
PropTypes.func
|
||||
]),
|
||||
Filter: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
|
||||
|
||||
// All Columns
|
||||
sortable: PropTypes.bool, // use table default
|
||||
resizable: PropTypes.bool, // use table default
|
||||
filterable: PropTypes.bool, // use table default
|
||||
show: PropTypes.bool,
|
||||
minWidth: PropTypes.number,
|
||||
|
||||
// Cells only
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
getProps: PropTypes.func,
|
||||
|
||||
// Pivot only
|
||||
aggregate: PropTypes.func,
|
||||
|
||||
// Headers only
|
||||
headerClassName: PropTypes.string,
|
||||
headerStyle: PropTypes.object,
|
||||
getHeaderProps: PropTypes.func,
|
||||
|
||||
// Footers only
|
||||
footerClassName: PropTypes.string,
|
||||
footerStyle: PropTypes.object,
|
||||
getFooterProps: PropTypes.object,
|
||||
filterMethod: PropTypes.func,
|
||||
filterAll: PropTypes.bool,
|
||||
sortMethod: PropTypes.func
|
||||
})
|
||||
),
|
||||
|
||||
// Global Expander Column Defaults
|
||||
expanderDefaults: PropTypes.shape({
|
||||
sortable: PropTypes.bool,
|
||||
resizable: PropTypes.bool,
|
||||
filterable: PropTypes.bool,
|
||||
width: PropTypes.number
|
||||
}),
|
||||
|
||||
pivotDefaults: PropTypes.object,
|
||||
|
||||
// Text
|
||||
previousText: PropTypes.node,
|
||||
nextText: PropTypes.node,
|
||||
loadingText: PropTypes.node,
|
||||
noDataText: PropTypes.node,
|
||||
pageText: PropTypes.node,
|
||||
ofText: PropTypes.node,
|
||||
rowsText: PropTypes.node,
|
||||
|
||||
// Components
|
||||
TableComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TheadComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TbodyComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TrGroupComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TrComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
ThComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TdComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
TfootComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
FilterComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
ExpanderComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
PivotValueComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
AggregatedComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
PivotComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]), // this is a computed default generated using
|
||||
// the ExpanderComponent and PivotValueComponent at run-time in methods.js
|
||||
PaginationComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
PreviousComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
NextComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
LoadingComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
NoDataComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
ResizerComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element]),
|
||||
PadRowComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.element])
|
||||
};
|
||||
+17
-5
@@ -19,6 +19,7 @@ export default {
|
||||
compactObject,
|
||||
isSortingDesc,
|
||||
normalizeComponent,
|
||||
asPx,
|
||||
}
|
||||
|
||||
function get (obj, path, def) {
|
||||
@@ -121,11 +122,17 @@ function sum (arr) {
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function makeTemplateComponent (compClass) {
|
||||
return ({ children, className, ...rest }) =>
|
||||
function makeTemplateComponent (compClass, displayName) {
|
||||
if (!displayName) {
|
||||
throw new Error('No displayName found for template component:', compClass)
|
||||
}
|
||||
const cmp = ({ children, className, ...rest }) => (
|
||||
<div className={classnames(compClass, className)} {...rest}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
cmp.displayName = displayName
|
||||
return cmp
|
||||
}
|
||||
|
||||
function groupBy (xs, key) {
|
||||
@@ -137,6 +144,11 @@ function groupBy (xs, key) {
|
||||
}, {})
|
||||
}
|
||||
|
||||
function asPx (value) {
|
||||
value = Number(value)
|
||||
return Number.isNaN(value) ? null : value + 'px'
|
||||
}
|
||||
|
||||
function isArray (a) {
|
||||
return Array.isArray(a)
|
||||
}
|
||||
@@ -148,8 +160,8 @@ function isArray (a) {
|
||||
function makePathArray (obj) {
|
||||
return flattenDeep(obj)
|
||||
.join('.')
|
||||
.replace('[', '.')
|
||||
.replace(']', '')
|
||||
.replace(/\[/g, '.')
|
||||
.replace(/\]/g, '')
|
||||
.split('.')
|
||||
}
|
||||
|
||||
@@ -168,7 +180,7 @@ function splitProps ({ className, style, ...rest }) {
|
||||
return {
|
||||
className,
|
||||
style,
|
||||
rest,
|
||||
rest: rest || {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user