Compare commits

...
Author SHA1 Message Date
AllenFang 31724fec7f add story for #979 2019-06-22 13:51:04 +08:00
AllenFang 4cf6e65abc fix #979 2019-06-22 13:50:50 +08:00
AllenFang 40c5ae7459 Publish
- react-bootstrap-table2-editor@1.2.4
 - react-bootstrap-table2-example@1.0.26
 - react-bootstrap-table2-toolkit@2.0.1
 - react-bootstrap-table-next@3.1.4
2019-06-10 20:53:14 +08:00
AllenandGitHub 3747c36039 Merge pull request #973 from react-bootstrap-table/develop
20190610 release
2019-06-10 20:51:10 +08:00
AllenFang 0d0d1a8913 fix #947 2019-06-08 17:19:39 +08:00
AllenFang db612eaa99 fix #946 2019-06-08 16:47:14 +08:00
AllenandGitHub 4d76d88e9a fix #945 (#967) 2019-06-08 13:11:49 +08:00
William LaugesenandAllen 1cd31dc54c Added Prop to csv/exporter.js to allow overriding of the Blob's default type (#958) 2019-06-07 13:18:50 +08:00
Bill ParrottandAllen 4ec02b294a set tabindex to 0 for table headers; fixes #955 (#965) 2019-06-05 20:13:35 +08:00
AllenFang 60eb47dc9e Publish
- react-bootstrap-table2-overlay@2.0.0
 - react-bootstrap-table2-toolkit@2.0.0
 - react-bootstrap-table-next@3.1.3
2019-05-19 21:19:50 +08:00
AllenandGitHub d74ecb63b4 Merge pull request #949 from react-bootstrap-table/develop
20190519 release
2019-05-19 21:14:49 +08:00
AllenFang 2c6cc915f0 fix #932 2019-05-19 17:05:32 +08:00
AllenFang a1457dfe59 fix #929 2019-05-19 16:28:36 +08:00
AllenFang 036c3fdc32 fix #940 2019-05-19 16:21:14 +08:00
AllenFang 55eea6f337 try to fix #916 2019-05-19 16:12:53 +08:00
Rita ZhaoandAllen 7c259cd1ee Add aria-label to search input (#931) 2019-05-12 12:58:53 +08:00
Bhathiya PereraandAllen 1e164bb3f4 Update row-selection.md (#937) 2019-05-12 12:53:14 +08:00
AllenFang 8a7c1def5b Publish
- react-bootstrap-table2-example@1.0.25
 - react-bootstrap-table2-toolkit@1.4.2
 - react-bootstrap-table-next@3.1.2
2019-04-29 21:20:42 +08:00
AllenandGitHub 77b8ed53bf Merge pull request #926 from react-bootstrap-table/develop
20190427 release
2019-04-29 21:19:37 +08:00
AllenFang 6bc54ef3ec fix test fail 2019-04-27 16:52:03 +08:00
AllenFang 6168bd7532 fix #905 2019-04-27 16:11:55 +08:00
AllenFang 36fa9b8630 fix #908 2019-04-27 15:38:28 +08:00
AllenFang 737922a5a4 fix #904 2019-04-27 14:58:57 +08:00
AllenFang 0f37fae23d fix #899 2019-04-27 14:38:41 +08:00
KirillandAllen ce7e05d7f9 Fix default prop tableId for SearchBar (#914) 2019-04-27 13:53:47 +08:00
AllenFang 067006eb72 fix #920 2019-04-27 13:46:47 +08:00
Utkarsh GuptaandAllen 8fa10e3b6f Added missed attribute (#913)
You missed 'onlyOneExpanding: true' in the source code.
2019-04-27 13:37:09 +08:00
AllenFang e2e6c51d40 Publish
- react-bootstrap-table2-example@1.0.24
 - react-bootstrap-table2-filter@1.1.9
 - react-bootstrap-table2-paginator@2.0.6
 - react-bootstrap-table2-toolkit@1.4.1
 - react-bootstrap-table-next@3.1.1
2019-04-15 19:45:38 +08:00
AllenandGitHub fb724331d3 Merge pull request #900 from react-bootstrap-table/develop
20180408 release
2019-04-15 19:38:41 +08:00
AllenFang 160dede412 fix #898 2019-04-07 17:33:00 +08:00
AllenFang 363a43251f fix #891 2019-04-07 16:49:03 +08:00
AllenFang 8ad0e65679 Merge branch 'SmaranSingh-master' into develop 2019-04-07 14:32:41 +08:00
AllenFang 6d5cca0047 optimize selection option equals 2019-04-07 14:31:43 +08:00
AllenFang 204e75c9c2 Merge branch 'master' of https://github.com/SmaranSingh/react-bootstrap-table2 into SmaranSingh-master 2019-04-07 14:30:21 +08:00
AllenFang fc27c56cbb Merge branch 'Jayboy75-develop' into develop 2019-04-07 14:05:40 +08:00
AllenFang 8436edba7e no inline-block on label element 2019-04-07 14:03:42 +08:00
SmaranSinghandGitHub 3606fa3b7b Update select.js 2019-04-04 16:11:01 +05:30
SmaranSinghandGitHub 73e8701bde Update select.js 2019-04-04 15:37:34 +05:30
Jay Staudt 6d2493d537 revert page-button title 2019-04-02 14:53:52 -04:00
Jay Staudt 1a1f6969cb adjustments via eslint 2019-04-02 14:42:47 -04:00
Jay Staudt d47a3757b8 wrap search bar with label and hidden text 2019-04-02 14:10:14 -04:00
Jay Staudt ba7512969e add non-redundant titles to page buttons 2019-04-02 14:09:53 -04:00
Jay Staudt 955ee17939 wrap filter components with labels and hidden text 2019-04-02 14:09:20 -04:00
AllenFang 497bf44192 Publish
- react-bootstrap-table2-editor@1.2.3
 - react-bootstrap-table2-example@1.0.23
 - react-bootstrap-table2-filter@1.1.8
 - react-bootstrap-table-next@3.1.0
2019-04-02 21:33:49 +08:00
AllenandGitHub fcefcf8c84 Merge pull request #886 from react-bootstrap-table/develop
20190331 release
2019-04-02 21:25:03 +08:00
AllenandGitHub 04e3af0bbb Merge pull request #861 from react-bootstrap-table/feature/row-expand-animate
Feature/row expand animate
2019-03-31 16:02:13 +08:00
AllenFang 9f47fa009c lock version 2019-03-31 15:33:43 +08:00
Alek LefebvreandAllen 0edf9c8891 fix #808 (#874) 2019-03-31 15:17:57 +08:00
AllenFang df5024892c Publish
- react-bootstrap-table2-example@1.0.22
 - react-bootstrap-table2-paginator@2.0.5
 - react-bootstrap-table-next@3.0.3
2019-03-26 20:41:04 +08:00
AllenandGitHub 4448c3f28c Merge pull request #875 from react-bootstrap-table/develop
20190326 release
2019-03-26 20:39:13 +08:00
AllenFang 196ae33295 fix #859 2019-03-25 23:07:22 +08:00
AllenFang 7f1b7a6c97 fix #838 2019-03-24 20:52:26 +08:00
AllenFang a6ccafcc75 fix #866 2019-03-24 16:55:56 +08:00
AllenFang 06d87299a3 Publish
- react-bootstrap-table2-example@1.0.21
 - react-bootstrap-table2-filter@1.1.7
 - react-bootstrap-table2-toolkit@1.4.0
 - react-bootstrap-table-next@3.0.2
2019-03-18 00:31:24 +08:00
AllenandGitHub 5891ec1b93 Merge pull request #862 from react-bootstrap-table/develop
20190317 release
2019-03-18 00:28:47 +08:00
AllenFang c5d9e04c2c fix #817 2019-03-17 16:30:39 +08:00
AllenFang dba3da28c1 Merge branch 'YassienW-animate-row-expansion' into feature/row-expand-animate 2019-03-17 15:24:07 +08:00
AllenFang a0e09cd804 fix conflicts 2019-03-17 15:20:16 +08:00
AllenFang d0e70f7246 fix #852 2019-03-17 14:43:39 +08:00
henning-kvinneslandandAllen b93c683f17 Fix typo. (#855)
`to cusom the sort caret` => `to customize the sort-caret`
2019-03-17 13:30:35 +08:00
henning-kvinneslandandAllen f80e1ea66c Fix typo. (#856)
`chagne` => `change`
2019-03-17 13:30:21 +08:00
AllenFang 7642bfa1a3 fix #849 2019-03-17 13:29:17 +08:00
Yassien 8f304a849f Animation now works with custom expand management 2019-03-16 19:03:22 +02:00
AllenFang 956f1cef4d Publish
- react-bootstrap-table2-example@1.0.20
 - react-bootstrap-table2-filter@1.1.6
 - react-bootstrap-table2-paginator@2.0.4
 - react-bootstrap-table2-toolkit@1.3.2
 - react-bootstrap-table-next@3.0.1
2019-03-10 13:38:21 +08:00
AllenandGitHub c45deee590 Merge pull request #846 from react-bootstrap-table/develop
20190310 release
2019-03-10 13:37:02 +08:00
AllenFang 2aab4301dd fix #835 2019-03-09 23:01:21 +08:00
AllenFang 43aa280761 Merge branch 'develop' of https://github.com/react-bootstrap-table/react-bootstrap-table2 into develop 2019-03-09 23:00:59 +08:00
AllenFang 3af30a0265 fix #840 2019-03-09 22:35:49 +08:00
AllenFang 4b8b8b261e update story 2019-03-09 22:31:24 +08:00
Norbert NemethandAllen e44782f222 fix #863 - expanded row column span does not update (#837) 2019-03-09 18:46:04 +08:00
AllenFang 921e8c7ecc fix #830 2019-03-09 18:18:20 +08:00
AllenFang a3b3ce0dc4 Merge branch 'develop' of https://github.com/react-bootstrap-table/react-bootstrap-table2 into develop 2019-03-09 15:52:37 +08:00
AllenFang e9f08d278d fix #826 2019-03-09 15:52:10 +08:00
Sartaj Singh BavejaandAllen b4973c826c Minor update to docs (#841) 2019-03-06 22:28:41 +08:00
Yassien 33c026c7e2 Added original padding without breaking the animation 2019-02-25 13:01:42 +02:00
Yassien d84fd5c801 CSS Animation for row expansion 2019-02-23 22:40:05 +02:00
77 changed files with 2501 additions and 632 deletions
+17
View File
@@ -33,6 +33,7 @@
* [pagination](#pagination) * [pagination](#pagination)
* [filter](#filter) * [filter](#filter)
* [onTableChange](#onTableChange) * [onTableChange](#onTableChange)
* [onDataSizeChange](#onDataSizeChange)
### <a name='keyField'>keyField(**required**) - [String]</a> ### <a name='keyField'>keyField(**required**) - [String]</a>
Tells `react-bootstrap-table2` which column is unique. Tells `react-bootstrap-table2` which column is unique.
@@ -317,4 +318,20 @@ Following is a shape of `newState`
newValue newValue
} }
} }
```
### <a name='onDataSizeChange'>onDataSizeChange - [Function]</a>
This callback function will be called only when data size change by search/filter etc. This function have one argument which is an object contains below props:
* `dataSize`: The new data size
```js
handleDataChange = ({ dataSize }) => {
this.setState({ rowCount: dataSize });
}
<BootstrapTable
onDataSizeChange={ handleDataChange }
....
/>
``` ```
+1 -1
View File
@@ -69,7 +69,7 @@ const cellEdit: {
// omit... // omit...
beforeSaveCell(oldValue, newValue, row, column, done) { beforeSaveCell(oldValue, newValue, row, column, done) {
setTimeout(() => { setTimeout(() => {
if (confirm('Do you want to accep this change?')) { if (confirm('Do you want to accept this change?')) {
done(); // contine to save the changes done(); // contine to save the changes
} else { } else {
done(false); // reject the changes done(false); // reject the changes
+1 -1
View File
@@ -164,7 +164,7 @@ Enable the column sort via a `true` value given.
``` ```
## <a name='sortCaret'>column.sortCaret - [Function]</a> ## <a name='sortCaret'>column.sortCaret - [Function]</a>
Use`column.sortCaret` to custom the sort caret. This callback function accept two arguments: `order` and `column` Use`column.sortCaret` to customize the sort caret. This callback function accept two arguments: `order` and `column`
```js ```js
{ {
+1 -1
View File
@@ -2,7 +2,7 @@
# Row expand # Row expand
`react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality. `react-bootstrap-table2` supports the row expand feature. By passing prop `expandRow` to enable this functionality.
> Default is click to expand/collapse a row. In addition, we don't support any way to chagne this mechanism! > Default is click to expand/collapse a row. In addition, we don't support any way to change this mechanism!
## Required ## Required
* [renderer (**required**)](#renderer) * [renderer (**required**)](#renderer)
+75 -1
View File
@@ -1,6 +1,6 @@
# Row selection # Row selection
`react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow` to enable row selection. When you enable this feature, `react-bootstrap-table2` will append a new selection column at first. `react-bootstrap-table2` supports the row selection feature. By passing prop `selectRow` to enable row selection. When you enable this feature, `react-bootstrap-table2` will prepend a new selection column.
## Required ## Required
* [mode (**required**)](#mode) * [mode (**required**)](#mode)
@@ -16,10 +16,13 @@
* [clickToEdit](#clickToEdit) * [clickToEdit](#clickToEdit)
* [onSelect](#onSelect) * [onSelect](#onSelect)
* [onSelectAll](#onSelectAll) * [onSelectAll](#onSelectAll)
* [selectColumnPosition](#selectColumnPosition)
* [hideSelectColumn](#hideSelectColumn) * [hideSelectColumn](#hideSelectColumn)
* [hideSelectAll](#hideSelectAll) * [hideSelectAll](#hideSelectAll)
* [selectionRenderer](#selectionRenderer) * [selectionRenderer](#selectionRenderer)
* [selectionHeaderRenderer](#selectionHeaderRenderer) * [selectionHeaderRenderer](#selectionHeaderRenderer)
* [headerColumnStyle](#headerColumnStyle)
* [selectColumnStyle](#selectColumnStyle)
### <a name="mode">selectRow.mode - [String]</a> ### <a name="mode">selectRow.mode - [String]</a>
@@ -198,6 +201,67 @@ const selectRow = {
> By default, `react-bootstrap-table2` will help you to handle the click event, it's not necessary to handle again by developer. > By default, `react-bootstrap-table2` will help you to handle the click event, it's not necessary to handle again by developer.
### <a name='headerColumnStyle'>selectRow.headerColumnStyle - [Object | Function]</a>
A way to custome the selection header cell. `headerColumnStyle` not only accept a simple style object but also a callback function for more flexible customization:
### Style Object
```js
const selectRow = {
mode: 'checkbox',
headerColumnStyle: { backgroundColor: 'blue' }
};
```
### Callback Function
```js
const selectRow = {
mode: 'checkbox',
headerColumnStyle: (status) => (
// status available value is checked, indeterminate and unchecked
return { backgroundColor: 'blue' };
)
};
```
### <a name='selectColumnStyle'>selectRow.selectColumnStyle - [Object | Function]</a>
A way to custome the selection cell. `selectColumnStyle` not only accept a simple style object but also a callback function for more flexible customization:
### Style Object
```js
const selectRow = {
mode: 'checkbox',
selectColumnStyle: { backgroundColor: 'blue' }
};
```
### Callback Function
If a callback function present, you can get below information to custom the selection cell:
* `checked`: Whether current row is seleccted or not
* `disabled`: Whether current row is disabled or not
* `rowIndex`: Current row index
* `rowKey`: Current row key
```js
const selectRow = {
mode: 'checkbox',
selectColumnStyle: ({
checked,
disabled,
rowIndex,
rowKey
}) => (
// ....
return { backgroundColor: 'blue' };
)
};
```
### <a name='onSelect'>selectRow.onSelect - [Function]</a> ### <a name='onSelect'>selectRow.onSelect - [Function]</a>
This callback function will be called when a row is select/unselect and pass following three arguments: This callback function will be called when a row is select/unselect and pass following three arguments:
`row`, `isSelect`, `rowIndex` and `e`. `row`, `isSelect`, `rowIndex` and `e`.
@@ -249,6 +313,16 @@ const selectRow = {
}; };
``` ```
### <a name='selectColumnPosition'>selectRow.selectColumnPosition - [String]</a>
Default is `left`. You can give this as `right` for rendering selection column in the right side.
```js
const selectRow = {
mode: 'checkbox',
selectColumnPosition: 'right'
};
```
### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a> ### <a name='hideSelectColumn'>selectRow.hideSelectColumn - [Bool]</a>
Default is `false`, if you don't want to have a selection column, give this prop as `true` Default is `false`, if you don't want to have a selection column, give this prop as `true`
@@ -89,7 +89,10 @@ const columns = [
In the following, we go though all the predefined editors: In the following, we go though all the predefined editors:
### Dropdown Editor ### Dropdown Editor
Dropdown editor give a select menu to choose a data from a list, the `editor.options` is required property for dropdown editor. Dropdown editor give a select menu to choose a data from a list. When use dropdown editor, either `editor.options` or `editor.getOptions` should be required prop.
#### editor.options
This is most simple case for assign the dropdown options data directly.
```js ```js
import { Type } from 'react-bootstrap-table2-editor'; import { Type } from 'react-bootstrap-table2-editor';
@@ -119,6 +122,46 @@ const columns = [
}]; }];
``` ```
#### editor.getOptions
It is much flexible which accept a function and you can assign the dropdown options dynamically.
There are two case for `getOptions`:
* *Synchronous*: Just return the options array in `getOptions` callback function
* *Asynchronous*: Call `setOptions` function argument when you get the options from remote.
```js
// Synchronous
const columns = [
..., {
dataField: 'type',
text: 'Job Type',
editor: {
type: Type.SELECT,
getOptions: () => [.....]
}
}];
// Asynchronous
const columns = [
..., {
dataField: 'type',
text: 'Job Type',
editor: {
type: Type.SELECT,
getOptions: (setOptions) => {
setTimeout(() => setOptions([...]), 1500);
}
}
}];
```
[here](https://react-bootstrap-table.github.io/react-bootstrap-table2/storybook/index.html?selectedKind=Cell%20Editing&selectedStory=Dropdown%20Editor%20with%20Dynamic%20Options) is an online example.
### Date Editor ### Date Editor
Date editor is use `<input type="date">`, the configuration is very simple: Date editor is use `<input type="date">`, the configuration is very simple:
@@ -132,7 +175,7 @@ const columns = [
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`; return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE
@@ -173,16 +216,16 @@ If you feel above predefined editors are not satisfied to your requirement, you
* `editorProps`: Some useful attributes you can use on DOM editor, like class, style etc. * `editorProps`: Some useful attributes you can use on DOM editor, like class, style etc.
* `value`: Current cell value * `value`: Current cell value
* `row`: Current row data * `row`: Current row data
* `column`: Current column definition * `column`: Current column definition
* `rowIndex`: Current row index * `rowIndex`: Current row index
* `columnIndex`: Current column index * `columnIndex`: Current column index
> Note when implement a custom React editor component, this component should have a **getValue** function which return current value on editor > Note when implement a custom React editor component, this component should have a **getValue** function which return current value on editor
> Note when you want to save value, you can call **editorProps.onUpdate** function > Note when you want to save value, you can call **editorProps.onUpdate** function
Following is a short example: Following is a short example:
```js ```js
class QualityRanger extends React.Component { class QualityRanger extends React.Component {
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-editor", "name": "react-bootstrap-table2-editor",
"version": "1.2.2", "version": "1.2.4",
"description": "it's the editor addon for react-bootstrap-table2", "description": "it's the editor addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"scripts": { "scripts": {
@@ -4,6 +4,15 @@ import cs from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
class DropDownEditor extends Component { class DropDownEditor extends Component {
constructor(props) {
super(props);
let options = props.options;
if (props.getOptions) {
options = props.getOptions(this.setOptions.bind(this)) || [];
}
this.state = { options };
}
componentDidMount() { componentDidMount() {
const { defaultValue, didMount } = this.props; const { defaultValue, didMount } = this.props;
this.select.value = defaultValue; this.select.value = defaultValue;
@@ -11,12 +20,16 @@ class DropDownEditor extends Component {
if (didMount) didMount(); if (didMount) didMount();
} }
setOptions(options) {
this.setState({ options });
}
getValue() { getValue() {
return this.select.value; return this.select.value;
} }
render() { render() {
const { defaultValue, didMount, className, options, ...rest } = this.props; const { defaultValue, didMount, getOptions, className, ...rest } = this.props;
const editorClass = cs('form-control editor edit-select', className); const editorClass = cs('form-control editor edit-select', className);
const attr = { const attr = {
@@ -31,7 +44,7 @@ class DropDownEditor extends Component {
defaultValue={ defaultValue } defaultValue={ defaultValue }
> >
{ {
options.map(({ label, value }) => ( this.state.options.map(({ label, value }) => (
<option key={ value } value={ value }>{ label }</option> <option key={ value } value={ value }>{ label }</option>
)) ))
} }
@@ -52,13 +65,16 @@ DropDownEditor.propTypes = {
label: PropTypes.string, label: PropTypes.string,
value: PropTypes.any value: PropTypes.any
})) }))
]).isRequired, ]),
didMount: PropTypes.func didMount: PropTypes.func,
getOptions: PropTypes.func
}; };
DropDownEditor.defaultProps = { DropDownEditor.defaultProps = {
className: '', className: '',
defaultValue: '', defaultValue: '',
style: {}, style: {},
didMount: undefined options: [],
didMount: undefined,
getOptions: undefined
}; };
export default DropDownEditor; export default DropDownEditor;
@@ -9,6 +9,7 @@ const sourceStylePath = path.join(__dirname, '../../react-bootstrap-table2/style
const paginationStylePath = path.join(__dirname, '../../react-bootstrap-table2-paginator/style'); const paginationStylePath = path.join(__dirname, '../../react-bootstrap-table2-paginator/style');
const filterStylePath = path.join(__dirname, '../../react-bootstrap-table2-filter/style'); const filterStylePath = path.join(__dirname, '../../react-bootstrap-table2-filter/style');
const toolkitSourcePath = path.join(__dirname, '../../react-bootstrap-table2-toolkit/index.js'); const toolkitSourcePath = path.join(__dirname, '../../react-bootstrap-table2-toolkit/index.js');
const toolkitStylePath = path.join(__dirname, '../../react-bootstrap-table2-toolkit/style');
const storyPath = path.join(__dirname, '../stories'); const storyPath = path.join(__dirname, '../stories');
const examplesPath = path.join(__dirname, '../examples'); const examplesPath = path.join(__dirname, '../examples');
const srcPath = path.join(__dirname, '../src'); const srcPath = path.join(__dirname, '../src');
@@ -43,7 +44,13 @@ const loaders = [{
}, { }, {
test: /\.scss$/, test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'], use: ['style-loader', 'css-loader', 'sass-loader'],
include: [storyPath, sourceStylePath, paginationStylePath, filterStylePath], include: [
storyPath,
sourceStylePath,
paginationStylePath,
filterStylePath,
toolkitStylePath
],
}, { }, {
test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/, test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000', loader: 'url-loader?limit=100000',
@@ -45,8 +45,12 @@ class ExposedFunctionTable extends React.Component {
console.log(this.node.table.props.data); console.log(this.node.table.props.data);
} }
handleGetCurrentData = () => {
console.log(this.node.table.props.data);
}
handleGetSelectedData = () => { handleGetSelectedData = () => {
console.log(this.node.selectionContext.state.selected); console.log(this.node.selectionContext.selected);
} }
handleGetExpandedData = () => { handleGetExpandedData = () => {
@@ -117,7 +121,7 @@ export default class ExposedFunctionTable extends React.Component {
} }
handleGetSelectedData = () => { handleGetSelectedData = () => {
console.log(this.node.selectionContext.state.selected); console.log(this.node.selectionContext.selected);
} }
handleGetExpandedData = () => { handleGetExpandedData = () => {
@@ -23,7 +23,7 @@ const columns = [{
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return `${('0' + dateObj.getDate()).slice(-2)}/${('0' + (dateObj.getMonth() + 1)).slice(-2)}/${dateObj.getFullYear()}`; return `${('0' + dateObj.getUTCDate()).slice(-2)}/${('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/${dateObj.getUTCFullYear()}`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE
@@ -48,7 +48,7 @@ const columns = [{
if (typeof cell !== 'object') { if (typeof cell !== 'object') {
dateObj = new Date(cell); dateObj = new Date(cell);
} }
return \`$\{('0' + dateObj.getDate()).slice(-2)}/$\{('0' + (dateObj.getMonth() + 1)).slice(-2)}/$\{dateObj.getFullYear()}\`; return \`$\{('0' + dateObj.getUTCDate()).slice(-2)}/$\{('0' + (dateObj.getUTCMonth() + 1)).slice(-2)}/$\{dateObj.getUTCFullYear()}\`;
}, },
editor: { editor: {
type: Type.DATE type: Type.DATE
@@ -0,0 +1,155 @@
/* eslint react/prefer-stateless-function: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
import Code from 'components/common/code-block';
import { jobsGenerator } from 'utils/common';
const jobs = jobsGenerator().map(j => ({
...j,
type2: j.type
}));
const columns = [{
dataField: 'id',
text: 'Job ID'
}, {
dataField: 'name',
text: 'Job Name'
}, {
dataField: 'owner',
text: 'Job Owner'
}, {
dataField: 'type',
text: 'Job Type1',
editor: {
type: Type.SELECT,
getOptions: () => [{
value: 'A',
label: 'A'
}, {
value: 'B',
label: 'B'
}, {
value: 'C',
label: 'C'
}, {
value: 'D',
label: 'D'
}, {
value: 'E',
label: 'E'
}]
}
}, {
dataField: 'type2',
text: 'Job Type2',
editor: {
type: Type.SELECT,
getOptions: (setOptions) => {
setTimeout(() => {
setOptions([{
value: 'A',
label: 'A'
}, {
value: 'B',
label: 'B'
}, {
value: 'C',
label: 'C'
}, {
value: 'D',
label: 'D'
}, {
value: 'E',
label: 'E'
}]);
}, 2000);
}
}
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import cellEditFactory, { Type } from 'react-bootstrap-table2-editor';
const columns = [{
dataField: 'id',
text: 'Job ID'
}, {
dataField: 'name',
text: 'Job Name'
}, {
dataField: 'owner',
text: 'Job Owner'
}, {
dataField: 'type',
text: 'Job Type1',
editor: {
type: Type.SELECT,
getOptions: () => [{
value: 'A',
label: 'A'
}, {
value: 'B',
label: 'B'
}, {
value: 'C',
label: 'C'
}, {
value: 'D',
label: 'D'
}, {
value: 'E',
label: 'E'
}]
}
}, {
dataField: 'type2',
text: 'Job Type2',
editor: {
type: Type.SELECT,
getOptions: (setOptions) => {
setTimeout(() => {
setOptions([{
value: 'A',
label: 'A'
}, {
value: 'B',
label: 'B'
}, {
value: 'C',
label: 'C'
}, {
value: 'D',
label: 'D'
}, {
value: 'E',
label: 'E'
}]);
}, 2000);
}
}
}];
<BootstrapTable
keyField="id"
data={ jobs }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click', blurToSave: true }) }
/>
`;
export default () => (
<div>
<h3>Dropdown Editor with Dynamic Options</h3>
<BootstrapTable
keyField="id"
data={ jobs }
columns={ columns }
cellEdit={ cellEditFactory({ mode: 'click', blurToSave: true }) }
/>
<Code>{ sourceCode }</Code>
</div>
);
@@ -11,141 +11,13 @@ const products = [
{ id: 14, name: 'Item 14', price: 14.5, inStock: true } { id: 14, name: 'Item 14', price: 14.5, inStock: true }
]; ];
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
const sourceCode = `\ const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
const columns = [
{
dataField: 'id',
text: 'Product ID'
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
class ProductList extends React.Component { class ProductList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { products }; this.state = { products, count: 0 };
} }
toggleInStock = () => { toggleInStock = () => {
@@ -163,17 +35,96 @@ class ProductList extends React.Component {
}; };
render() { render() {
const columns = [
{
dataField: 'id',
text: 'Product ID',
formatter: (cell, row, rowIndex, extraData) => (
<div>
<span>ID: {row.id}</span>
<br />
<span>state: {extraData}</span>
</div>
),
formatExtraData: this.state.count
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
return ( return (
<div> <div>
<h1 className="h2">Products</h1> <h3>Action 1 and Action 2 are dummy column</h3>
<button onClick={ this.toggleInStock } className="btn btn-primary">
Toggle item 13 stock status
</button>
<button
className="btn btn-success"
onClick={ () => this.setState(() => ({ count: this.state.count + 1 })) }
>
Click me to Increase counter
</button>
<BootstrapTable <BootstrapTable
keyField="id" keyField="id"
data={ this.state.products } data={ this.state.products }
columns={ columns } columns={ columns }
/> />
<button onClick={ this.toggleInStock } className="btn btn-primary"> <Code>{ sourceCode }</Code>
Toggle item 13 stock status
</button>
</div> </div>
); );
} }
@@ -183,7 +134,7 @@ class ProductList extends React.Component {
class ProductList extends React.Component { class ProductList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { products }; this.state = { products, count: 0 };
} }
toggleInStock = () => { toggleInStock = () => {
@@ -200,13 +151,95 @@ class ProductList extends React.Component {
this.setState(curr => ({ ...curr, products: newProducts })); this.setState(curr => ({ ...curr, products: newProducts }));
}; };
counter = () => {
this.setState(curr => ({ ...curr, count: this.state.count + 1 }));
}
render() { render() {
const columns = [
{
dataField: 'id',
text: 'Product ID',
formatter: (cell, row, rowIndex, extraData) => (
<div>
<span>ID: {row.id}</span>
<br />
<span>Counter: {extraData}</span>
</div>
),
formatExtraData: this.state.count
},
{
dataField: 'name',
text: 'Product Name'
},
{
dataField: 'price',
text: 'Product Price'
},
{
dataField: 'inStock',
text: 'In Stock',
formatter: (cellContent, row) => (
<div className="checkbox disabled">
<label>
<input type="checkbox" checked={ row.inStock } disabled />
</label>
</div>
)
},
{
dataField: 'df1',
isDummyField: true,
text: 'Action 1',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
},
{
dataField: 'df2',
isDummyField: true,
text: 'Action 2',
formatter: (cellContent, row) => {
if (row.inStock) {
return (
<h5>
<span className="label label-success"> Available</span>
</h5>
);
}
return (
<h5>
<span className="label label-danger"> Backordered</span>
</h5>
);
}
}
];
return ( return (
<div> <div>
<h3>Action 1 and Action 2 are dummy column</h3> <h3>Action 1 and Action 2 are dummy column</h3>
<button onClick={ this.toggleInStock } className="btn btn-primary"> <button onClick={ this.toggleInStock } className="btn btn-primary">
Toggle item 13 stock status Toggle item 13 stock status
</button> </button>
<button
className="btn btn-success"
onClick={ this.counter }
>
Click me to Increase counter
</button>
<BootstrapTable <BootstrapTable
keyField="id" keyField="id"
data={ this.state.products } data={ this.state.products }
@@ -0,0 +1,188 @@
/* eslint no-param-reassign: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
class DummyColumnWithRowExpand extends React.Component {
constructor(props) {
super(props);
this.state = {
hoverIdx: null
};
}
expandRow = {
renderer: () => (
<div style={ { width: '100%', height: '20px' } }>Content</div>
),
showExpandColumn: true,
expandByColumnOnly: true
};
actionFormater = (cell, row, rowIndex, { hoverIdx }) => {
if ((hoverIdx !== null || hoverIdx !== undefined) && hoverIdx === rowIndex) {
return (
<div
style={ { width: '20px', height: '20px', backgroundColor: 'orange' } }
/>
);
}
return (
<div
style={ { width: '20px', height: '20px' } }
/>
);
}
rowEvents = {
onMouseEnter: (e, row, rowIndex) => {
this.setState({ hoverIdx: rowIndex });
},
onMouseLeave: () => {
this.setState({ hoverIdx: null });
}
}
rowStyle = (row, rowIndex) => {
row.index = rowIndex;
const style = {};
if (rowIndex % 2 === 0) {
style.backgroundColor = 'transparent';
} else {
style.backgroundColor = 'rgba(54, 163, 173, .10)';
}
style.borderTop = 'none';
return style;
}
render() {
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}, {
text: '',
isDummyField: true,
formatter: this.actionFormater,
formatExtraData: { hoverIdx: this.state.hoverIdx },
headerStyle: { width: '50px' },
style: { height: '30px' }
}];
return (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
noDataIndication="There is no data"
classes="table"
rowStyle={ this.rowStyle }
rowEvents={ this.rowEvents }
expandRow={ this.expandRow }
/>
</div>
);
}
}
`;
export default class DummyColumnWithRowExpand extends React.Component {
constructor(props) {
super(props);
this.state = {
hoverIdx: null
};
}
expandRow = {
renderer: () => (
<div style={ { width: '100%', height: '20px' } }>Content</div>
),
showExpandColumn: true,
expandByColumnOnly: true
};
actionFormater = (cell, row, rowIndex, { hoverIdx }) => {
if ((hoverIdx !== null || hoverIdx !== undefined) && hoverIdx === rowIndex) {
return (
<div
style={ { width: '20px', height: '20px', backgroundColor: 'orange' } }
/>
);
}
return (
<div
style={ { width: '20px', height: '20px' } }
/>
);
}
rowEvents = {
onMouseEnter: (e, row, rowIndex) => {
this.setState({ hoverIdx: rowIndex });
},
onMouseLeave: () => {
this.setState({ hoverIdx: null });
}
}
rowStyle = (row, rowIndex) => {
row.index = rowIndex;
const style = {};
if (rowIndex % 2 === 0) {
style.backgroundColor = 'transparent';
} else {
style.backgroundColor = 'rgba(54, 163, 173, .10)';
}
style.borderTop = 'none';
return style;
}
render() {
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}, {
isDummyField: true,
text: '',
formatter: this.actionFormater,
formatExtraData: { hoverIdx: this.state.hoverIdx },
headerStyle: { width: '50px' },
style: { height: '30px' }
}];
return (
<div>
<BootstrapTable
keyField="id"
data={ products }
columns={ columns }
rowStyle={ this.rowStyle }
rowEvents={ this.rowEvents }
expandRow={ this.expandRow }
/>
<Code>{ sourceCode }</Code>
</div>
);
}
}
@@ -0,0 +1,102 @@
/* eslint react/prop-types: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import paginationFactory from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
const products = productsGenerator(150);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price'
}];
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { CSVExport, Search } from 'react-bootstrap-table2-toolkit';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
const { SearchBar } = Search;
const { ExportCSVButton } = CSVExport;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true
};
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
search
>
{
props => (
<div>
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
<hr />
<SearchBar { ...props.searchProps } />
<BootstrapTable
{ ...props.baseProps }
pagination={ paginationFactory() }
filter={ filterFactory() }
/>
</div>
)
}
</ToolkitProvider>
`;
export default () => (
<div>
<h3>Export all the filtered/searched rows</h3>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
exportCSV={ { onlyExportFiltered: true, exportAll: false } }
search
>
{
props => (
<div>
<ExportCSVButton { ...props.csvProps }>Export CSV!!</ExportCSVButton>
<hr />
<SearchBar { ...props.searchProps } />
<BootstrapTable
{ ...props.baseProps }
pagination={ paginationFactory() }
filter={ filterFactory() }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);
@@ -0,0 +1,151 @@
/* eslint react/no-multi-comp: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import paginationFactory from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'price',
text: 'Product Price',
filter: textFilter()
}];
const sourceCode1 = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
class Case1 extends React.Component {
constructor(props) {
super(props);
this.state = { rowCount: products.length };
}
handleDataChange = ({ dataSize }) => {
this.setState({ rowCount: dataSize });
}
render() {
return (
<div>
<h5>Row Count:<span className="badge">{ this.state.rowCount }</span></h5>
<BootstrapTable
onDataSizeChange={ this.handleDataChange }
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);
}
`;
const sourceCode2 = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
import paginationFactory from 'react-bootstrap-table2-paginator';
class Case2 extends React.Component {
constructor(props) {
super(props);
this.state = { rowCount: products.length };
}
handleDataChange = ({ dataSize }) => {
this.setState({ rowCount: dataSize });
}
render() {
return (
<div>
<h5>Row Count:<span className="badge">{ this.state.rowCount }</span></h5>
<BootstrapTable
onDataSizeChange={ this.handleDataChange }
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
pagination={ paginationFactory() }
/>
<Code>{ sourceCode }</Code>
</div>
);
}
`;
const products1 = productsGenerator(8);
class WithoutPaginationCase extends React.Component {
constructor(props) {
super(props);
this.state = { rowCount: products1.length };
}
handleDataChange = ({ dataSize }) => {
this.setState({ rowCount: dataSize });
}
render() {
return (
<div>
<h3>Without Pagination Case</h3>
<h5>Row Count:<span className="badge">{ this.state.rowCount }</span></h5>
<BootstrapTable
onDataSizeChange={ this.handleDataChange }
keyField="id"
data={ products1 }
columns={ columns }
filter={ filterFactory() }
/>
<Code>{ sourceCode2 }</Code>
</div>
);
}
}
const products2 = productsGenerator(88);
class WithPaginationCase extends React.Component {
constructor(props) {
super(props);
this.state = { rowCount: products2.length };
}
handleDataChange = ({ dataSize }) => {
this.setState({ rowCount: dataSize });
}
render() {
return (
<div>
<h3>Without Pagination Case</h3>
<h5>Row Count:<span className="badge">{ this.state.rowCount }</span></h5>
<BootstrapTable
onDataSizeChange={ this.handleDataChange }
keyField="id"
data={ products2 }
columns={ columns }
filter={ filterFactory() }
pagination={ paginationFactory() }
/>
<Code>{ sourceCode1 }</Code>
</div>
);
}
}
export default () => (
<div>
<WithoutPaginationCase />
<WithPaginationCase />
</div>
);
@@ -7,7 +7,7 @@ import ToolkitProvider, { Search } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { productsGenerator } from 'utils/common';
const products = productsGenerator(21); const products = productsGenerator(40);
const { SearchBar } = Search; const { SearchBar } = Search;
const columns = [{ const columns = [{
@@ -24,61 +24,12 @@ import paginationFactory, { PaginationProvider, PaginationListStandalone } from
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter } from 'react-bootstrap-table2-filter';
class Table extends React.Component { class Table extends React.Component {
render() { state = { products }
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<PaginationListStandalone { ...paginationProps } />
<div>
<div>
<BootstrapTable
striped
hover
keyField="id"
data={ products }
columns={ columns }
filter={ filterFactory() }
cellEdit={ cellEditFactory() }
{ ...paginationTableProps }
/>
</div>
</div>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return ( loadData = () => {
<div> this.setState({ products: productsGenerator(17) });
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
} }
}
`;
export default class Table extends React.Component {
render() { render() {
const options = { const options = {
custom: true, custom: true,
@@ -93,15 +44,84 @@ export default class Table extends React.Component {
firstPageTitle: 'Next page', firstPageTitle: 'Next page',
lastPageTitle: 'Last page', lastPageTitle: 'Last page',
showTotal: true, showTotal: true,
totalSize: products.length totalSize: this.state.products.length
}; };
const contentTable = ({ paginationProps, paginationTableProps }) => ( const contentTable = ({ paginationProps, paginationTableProps }) => (
<div> <div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } /> <PaginationListStandalone { ...paginationProps } />
<ToolkitProvider <ToolkitProvider
keyField="id" keyField="id"
columns={ columns } columns={ columns }
data={ products } data={ this.state.products }
search
>
{
toolkitprops => (
<div>
<SearchBar { ...toolkitprops.searchProps } />
<BootstrapTable
striped
hover
{ ...toolkitprops.baseProps }
{ ...paginationTableProps }
/>
</div>
)
}
</ToolkitProvider>
<PaginationListStandalone { ...paginationProps } />
</div>
);
return (
<div>
<h2>PaginationProvider will care the data size change. You dont do anything</h2>
<PaginationProvider
pagination={
paginationFactory(options)
}
>
{ contentTable }
</PaginationProvider>
<Code>{ sourceCode }</Code>
</div >
);
}
}
`;
export default class Table extends React.Component {
state = { products }
loadData = () => {
this.setState({ products: productsGenerator(17) });
}
render() {
const options = {
custom: true,
paginationSize: 4,
pageStartIndex: 1,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
showTotal: true,
totalSize: this.state.products.length
};
const contentTable = ({ paginationProps, paginationTableProps }) => (
<div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } />
<ToolkitProvider
keyField="id"
columns={ columns }
data={ this.state.products }
search search
> >
{ {
@@ -3,28 +3,70 @@ import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator'; import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, selectFilter } from 'react-bootstrap-table2-filter';
import Code from 'components/common/code-block'; import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common'; import { productsQualityGenerator } from 'utils/common';
const products = productsGenerator(21); const products = productsQualityGenerator(21);
const selectOptions = {
0: 'good',
1: 'Bad',
2: 'unknown'
};
const columns = [{ const columns = [{
dataField: 'id', dataField: 'id',
text: 'Product ID', text: 'Product ID'
filter: textFilter({})
}, { }, {
dataField: 'name', dataField: 'name',
text: 'Product Name', text: 'Product Name',
filter: textFilter() filter: textFilter()
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions[cell],
filter: selectFilter({
options: selectOptions,
defaultValue: 0
})
}]; }];
const sourceCode = `\ const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next'; import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator'; import paginationFactory, { PaginationProvider, PaginationListStandalone } from 'react-bootstrap-table2-paginator';
import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import filterFactory, { textFilter, selectFilter } from 'react-bootstrap-table2-filter';
const selectOptions = {
0: 'good',
1: 'Bad',
2: 'unknown'
};
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name',
filter: textFilter()
}, {
dataField: 'quality',
text: 'Product Quailty',
formatter: cell => selectOptions[cell],
filter: selectFilter({
options: selectOptions,
defaultValue: 0
})
}];
class Table extends React.Component { class Table extends React.Component {
state = { products }
loadData = () => {
this.setState({ products: productsQualityGenerator(40, 7) });
}
render() { render() {
const options = { const options = {
custom: true, custom: true,
@@ -39,10 +81,11 @@ class Table extends React.Component {
firstPageTitle: 'Next page', firstPageTitle: 'Next page',
lastPageTitle: 'Last page', lastPageTitle: 'Last page',
showTotal: true, showTotal: true,
totalSize: products.length totalSize: this.state.products.length
}; };
const contentTable = ({ paginationProps, paginationTableProps }) => ( const contentTable = ({ paginationProps, paginationTableProps }) => (
<div> <div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } /> <PaginationListStandalone { ...paginationProps } />
<div> <div>
<div> <div>
@@ -50,10 +93,9 @@ class Table extends React.Component {
striped striped
hover hover
keyField="id" keyField="id"
data={ products } data={ this.state.products }
columns={ columns } columns={ columns }
filter={ filterFactory() } filter={ filterFactory() }
cellEdit={ cellEditFactory() }
{ ...paginationTableProps } { ...paginationTableProps }
/> />
</div> </div>
@@ -72,7 +114,6 @@ class Table extends React.Component {
> >
{ contentTable } { contentTable }
</PaginationProvider> </PaginationProvider>
<Code>{ sourceCode }</Code>
</div > </div >
); );
} }
@@ -80,6 +121,12 @@ class Table extends React.Component {
`; `;
export default class Table extends React.Component { export default class Table extends React.Component {
state = { products }
loadData = () => {
this.setState({ products: productsQualityGenerator(40, 7) });
}
render() { render() {
const options = { const options = {
custom: true, custom: true,
@@ -94,10 +141,11 @@ export default class Table extends React.Component {
firstPageTitle: 'Next page', firstPageTitle: 'Next page',
lastPageTitle: 'Last page', lastPageTitle: 'Last page',
showTotal: true, showTotal: true,
totalSize: products.length totalSize: this.state.products.length
}; };
const contentTable = ({ paginationProps, paginationTableProps }) => ( const contentTable = ({ paginationProps, paginationTableProps }) => (
<div> <div>
<button className="btn btn-default" onClick={ this.loadData }>Load Another Data</button>
<PaginationListStandalone { ...paginationProps } /> <PaginationListStandalone { ...paginationProps } />
<div> <div>
<div> <div>
@@ -105,7 +153,7 @@ export default class Table extends React.Component {
striped striped
hover hover
keyField="id" keyField="id"
data={ products } data={ this.state.products }
columns={ columns } columns={ columns }
filter={ filterFactory() } filter={ filterFactory() }
{ ...paginationTableProps } { ...paginationTableProps }
@@ -0,0 +1,150 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
import Code from 'components/common/code-block';
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
class BookList extends React.Component {
state = {
books: [
{ id: '1', name: 'Book 1' },
{ id: '2', name: 'Book 2' },
{ id: '3', name: 'Book 3' },
{ id: '4', name: 'Book 4' },
{ id: '5', name: 'Book 5' },
{ id: '6', name: 'Book 6' }
]
};
deleteBookWithId = () => {
const lastOneId = this.state.books.length;
const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString());
this.setState({ books: updatedBooks });
};
addBook = () => {
const lastOneId = this.state.books.length + 1;
this.setState({ books: [...this.state.books, {
id: \`$\{lastOneId}\`, name: \`Book $\{lastOneId}\`
}] });
}
render() {
const options = {
// pageStartIndex: 0,
sizePerPage: 5,
hideSizePerPage: true,
hidePageListOnlyOnePage: true
};
const columns = [
{
dataField: 'id',
text: 'Product ID',
Cell: row => (
<div>
<span title={ row.value }>{ row.value }</span>
</div>
)
},
{
dataField: 'name',
text: 'Product Name'
}
];
return (
<React.Fragment>
<BootstrapTable
keyField="id"
data={ this.state.books }
columns={ columns }
pagination={ paginationFactory(options) }
/>
<button className="btn btn-default" onClick={ () => this.deleteBookWithId() }>
delete last one book
</button>
<button className="btn btn-default" onClick={ () => this.addBook() }>
Add a book to the end
</button>
<Code>{ sourceCode }</Code>
</React.Fragment>
);
}
`;
export default class BookList extends React.Component {
state = {
books: [
{ id: '1', name: 'Book 1' },
{ id: '2', name: 'Book 2' },
{ id: '3', name: 'Book 3' },
{ id: '4', name: 'Book 4' },
{ id: '5', name: 'Book 5' },
{ id: '6', name: 'Book 6' },
{ id: '7', name: 'Book 6' },
{ id: '8', name: 'Book 6' },
{ id: '9', name: 'Book 6' },
{ id: '10', name: 'Book 6' },
{ id: '11', name: 'Book 6' }
]
};
deleteBookWithId = () => {
const lastOneId = this.state.books.length;
const updatedBooks = this.state.books.filter(m => m.id !== lastOneId.toString());
this.setState({ books: updatedBooks });
};
addBook = () => {
const lastOneId = this.state.books.length + 1;
this.setState({ books: [...this.state.books, {
id: `${lastOneId}`, name: `Book ${lastOneId}`
}] });
}
render() {
const options = {
// pageStartIndex: 0,
sizePerPage: 5,
hideSizePerPage: true,
hidePageListOnlyOnePage: true
};
const columns = [
{
dataField: 'id',
text: 'Product ID',
Cell: row => (
<div>
<span title={ row.value }>{ row.value }</span>
</div>
)
},
{
dataField: 'name',
text: 'Product Name'
}
];
return (
<React.Fragment>
<BootstrapTable
keyField="id"
data={ this.state.books }
columns={ columns }
pagination={ paginationFactory(options) }
/>
<button className="btn btn-default" onClick={ () => this.deleteBookWithId() }>
delete last one book
</button>
<button className="btn btn-default" onClick={ () => this.addBook() }>
Add a book to the end
</button>
<Code>{ sourceCode }</Code>
</React.Fragment>
);
}
}
@@ -84,6 +84,7 @@ export default class StandaloneSizePerPage extends React.Component {
<div> <div>
<SizePerPageDropdownStandalone <SizePerPageDropdownStandalone
{ ...paginationProps } { ...paginationProps }
btnContextual="btn btn-primary"
/> />
<BootstrapTable <BootstrapTable
keyField="id" keyField="id"
@@ -43,6 +43,7 @@ const columns = [{
}]; }];
const expandRow = { const expandRow = {
onlyOneExpanding: true,
renderer: row => ( renderer: row => (
<div> <div>
<p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p> <p>{ \`This Expand row is belong to rowKey $\{row.id}\` }</p>
@@ -0,0 +1,111 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(2);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow1 = {
mode: 'checkbox',
clickToSelect: true,
headerColumnStyle: {
backgroundColor: 'blue'
}
};
const sourceCode1 = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = ...
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
headerColumnStyle: {
backgroundColor: 'blue'
}
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
const selectRow2 = {
mode: 'checkbox',
clickToSelect: true,
headerColumnStyle: (status) => {
if (status === 'checked') {
return {
backgroundColor: 'yellow'
};
} else if (status === 'indeterminate') {
return {
backgroundColor: 'pink'
};
} else if (status === 'unchecked') {
return {
backgroundColor: 'grey'
};
}
return {};
}
};
const sourceCode2 = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = ...
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
headerColumnStyle: (status) => {
if (status === 'checked') {
return {
backgroundColor: 'yellow'
};
} else if (status === 'indeterminate') {
return {
backgroundColor: 'pink'
};
} else if (status === 'unchecked') {
return {
backgroundColor: 'grey'
};
}
return {};
}
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow2 } />
<Code>{ sourceCode2 }</Code>
</div>
);
@@ -0,0 +1,110 @@
/* eslint no-unused-vars: 0 */
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator(2);
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow1 = {
mode: 'checkbox',
clickToSelect: true,
selectColumnStyle: {
backgroundColor: 'grey'
}
};
const sourceCode1 = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = ...
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
selectColumnStyle: {
backgroundColor: 'grey'
}
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
const selectRow2 = {
mode: 'checkbox',
clickToSelect: true,
selectColumnStyle: ({
checked,
disabled,
rowIndex,
rowKey
}) => {
if (checked) {
return {
backgroundColor: 'yellow'
};
}
return {
backgroundColor: 'pink'
};
}
};
const sourceCode2 = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = ...
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
selectColumnStyle: ({
checked,
disabled,
rowIndex,
rowKey
}) => {
if (checked) {
return {
backgroundColor: 'yellow'
};
}
return {
backgroundColor: 'pink'
};
}
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow1 } />
<Code>{ sourceCode1 }</Code>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow2 } />
<Code>{ sourceCode2 }</Code>
</div>
);
@@ -0,0 +1,59 @@
import React from 'react';
import BootstrapTable from 'react-bootstrap-table-next';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';
const products = productsGenerator();
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
selectColumnPosition: 'right'
};
const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price'
}];
const selectRow = {
mode: 'checkbox',
clickToSelect: true,
selectColumnPosition: 'right'
};
<BootstrapTable
keyField='id'
data={ products }
columns={ columns }
selectRow={ selectRow }
/>
`;
export default () => (
<div>
<BootstrapTable keyField="id" data={ products } columns={ columns } selectRow={ selectRow } />
<Code>{ sourceCode }</Code>
</div>
);
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-example", "name": "react-bootstrap-table2-example",
"version": "1.0.19", "version": "1.0.26",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"private": true, "private": true,
@@ -29,10 +29,10 @@ export const withOnSale = rows => rows.map((row) => {
return row; return row;
}); });
export const productsQualityGenerator = (quantity = 5) => export const productsQualityGenerator = (quantity = 5, factor = 0) =>
Array.from({ length: quantity }, (value, index) => ({ Array.from({ length: quantity }, (value, index) => ({
id: index, id: index + factor,
name: `Item name ${index}`, name: `Item name ${index + factor}`,
quality: index % 3 quality: index % 3
})); }));
+19 -2
View File
@@ -35,6 +35,7 @@ import ColumnEventTable from 'examples/columns/column-event-table';
import ColumnHiddenTable from 'examples/columns/column-hidden-table'; import ColumnHiddenTable from 'examples/columns/column-hidden-table';
import ColumnAttrsTable from 'examples/columns/column-attrs-table'; import ColumnAttrsTable from 'examples/columns/column-attrs-table';
import DummyColumnTable from 'examples/columns/dummy-column-table'; import DummyColumnTable from 'examples/columns/dummy-column-table';
import RowExpandWithFormattedDummyColumn from 'examples/columns/row-expand-with-formatted-dummy-column.js';
// work on header columns // work on header columns
import HeaderColumnFormatTable from 'examples/header-columns/column-format-table'; import HeaderColumnFormatTable from 'examples/header-columns/column-format-table';
@@ -125,6 +126,7 @@ import EditorStyleTable from 'examples/cell-edit/editor-style-table';
import EditorClassTable from 'examples/cell-edit/editor-class-table'; import EditorClassTable from 'examples/cell-edit/editor-class-table';
import DBClickEditWithSelection from 'examples/cell-edit/dbclick-to-edit-with-selection-table'; import DBClickEditWithSelection from 'examples/cell-edit/dbclick-to-edit-with-selection-table';
import DropdownEditorTable from 'examples/cell-edit/dropdown-editor-table'; import DropdownEditorTable from 'examples/cell-edit/dropdown-editor-table';
import DropdownEditorWithDynamicOptionsTable from 'examples/cell-edit/dropdown-editor-with-dynamic-options-table';
import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table'; import TextareaEditorTable from 'examples/cell-edit/textarea-editor-table';
import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table'; import CheckboxEditorTable from 'examples/cell-edit/checkbox-editor-table';
import DateEditorTable from 'examples/cell-edit/date-editor-table'; import DateEditorTable from 'examples/cell-edit/date-editor-table';
@@ -142,12 +144,15 @@ import SelectionWithExpansionTable from 'examples/row-selection/selection-with-e
import SelectionNoDataTable from 'examples/row-selection/selection-no-data'; import SelectionNoDataTable from 'examples/row-selection/selection-no-data';
import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionStyleTable from 'examples/row-selection/selection-style';
import SelectionClassTable from 'examples/row-selection/selection-class'; import SelectionClassTable from 'examples/row-selection/selection-class';
import HeaderStyleTable from 'examples/row-selection/header-style';
import HideSelectAllTable from 'examples/row-selection/hide-select-all'; import HideSelectAllTable from 'examples/row-selection/hide-select-all';
import CustomSelectionTable from 'examples/row-selection/custom-selection'; import CustomSelectionTable from 'examples/row-selection/custom-selection';
import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows';
import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor'; import SelectionBgColorTable from 'examples/row-selection/selection-bgcolor';
import SelectionHooks from 'examples/row-selection/selection-hooks'; import SelectionHooks from 'examples/row-selection/selection-hooks';
import HideSelectionColumnTable from 'examples/row-selection/hide-selection-column'; import HideSelectionColumnTable from 'examples/row-selection/hide-selection-column';
import SelectionColumnStyleTable from 'examples/row-selection/select-column-style';
import SelectionColumnPositionTable from 'examples/row-selection/selection-column-position';
// work on row expand // work on row expand
import BasicRowExpand from 'examples/row-expand'; import BasicRowExpand from 'examples/row-expand';
@@ -163,6 +168,7 @@ import ExpandHooks from 'examples/row-expand/expand-hooks';
// pagination // pagination
import PaginationTable from 'examples/pagination'; import PaginationTable from 'examples/pagination';
import PaginationHooksTable from 'examples/pagination/pagination-hooks'; import PaginationHooksTable from 'examples/pagination/pagination-hooks';
import PaginationWithDynamicData from 'examples/pagination/pagination-with-dynamic-data';
import CustomPaginationTable from 'examples/pagination/custom-pagination'; import CustomPaginationTable from 'examples/pagination/custom-pagination';
import CustomPageButtonTable from 'examples/pagination/custom-page-button'; import CustomPageButtonTable from 'examples/pagination/custom-page-button';
import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option'; import CustomSizePerPageOptionTable from 'examples/pagination/custom-size-per-page-option';
@@ -191,6 +197,7 @@ import CSVFormatter from 'examples/csv/csv-column-formatter';
import CustomCSVHeader from 'examples/csv/custom-csv-header'; import CustomCSVHeader from 'examples/csv/custom-csv-header';
import HideCSVColumn from 'examples/csv/hide-column'; import HideCSVColumn from 'examples/csv/hide-column';
import ExportOnlySelected from 'examples/csv/export-only-selected'; import ExportOnlySelected from 'examples/csv/export-only-selected';
import ExportOnlyFiltered from 'examples/csv/export-only-filtered';
import CSVColumnType from 'examples/csv/csv-column-type'; import CSVColumnType from 'examples/csv/csv-column-type';
import CustomCSVButton from 'examples/csv/custom-csv-button'; import CustomCSVButton from 'examples/csv/custom-csv-button';
import ExportCustomData from 'examples/csv/export-custom-data'; import ExportCustomData from 'examples/csv/export-custom-data';
@@ -215,6 +222,7 @@ import RemoteCellEdit from 'examples/remote/remote-celledit';
import RemoteAll from 'examples/remote/remote-all'; import RemoteAll from 'examples/remote/remote-all';
// data // data
import DataChangeListener from 'examples/data/data-change-listener';
import LoadDataWithFilter from 'examples/data/load-data-on-the-fly-with-filter'; import LoadDataWithFilter from 'examples/data/load-data-on-the-fly-with-filter';
import LoadDataWithDefaultFilter from 'examples/data/load-data-on-the-fly-with-default-filter'; import LoadDataWithDefaultFilter from 'examples/data/load-data-on-the-fly-with-default-filter';
import LoadDataWithSearch from 'examples/data/load-data-on-the-fly-with-search'; import LoadDataWithSearch from 'examples/data/load-data-on-the-fly-with-search';
@@ -227,6 +235,7 @@ import 'stories/stylesheet/storybook.scss';
import '../../react-bootstrap-table2/style/react-bootstrap-table2.scss'; import '../../react-bootstrap-table2/style/react-bootstrap-table2.scss';
import '../../react-bootstrap-table2-paginator/style/react-bootstrap-table2-paginator.scss'; import '../../react-bootstrap-table2-paginator/style/react-bootstrap-table2-paginator.scss';
import '../../react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss'; import '../../react-bootstrap-table2-filter/style/react-bootstrap-table2-filter.scss';
import '../../react-bootstrap-table2-toolkit/style/react-bootstrap-table2-toolkit.scss';
// import bootstrap style by given version // import bootstrap style by given version
import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style'; import bootstrapStyle, { BOOTSTRAP_VERSION } from './bootstrap-style';
@@ -265,7 +274,8 @@ storiesOf('Work on Columns', module)
.add('Customize Column Class', () => <ColumnClassTable />) .add('Customize Column Class', () => <ColumnClassTable />)
.add('Customize Column Style', () => <ColumnStyleTable />) .add('Customize Column Style', () => <ColumnStyleTable />)
.add('Customize Column HTML attribute', () => <ColumnAttrsTable />) .add('Customize Column HTML attribute', () => <ColumnAttrsTable />)
.add('Dummy Column', () => <DummyColumnTable />); .add('Dummy Column', () => <DummyColumnTable />)
.add('Row Expand with Dummy Column Formatter', () => <RowExpandWithFormattedDummyColumn />);
storiesOf('Work on Header Columns', module) storiesOf('Work on Header Columns', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
@@ -363,6 +373,7 @@ storiesOf('Cell Editing', module)
.add('Custom Editor Style', () => <EditorStyleTable />) .add('Custom Editor Style', () => <EditorStyleTable />)
.add('DoubleClick to Edit with Selection', () => <DBClickEditWithSelection />) .add('DoubleClick to Edit with Selection', () => <DBClickEditWithSelection />)
.add('Dropdown Editor', () => <DropdownEditorTable />) .add('Dropdown Editor', () => <DropdownEditorTable />)
.add('Dropdown Editor with Dynamic Options', () => <DropdownEditorWithDynamicOptionsTable />)
.add('Textarea Editor', () => <TextareaEditorTable />) .add('Textarea Editor', () => <TextareaEditorTable />)
.add('Checkbox Editor', () => <CheckboxEditorTable />) .add('Checkbox Editor', () => <CheckboxEditorTable />)
.add('Date Editor', () => <DateEditorTable />) .add('Date Editor', () => <DateEditorTable />)
@@ -381,12 +392,15 @@ storiesOf('Row Selection', module)
.add('Selection without Data', () => <SelectionNoDataTable />) .add('Selection without Data', () => <SelectionNoDataTable />)
.add('Selection Style', () => <SelectionStyleTable />) .add('Selection Style', () => <SelectionStyleTable />)
.add('Selection Class', () => <SelectionClassTable />) .add('Selection Class', () => <SelectionClassTable />)
.add('Custom Selection Column Header Style', () => <HeaderStyleTable />)
.add('Hide Select All', () => <HideSelectAllTable />) .add('Hide Select All', () => <HideSelectAllTable />)
.add('Custom Selection', () => <CustomSelectionTable />) .add('Custom Selection', () => <CustomSelectionTable />)
.add('Selection Background Color', () => <SelectionBgColorTable />) .add('Selection Background Color', () => <SelectionBgColorTable />)
.add('Not Selectabled Rows', () => <NonSelectableRowsTable />) .add('Not Selectabled Rows', () => <NonSelectableRowsTable />)
.add('Selection Hooks', () => <SelectionHooks />) .add('Selection Hooks', () => <SelectionHooks />)
.add('Hide Selection Column', () => <HideSelectionColumnTable />); .add('Hide Selection Column', () => <HideSelectionColumnTable />)
.add('Custom Selection Column Style', () => <SelectionColumnStyleTable />)
.add('Selection Column Position', () => <SelectionColumnPositionTable />);
storiesOf('Row Expand', module) storiesOf('Row Expand', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
@@ -404,6 +418,7 @@ storiesOf('Pagination', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Basic Pagination Table', () => <PaginationTable />) .add('Basic Pagination Table', () => <PaginationTable />)
.add('Pagination Hooks', () => <PaginationHooksTable />) .add('Pagination Hooks', () => <PaginationHooksTable />)
.add('Pagination with Dynamic Data', () => <PaginationWithDynamicData />)
.add('Custom Pagination', () => <CustomPaginationTable />) .add('Custom Pagination', () => <CustomPaginationTable />)
.add('Custom Page Button', () => <CustomPageButtonTable />) .add('Custom Page Button', () => <CustomPageButtonTable />)
.add('Custom Page List', () => <CustomPageListTable />) .add('Custom Page List', () => <CustomPageListTable />)
@@ -441,6 +456,7 @@ storiesOf('Export CSV', module)
.add('Custom CSV Header', () => <CustomCSVHeader />) .add('Custom CSV Header', () => <CustomCSVHeader />)
.add('Hide CSV Column', () => <HideCSVColumn />) .add('Hide CSV Column', () => <HideCSVColumn />)
.add('Only Export Selected Rows', () => <ExportOnlySelected />) .add('Only Export Selected Rows', () => <ExportOnlySelected />)
.add('Only Export Filtered/Searched Rows', () => <ExportOnlyFiltered />)
.add('CSV Column Type', () => <CSVColumnType />) .add('CSV Column Type', () => <CSVColumnType />)
.add('Custom CSV Button', () => <CustomCSVButton />) .add('Custom CSV Button', () => <CustomCSVButton />)
.add('Export Custom Data', () => <ExportCustomData />) .add('Export Custom Data', () => <ExportCustomData />)
@@ -462,6 +478,7 @@ storiesOf('Remote', module)
storiesOf('Data', module) storiesOf('Data', module)
.addDecorator(bootstrapStyle()) .addDecorator(bootstrapStyle())
.add('Data Change Listener', () => <DataChangeListener />)
.add('Load data with Filter', () => <LoadDataWithFilter />) .add('Load data with Filter', () => <LoadDataWithFilter />)
.add('Load data with Default Filter', () => <LoadDataWithDefaultFilter />) .add('Load data with Default Filter', () => <LoadDataWithDefaultFilter />)
.add('Load data with Search', () => <LoadDataWithSearch />) .add('Load data with Search', () => <LoadDataWithSearch />)
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-filter", "name": "react-bootstrap-table2-filter",
"version": "1.1.5", "version": "1.1.9",
"description": "it's a column filter addon for react-bootstrap-table2", "description": "it's a column filter addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
+29 -18
View File
@@ -18,7 +18,7 @@ const legalComparators = [
]; ];
function dateParser(d) { function dateParser(d) {
return `${d.getFullYear()}-${('0' + (d.getMonth() + 1)).slice(-2)}-${('0' + d.getDate()).slice(-2)}`; return `${d.getUTCFullYear()}-${('0' + (d.getUTCMonth() + 1)).slice(-2)}-${('0' + d.getUTCDate()).slice(-2)}`;
} }
class DateFilter extends Component { class DateFilter extends Component {
@@ -132,24 +132,35 @@ class DateFilter extends Component {
className={ `filter date-filter ${className}` } className={ `filter date-filter ${className}` }
style={ style } style={ style }
> >
<select <label
ref={ n => this.dateFilterComparator = n } className="filter-label"
style={ comparatorStyle } htmlFor={ `date-filter-comparator-${text}` }
className={ `date-filter-comparator form-control ${comparatorClassName}` }
onChange={ this.onChangeComparator }
defaultValue={ defaultValue ? defaultValue.comparator : '' }
> >
{ this.getComparatorOptions() } <span className="sr-only">Filter comparator</span>
</select> <select
<input ref={ n => this.dateFilterComparator = n }
ref={ n => this.inputDate = n } id={ `date-filter-comparator-${text}` }
className={ `filter date-filter-input form-control ${dateClassName}` } style={ comparatorStyle }
style={ dateStyle } className={ `date-filter-comparator form-control ${comparatorClassName}` }
type="date" onChange={ this.onChangeComparator }
onChange={ this.onChangeDate } defaultValue={ defaultValue ? defaultValue.comparator : '' }
placeholder={ placeholder || `Enter ${text}...` } >
defaultValue={ this.getDefaultDate() } { this.getComparatorOptions() }
/> </select>
</label>
<label htmlFor={ `date-filter-column-${text}` }>
<span className="sr-only">Enter ${ text }</span>
<input
ref={ n => this.inputDate = n }
id={ `date-filter-column-${text}` }
className={ `filter date-filter-input form-control ${dateClassName}` }
style={ dateStyle }
type="date"
onChange={ this.onChangeDate }
placeholder={ placeholder || `Enter ${text}...` }
defaultValue={ this.getDefaultDate() }
/>
</label>
</div> </div>
); );
} }
@@ -111,18 +111,25 @@ class MultiSelectFilter extends Component {
`filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`; `filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`;
return ( return (
<select <label
{ ...rest } className="filter-label"
ref={ n => this.selectInput = n } htmlFor={ `multiselect-filter-column-${column.text}` }
style={ style }
multiple
className={ selectClass }
onChange={ this.filter }
onClick={ e => e.stopPropagation() }
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
> >
{ this.getOptions() } <span className="sr-only">Filter by {column.text}</span>
</select> <select
{ ...rest }
ref={ n => this.selectInput = n }
id={ `multiselect-filter-column-${column.text}` }
style={ style }
multiple
className={ selectClass }
onChange={ this.filter }
onClick={ e => e.stopPropagation() }
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
>
{ this.getOptions() }
</select>
</label>
); );
} }
} }
@@ -173,35 +173,53 @@ class NumberFilter extends Component {
className={ `filter number-filter ${className}` } className={ `filter number-filter ${className}` }
style={ style } style={ style }
> >
<select <label
ref={ n => this.numberFilterComparator = n } className="filter-label"
style={ comparatorStyle } htmlFor={ `number-filter-comparator-${column.text}` }
className={ `number-filter-comparator form-control ${comparatorClassName}` }
onChange={ this.onChangeComparator }
defaultValue={ defaultValue ? defaultValue.comparator : '' }
> >
{ this.getComparatorOptions() } <span className="sr-only">Filter comparator</span>
</select> <select
ref={ n => this.numberFilterComparator = n }
style={ comparatorStyle }
id={ `number-filter-comparator-${column.text}` }
className={ `number-filter-comparator form-control ${comparatorClassName}` }
onChange={ this.onChangeComparator }
defaultValue={ defaultValue ? defaultValue.comparator : '' }
>
{ this.getComparatorOptions() }
</select>
</label>
{ {
options ? options ?
<select <label
ref={ n => this.numberFilter = n } className="filter-label"
style={ numberStyle } htmlFor={ `number-filter-column-${column.text}` }
className={ selectClass }
onChange={ this.onChangeNumberSet }
defaultValue={ defaultValue ? defaultValue.number : '' }
> >
{ this.getNumberOptions() } <span className="sr-only">{`Select ${column.text}`}</span>
</select> : <select
<input ref={ n => this.numberFilter = n }
ref={ n => this.numberFilter = n } id={ `number-filter-column-${column.text}` }
type="number" style={ numberStyle }
style={ numberStyle } className={ selectClass }
className={ `number-filter-input form-control ${numberClassName}` } onChange={ this.onChangeNumberSet }
placeholder={ placeholder || `Enter ${column.text}...` } defaultValue={ defaultValue ? defaultValue.number : '' }
onChange={ this.onChangeNumber } >
defaultValue={ defaultValue ? defaultValue.number : '' } { this.getNumberOptions() }
/> </select>
</label> :
<label htmlFor={ `number-filter-column-${column.text}` }>
<span className="sr-only">{`Enter ${column.text}`}</span>
<input
ref={ n => this.numberFilter = n }
id={ `number-filter-column-${column.text}` }
type="number"
style={ numberStyle }
className={ `number-filter-input form-control ${numberClassName}` }
placeholder={ placeholder || `Enter ${column.text}...` }
onChange={ this.onChangeNumber }
defaultValue={ defaultValue ? defaultValue.number : '' }
/>
</label>
} }
</div> </div>
); );
@@ -8,15 +8,18 @@ import { FILTER_TYPE } from '../const';
function optionsEquals(currOpts, prevOpts) { function optionsEquals(currOpts, prevOpts) {
if (Array.isArray(currOpts)) { if (Array.isArray(currOpts)) {
for (let i = 0; i < currOpts.length; i += 1) { if (currOpts.length === prevOpts.length) {
if ( for (let i = 0; i < currOpts.length; i += 1) {
currOpts[i].value !== prevOpts[i].value || if (
currOpts[i].label !== prevOpts[i].label currOpts[i].value !== prevOpts[i].value ||
) { currOpts[i].label !== prevOpts[i].label
return false; ) {
return false;
}
} }
return true;
} }
return currOpts.length === prevOpts.length; return false;
} }
const keys = Object.keys(currOpts); const keys = Object.keys(currOpts);
for (let i = 0; i < keys.length; i += 1) { for (let i = 0; i < keys.length; i += 1) {
@@ -136,17 +139,24 @@ class SelectFilter extends Component {
`filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`; `filter select-filter form-control ${className} ${this.state.isSelected ? '' : 'placeholder-selected'}`;
return ( return (
<select <label
{ ...rest } className="filter-label"
ref={ n => this.selectInput = n } htmlFor={ `select-filter-column-${column.text}` }
style={ style }
className={ selectClass }
onChange={ this.filter }
onClick={ e => e.stopPropagation() }
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
> >
{ this.getOptions() } <span className="sr-only">Filter by { column.text }</span>
</select> <select
{ ...rest }
ref={ n => this.selectInput = n }
id={ `select-filter-column-${column.text}` }
style={ style }
className={ selectClass }
onChange={ this.filter }
onClick={ e => e.stopPropagation() }
defaultValue={ defaultValue !== undefined ? defaultValue : '' }
>
{ this.getOptions() }
</select>
</label>
); );
} }
} }
+18 -11
View File
@@ -94,17 +94,24 @@ class TextFilter extends Component {
// stopPropagation for onClick event is try to prevent sort was triggered. // stopPropagation for onClick event is try to prevent sort was triggered.
return ( return (
<input <label
{ ...rest } className="filter-label"
ref={ n => this.input = n } htmlFor={ `text-filter-column-${text}` }
type="text" >
className={ `filter text-filter form-control ${className}` } <span className="sr-only">Filter by {text}</span>
style={ style } <input
onChange={ this.filter } { ...rest }
onClick={ this.handleClick } ref={ n => this.input = n }
placeholder={ placeholder || `Enter ${text}...` } type="text"
value={ this.state.value } id={ `text-filter-column-${text}` }
/> className={ `filter text-filter form-control ${className}` }
style={ style }
onChange={ this.filter }
onClick={ this.handleClick }
placeholder={ placeholder || `Enter ${text}...` }
value={ this.state.value }
/>
</label>
); );
} }
} }
+20 -16
View File
@@ -27,9 +27,8 @@ export default (
this.onFilter = this.onFilter.bind(this); this.onFilter = this.onFilter.bind(this);
this.doFilter = this.doFilter.bind(this); this.doFilter = this.doFilter.bind(this);
this.onExternalFilter = this.onExternalFilter.bind(this); this.onExternalFilter = this.onExternalFilter.bind(this);
this.state = { this.data = props.data;
data: props.data this.isEmitDataChange = false;
};
} }
componentDidMount() { componentDidMount() {
@@ -39,13 +38,12 @@ export default (
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
let nextData = nextProps.data; // let nextData = nextProps.data;
if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.state.data)) { if (!isRemoteFiltering() && !_.isEqual(nextProps.data, this.data)) {
nextData = this.doFilter(nextProps); this.doFilter(nextProps, undefined, this.isEmitDataChange);
} else {
this.data = nextProps.data;
} }
this.setState({
data: nextData
});
} }
onFilter(column, filterType, initialize = false) { onFilter(column, filterType, initialize = false) {
@@ -83,9 +81,7 @@ export default (
if (filter.props.onFilter) { if (filter.props.onFilter) {
result = filter.props.onFilter(filterVal); result = filter.props.onFilter(filterVal);
} }
this.doFilter(this.props, result);
result = this.doFilter(this.props, result);
this.setState({ data: result });
}; };
} }
@@ -95,21 +91,29 @@ export default (
}; };
} }
doFilter(props, customResult) { getFiltered() {
return this.data;
}
doFilter(props, customResult, ignoreEmitDataChange = false) {
let result = customResult; let result = customResult;
const { dataChangeListener, data, columns } = props; const { dataChangeListener, data, columns } = props;
result = result || filters(data, columns, _)(this.currFilters); result = result || filters(data, columns, _)(this.currFilters);
if (dataChangeListener) { this.data = result;
if (dataChangeListener && !ignoreEmitDataChange) {
this.isEmitDataChange = true;
dataChangeListener.emit('filterChanged', result.length); dataChangeListener.emit('filterChanged', result.length);
} else {
this.isEmitDataChange = false;
this.forceUpdate();
} }
return result;
} }
render() { render() {
return ( return (
<FilterContext.Provider value={ { <FilterContext.Provider value={ {
data: this.state.data, data: this.data,
onFilter: this.onFilter, onFilter: this.onFilter,
onExternalFilter: this.onExternalFilter onExternalFilter: this.onExternalFilter
} } } }
+6 -6
View File
@@ -98,9 +98,9 @@ export const filterByDate = _ => (
customFilterValue customFilterValue
) => { ) => {
if (!date || !comparator) return data; if (!date || !comparator) return data;
const filterDate = date.getDate(); const filterDate = date.getUTCDate();
const filterMonth = date.getMonth(); const filterMonth = date.getUTCMonth();
const filterYear = date.getFullYear(); const filterYear = date.getUTCFullYear();
return data.filter((row) => { return data.filter((row) => {
let valid = true; let valid = true;
@@ -114,9 +114,9 @@ export const filterByDate = _ => (
cell = new Date(cell); cell = new Date(cell);
} }
const targetDate = cell.getDate(); const targetDate = cell.getUTCDate();
const targetMonth = cell.getMonth(); const targetMonth = cell.getUTCMonth();
const targetYear = cell.getFullYear(); const targetYear = cell.getUTCFullYear();
switch (comparator) { switch (comparator) {
@@ -1,3 +1,7 @@
.react-bootstrap-table > table > thead > tr > th .filter-label {
display: block !important;
}
.react-bootstrap-table > table > thead > tr > th .filter { .react-bootstrap-table > table > thead > tr > th .filter {
font-weight: normal; font-weight: normal;
} }
@@ -283,9 +283,9 @@ describe('FilterContext', () => {
expect(onFilter).toHaveBeenCalledWith(filterVal); expect(onFilter).toHaveBeenCalledWith(filterVal);
}); });
it('should set state.data correctly', () => { it('should set data correctly', () => {
instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal); instance.onFilter(customColumns[1], FILTER_TYPE.TEXT)(filterVal);
expect(instance.state.data).toEqual(mockReturn); expect(instance.data).toEqual(mockReturn);
}); });
}); });
+4 -4
View File
@@ -11,10 +11,10 @@ export default options => loading =>
componentDidMount() { componentDidMount() {
if (loading) { if (loading) {
const { wrapper } = this.overlay; const { wrapper } = this.overlay;
const masker = wrapper.firstChild; const masker = wrapper.current.firstChild;
const headerDOM = wrapper.parentElement.querySelector('thead'); const headerDOM = wrapper.current.parentElement.querySelector('thead');
const bodyDOM = wrapper.parentElement.querySelector('tbody'); const bodyDOM = wrapper.current.parentElement.querySelector('tbody');
const captionDOM = wrapper.parentElement.querySelector('caption'); const captionDOM = wrapper.current.parentElement.querySelector('caption');
let marginTop = window.getComputedStyle(headerDOM).height; let marginTop = window.getComputedStyle(headerDOM).height;
if (captionDOM) { if (captionDOM) {
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-overlay", "name": "react-bootstrap-table2-overlay",
"version": "1.0.0", "version": "2.0.0",
"description": "it's a loading overlay addons for react-bootstrap-table2", "description": "it's a loading overlay addons for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -37,7 +37,7 @@
} }
], ],
"dependencies": { "dependencies": {
"react-loading-overlay": "0.2.8" "react-loading-overlay": "1.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"prop-types": "^15.0.0", "prop-types": "^15.0.0",
+312 -160
View File
@@ -2,199 +2,351 @@
# yarn lockfile v1 # yarn lockfile v1
asap@~2.0.3: "@babel/helper-module-imports@^7.0.0":
version "2.0.6" version "7.0.0"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==
base64-js@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
buffer@^5.0.3:
version "5.0.8"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24"
dependencies: dependencies:
base64-js "^1.0.2" "@babel/types" "^7.0.0"
ieee754 "^1.1.4"
chain-function@^1.0.0: "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2":
version "1.0.0" version "7.4.4"
resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
css-color-keywords@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
css-to-react-native@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.4.tgz#cf4cc407558b3474d4ba8be1a2cd3b6ce713101b"
dependencies: dependencies:
css-color-keywords "^1.0.0" regenerator-runtime "^0.13.2"
fbjs "^0.8.5"
postcss-value-parser "^3.3.0"
dom-helpers@^3.2.0: "@babel/types@^7.0.0":
version "3.2.1" version "7.4.4"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
dependencies: dependencies:
iconv-lite "~0.4.13" esutils "^2.0.2"
lodash "^4.17.11"
to-fast-properties "^2.0.0"
fbjs@^0.8.16, fbjs@^0.8.5, fbjs@^0.8.9: "@emotion/cache@^10.0.9":
version "0.8.16" version "10.0.9"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.9.tgz#e0c7b7a289f7530edcfad4dcf3858bd2e5700a6f"
integrity sha512-f7MblpE2xoimC4fCMZ9pivmsIn7hyWRIvY75owMDi8pdOSeh+w5tH3r4hBJv/LLrwiMM7cTQURqTPcYoL5pWnw==
dependencies: dependencies:
core-js "^1.0.0" "@emotion/sheet" "0.9.2"
isomorphic-fetch "^2.1.1" "@emotion/stylis" "0.8.3"
loose-envify "^1.0.0" "@emotion/utils" "0.11.1"
object-assign "^4.1.0" "@emotion/weak-memoize" "0.2.2"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
has-flag@^1.0.0: "@emotion/hash@0.7.1":
version "1.0.0" version "0.7.1"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.1.tgz#9833722341379fb7d67f06a4b00ab3c37913da53"
integrity sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA==
hoist-non-react-statics@^1.2.0: "@emotion/memoize@0.7.1":
version "1.2.0" version "0.7.1"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.1.tgz#e93c13942592cf5ef01aa8297444dc192beee52f"
integrity sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==
iconv-lite@~0.4.13: "@emotion/serialize@^0.11.6":
version "0.4.19" version "0.11.6"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.6.tgz#78be8b9ee9ff49e0196233ba6ec1c1768ba1e1fc"
integrity sha512-n4zVv2qGLmspF99jaEUwnMV0fnEGsyUMsC/8KZKUSUTZMYljHE+j+B6rSD8PIFtaUIhHaxCG2JawN6L+OgLN0Q==
ieee754@^1.1.4:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
is-function@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
is-plain-object@^2.0.1:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
dependencies: dependencies:
isobject "^3.0.1" "@emotion/hash" "0.7.1"
"@emotion/memoize" "0.7.1"
"@emotion/unitless" "0.7.3"
"@emotion/utils" "0.11.1"
csstype "^2.5.7"
is-stream@^1.0.1: "@emotion/sheet@0.9.2":
version "0.9.2"
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.2.tgz#74e5c6b5e489a1ba30ab246ab5eedd96916487c4"
integrity sha512-pVBLzIbC/QCHDKJF2E82V2H/W/B004mDFQZiyo/MSR+VC4pV5JLG0TF/zgQDFvP3fZL/5RTPGEmXlYJBMUuJ+A==
"@emotion/stylis@0.8.3":
version "0.8.3"
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.3.tgz#3ca7e9bcb31b3cb4afbaeb66156d86ee85e23246"
integrity sha512-M3nMfJ6ndJMYloSIbYEBq6G3eqoYD41BpDOxreE8j0cb4fzz/5qvmqU9Mb2hzsXcCnIlGlWhS03PCzVGvTAe0Q==
"@emotion/unitless@0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.3.tgz#6310a047f12d21a1036fb031317219892440416f"
integrity sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==
"@emotion/utils@0.11.1":
version "0.11.1"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.1.tgz#8529b7412a6eb4b48bdf6e720cc1b8e6e1e17628"
integrity sha512-8M3VN0hetwhsJ8dH8VkVy7xo5/1VoBsDOk/T4SJOeXwTO1c4uIqVNx2qyecLFnnUWD5vvUqHQ1gASSeUN6zcTg==
"@emotion/weak-memoize@0.2.2":
version "0.2.2"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.2.tgz#63985d3d8b02530e0869962f4da09142ee8e200e"
integrity sha512-n/VQ4mbfr81aqkx/XmVicOLjviMuy02eenSdJY33SVA7S2J42EU0P1H0mOogfYedb3wXA0d/LVtBrgTSm04WEA==
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
dependencies:
sprintf-js "~1.0.2"
babel-plugin-emotion@^10.0.9:
version "10.0.9"
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.9.tgz#04a0404d5a4084d5296357a393d344c0f8303ae4"
integrity sha512-IfWP12e9/wHtWHxVTzD692Nbcmrmcz2tip7acp6YUqtrP7slAyr5B+69hyZ8jd55GsyNSZwryNnmuDEVe0j+7w==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@emotion/hash" "0.7.1"
"@emotion/memoize" "0.7.1"
"@emotion/serialize" "^0.11.6"
babel-plugin-macros "^2.0.0"
babel-plugin-syntax-jsx "^6.18.0"
convert-source-map "^1.5.0"
escape-string-regexp "^1.0.5"
find-root "^1.1.0"
source-map "^0.5.7"
babel-plugin-macros@^2.0.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.5.1.tgz#4a119ac2c2e19b458c259b9accd7ee34fd57ec6f"
integrity sha512-xN3KhAxPzsJ6OQTktCanNpIFnnMsCV+t8OloKxIL72D6+SUZYFn9qfklPgef5HyyDtzYZqqb+fs1S12+gQY82Q==
dependencies:
"@babel/runtime" "^7.4.2"
cosmiconfig "^5.2.0"
resolve "^1.10.0"
babel-plugin-syntax-jsx@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
caller-callsite@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
dependencies:
callsites "^2.0.0"
caller-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
dependencies:
caller-callsite "^2.0.0"
callsites@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
convert-source-map@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
dependencies:
safe-buffer "~5.1.1"
cosmiconfig@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
dependencies:
import-fresh "^2.0.0"
is-directory "^0.3.1"
js-yaml "^3.13.1"
parse-json "^4.0.0"
create-emotion@^10.0.9:
version "10.0.9"
resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-10.0.9.tgz#290c2036126171c9566fa24f49c9241d54625138"
integrity sha512-sLKD4bIiTs8PpEqr5vlCoV5lsYE4QOBYEUWaD0R+VGRMCvBKHmYlvLJXsL99Kdc4YEFAFwipi2bbncnvv6UxRg==
dependencies:
"@emotion/cache" "^10.0.9"
"@emotion/serialize" "^0.11.6"
"@emotion/sheet" "0.9.2"
"@emotion/utils" "0.11.1"
csstype@^2.5.7:
version "2.6.4"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f"
integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==
dom-helpers@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
dependencies:
"@babel/runtime" "^7.1.2"
emotion@^10.0.1:
version "10.0.9"
resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.9.tgz#2c37598af13df31dcd35a1957eaa8830f368c066"
integrity sha512-IMFwwWlU2TDt7eh4v6dm58E8VHAYOitqRbVoazQdxIu9/0CAH4a3UrTMnZSlWQAo09MrRRlKfgQFHswnj40meQ==
dependencies:
babel-plugin-emotion "^10.0.9"
create-emotion "^10.0.9"
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
find-root@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
isobject@^3.0.1: import-fresh@^2.0.0:
version "3.0.1" version "2.0.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
dependencies: dependencies:
node-fetch "^1.0.1" caller-path "^2.0.0"
whatwg-fetch ">=0.10.0" resolve-from "^3.0.0"
js-tokens@^3.0.0: is-arrayish@^0.2.1:
version "3.0.2" version "0.2.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
loose-envify@^1.0.0, loose-envify@^1.3.1: is-directory@^0.3.1:
version "1.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies: dependencies:
js-tokens "^3.0.0" argparse "^1.0.7"
esprima "^4.0.0"
node-fetch@^1.0.1: json-parse-better-errors@^1.0.1:
version "1.7.3" version "1.0.2"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
lodash@^4.17.11:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies: dependencies:
encoding "^0.1.11" js-tokens "^3.0.0 || ^4.0.0"
is-stream "^1.0.1"
object-assign@^4.1.0, object-assign@^4.1.1: object-assign@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
postcss-value-parser@^3.3.0: parse-json@^4.0.0:
version "3.3.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
dependencies: dependencies:
asap "~2.0.3" error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6: path-parse@^1.0.6:
version "15.6.0" version "1.0.6"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
prop-types@^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
dependencies: dependencies:
fbjs "^0.8.16" loose-envify "^1.4.0"
loose-envify "^1.3.1"
object-assign "^4.1.1" object-assign "^4.1.1"
react-is "^16.8.1"
react-loading-overlay@0.2.8: react-is@^16.8.1:
version "0.2.8" version "16.8.6"
resolved "https://registry.yarnpkg.com/react-loading-overlay/-/react-loading-overlay-0.2.8.tgz#c1c5531c9cfa4be6caca6b9aa0c1eb19e22b03fe" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-loading-overlay@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/react-loading-overlay/-/react-loading-overlay-1.0.1.tgz#ee3b1ad56c45bb2f1ba46d4820ba0d06cd319a91"
integrity sha512-aUjtZ8tNXBSx+MbD2SQs0boPbeTAGTh+I5U9nWjDzMasKlYr58RJpr57c8W7uApeLpOkAGbInExRi6GamNC2bA==
dependencies: dependencies:
prop-types "^15.5.10" emotion "^10.0.1"
react-transition-group "^1.2.1" prop-types "^15.6.2"
styled-components "^2.1.2" react-transition-group "^2.5.0"
react-transition-group@^1.2.1: react-transition-group@^2.5.0:
version "1.2.1" version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
dependencies: dependencies:
chain-function "^1.0.0" dom-helpers "^3.4.0"
dom-helpers "^3.2.0" loose-envify "^1.4.0"
loose-envify "^1.3.1" prop-types "^15.6.2"
prop-types "^15.5.6" react-lifecycles-compat "^3.0.4"
warning "^3.0.0"
setimmediate@^1.0.5: regenerator-runtime@^0.13.2:
version "1.0.5" version "0.13.2"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
styled-components@^2.1.2: resolve-from@^3.0.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.2.4.tgz#dd87fd3dafd359e7a0d570aec1bd07d691c0b5a2"
dependencies:
buffer "^5.0.3"
css-to-react-native "^2.0.3"
fbjs "^0.8.9"
hoist-non-react-statics "^1.2.0"
is-function "^1.0.1"
is-plain-object "^2.0.1"
prop-types "^15.5.4"
stylis "^3.4.0"
supports-color "^3.2.3"
stylis@^3.4.0:
version "3.4.5"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.4.5.tgz#d7b9595fc18e7b9c8775eca8270a9a1d3e59806e"
supports-color@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
dependencies:
has-flag "^1.0.0"
ua-parser-js@^0.7.9:
version "0.7.17"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
warning@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
dependencies: integrity sha1-six699nWiBvItuZTM17rywoYh0g=
loose-envify "^1.0.0"
whatwg-fetch@>=0.10.0: resolve@^1.10.0:
version "2.0.3" version "1.11.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==
dependencies:
path-parse "^1.0.6"
safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
@@ -190,6 +190,19 @@ import paginationFactory, {
That's it!! The benifit for using standalone is you can much easier to render the standalone component in any posistion. In the future, we will implement more featue like applying `style`, `className` etc on standalone components. That's it!! The benifit for using standalone is you can much easier to render the standalone component in any posistion. In the future, we will implement more featue like applying `style`, `className` etc on standalone components.
##### Customizable props for `PaginationListStandalone`
* N/A
##### Customizable props for `SizePerPageDropdownStandalone`
* `open`: `true` to make dropdown show.
* `hidden`: `true` to hide the size per page dropdown.
* `btnContextual`: Set the button contextual
* `variation`: Variation for dropdown, available value is `dropdown` and `dropup`.
* `className`: Custom the class on size per page dropdown
##### Customizable props for `SizePerPageDropdownStandalone`
* N/A
#### 4.2 Customization Everything #### 4.2 Customization Everything
If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object: If you choose to custom the pagination component by yourself, the `paginationProps` will be important for you. Becasue you have to know for example how to change page or what's the current page etc. Hence, following is all the props in `paginationProps` object:
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-paginator", "name": "react-bootstrap-table2-paginator",
"version": "2.0.3", "version": "2.0.6",
"description": "it's the pagination addon for react-bootstrap-table2", "description": "it's the pagination addon for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -32,7 +32,12 @@ class PaginationDataProvider extends Provider {
// user should align the page when the page is not fit to the data size when remote enable // user should align the page when the page is not fit to the data size when remote enable
if (!this.isRemotePagination() && !custom) { if (!this.isRemotePagination() && !custom) {
const newPage = alignPage( const newPage = alignPage(
nextProps.data.length, this.currPage, currSizePerPage, pageStartIndex); nextProps.data.length,
this.props.data.length,
this.currPage,
currSizePerPage,
pageStartIndex
);
if (this.currPage !== newPage) { if (this.currPage !== newPage) {
if (onPageChange) { if (onPageChange) {
@@ -41,6 +46,9 @@ class PaginationDataProvider extends Provider {
this.currPage = newPage; this.currPage = newPage;
} }
} }
if (nextProps.onDataSizeChange && nextProps.data.length !== this.props.data.length) {
nextProps.onDataSizeChange({ dataSize: nextProps.data.length });
}
} }
isRemotePagination = () => this.props.isRemotePagination(); isRemotePagination = () => this.props.isRemotePagination();
@@ -56,7 +56,7 @@ export default ExtendBase =>
alwaysShowAllBtns alwaysShowAllBtns
} = this.props; } = this.props;
let pages; let pages = [];
let endPage = totalPages; let endPage = totalPages;
if (endPage <= 0) return []; if (endPage <= 0) return [];
@@ -68,24 +68,42 @@ export default ExtendBase =>
startPage = endPage - paginationSize + 1; startPage = endPage - paginationSize + 1;
} }
if (startPage !== pageStartIndex && totalPages > paginationSize && withFirstAndLast) { if (alwaysShowAllBtns) {
if (withFirstAndLast) {
pages = [firstPageText, prePageText];
} else {
pages = [prePageText];
}
}
if (startPage !== pageStartIndex &&
totalPages > paginationSize &&
withFirstAndLast &&
pages.length === 0
) {
pages = [firstPageText, prePageText]; pages = [firstPageText, prePageText];
} else if (totalPages > 1 || alwaysShowAllBtns) { } else if (totalPages > 1 && pages.length === 0) {
pages = [prePageText]; pages = [prePageText];
} else {
pages = [];
} }
for (let i = startPage; i <= endPage; i += 1) { for (let i = startPage; i <= endPage; i += 1) {
if (i >= pageStartIndex) pages.push(i); if (i >= pageStartIndex) pages.push(i);
} }
if (endPage <= lastPage && pages.length > 1) { if (alwaysShowAllBtns || (endPage <= lastPage && pages.length > 1)) {
pages.push(nextPageText); pages.push(nextPageText);
} }
if (endPage !== lastPage && withFirstAndLast) { if ((endPage !== lastPage && withFirstAndLast) || (withFirstAndLast && alwaysShowAllBtns)) {
pages.push(lastPageText); pages.push(lastPageText);
} }
// if ((endPage <= lastPage && pages.length > 1) || alwaysShowAllBtns) {
// pages.push(nextPageText);
// }
// if (endPage !== lastPage && withFirstAndLast) {
// pages.push(lastPageText);
// }
return pages; return pages;
} }
+12 -2
View File
@@ -1,3 +1,5 @@
import Const from './const';
const getNormalizedPage = ( const getNormalizedPage = (
page, page,
pageStartIndex pageStartIndex
@@ -19,12 +21,20 @@ const startIndex = (
export const alignPage = ( export const alignPage = (
dataSize, dataSize,
prevDataSize,
page, page,
sizePerPage, sizePerPage,
pageStartIndex pageStartIndex
) => { ) => {
if (page < pageStartIndex || page > (Math.floor(dataSize / sizePerPage) + pageStartIndex)) { if (prevDataSize < dataSize) return page;
return pageStartIndex; if (page < pageStartIndex) return pageStartIndex;
if (dataSize <= 0) return pageStartIndex;
if ((page >= (Math.floor(dataSize / sizePerPage) + pageStartIndex)) && pageStartIndex === 1) {
return Math.ceil(dataSize / sizePerPage);
}
if (page >= Math.floor(dataSize / sizePerPage) && pageStartIndex === 0) {
const newPage = Math.ceil(dataSize / sizePerPage);
return newPage - Math.abs((Const.PAGE_START_INDEX - pageStartIndex));
} }
return page; return page;
}; };
@@ -48,6 +48,7 @@ const sizePerPageDropdownAdapter = WrappedComponent =>
} }
return ( return (
<WrappedComponent <WrappedComponent
{ ...this.props }
currSizePerPage={ `${currSizePerPage}` } currSizePerPage={ `${currSizePerPage}` }
options={ this.calculateSizePerPageStatus() } options={ this.calculateSizePerPageStatus() }
optionRenderer={ sizePerPageOptionRenderer } optionRenderer={ sizePerPageOptionRenderer }
@@ -50,9 +50,15 @@ class StateProvider extends React.Component {
// user should align the page when the page is not fit to the data size when remote enable // user should align the page when the page is not fit to the data size when remote enable
if (this.isRemotePagination() || custom) { if (this.isRemotePagination() || custom) {
this.currPage = nextProps.pagination.options.page; if (typeof nextProps.pagination.options.page !== 'undefined') {
this.currSizePerPage = nextProps.pagination.options.sizePerPage; this.currPage = nextProps.pagination.options.page;
this.dataSize = nextProps.pagination.options.totalSize; }
if (typeof nextProps.pagination.options.sizePerPage !== 'undefined') {
this.currSizePerPage = nextProps.pagination.options.sizePerPage;
}
if (typeof nextProps.pagination.options.totalSize !== 'undefined') {
this.dataSize = nextProps.pagination.options.totalSize;
}
} }
} }
@@ -117,13 +123,14 @@ class StateProvider extends React.Component {
const { pagination: { options } } = this.props; const { pagination: { options } } = this.props;
const pageStartIndex = typeof options.pageStartIndex === 'undefined' ? const pageStartIndex = typeof options.pageStartIndex === 'undefined' ?
Const.PAGE_START_INDEX : options.pageStartIndex; Const.PAGE_START_INDEX : options.pageStartIndex;
this.dataSize = newDataSize;
this.currPage = alignPage( this.currPage = alignPage(
newDataSize, newDataSize,
this.dataSize,
this.currPage, this.currPage,
this.currSizePerPage, this.currSizePerPage,
pageStartIndex pageStartIndex
); );
this.dataSize = newDataSize;
this.forceUpdate(); this.forceUpdate();
} }
@@ -43,18 +43,132 @@ describe('Page Functions', () => {
}); });
describe('alignPage', () => { describe('alignPage', () => {
const pageStartIndex = 1; let newDataSize;
const sizePerPage = 10; let prevDataSize;
const page = 3; let currPage;
describe('if the page does not fit the pages which calculated from the length of data', () => { let pageStartIndex;
it('should return pageStartIndex argument', () => { let sizePerPage;
expect(alignPage(15, page, sizePerPage, pageStartIndex)).toEqual(pageStartIndex);
describe('if prevDataSize < newDataSize', () => {
beforeEach(() => {
newDataSize = 10;
prevDataSize = 6;
currPage = 2;
pageStartIndex = 1;
sizePerPage = 5;
});
it('should return same page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(currPage);
}); });
}); });
describe('if the length of store.data is large than the end page index', () => { describe('if currPage < newDataSize', () => {
it('should return current page', () => { beforeEach(() => {
expect(alignPage(30, page, sizePerPage, pageStartIndex)).toEqual(page); newDataSize = 10;
prevDataSize = 12;
currPage = 0;
pageStartIndex = 1;
sizePerPage = 5;
});
it('should return correct page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(pageStartIndex);
});
});
describe('if partStartIndex is default 1', () => {
describe('and currPage is bigger than newest last page', () => {
beforeEach(() => {
newDataSize = 9;
prevDataSize = 12;
currPage = 3;
pageStartIndex = 1;
sizePerPage = 5;
});
it('should return correct page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(2);
});
});
describe('and currPage is short than newest last page', () => {
beforeEach(() => {
newDataSize = 11;
prevDataSize = 12;
currPage = 3;
pageStartIndex = 1;
sizePerPage = 5;
});
it('should return correct page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(currPage);
});
});
});
describe('if partStartIndex is default 0', () => {
describe('and currPage is bigger than newest last page', () => {
beforeEach(() => {
newDataSize = 8;
prevDataSize = 11;
currPage = 2;
pageStartIndex = 0;
sizePerPage = 5;
});
it('should return correct page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(1);
});
});
describe('and currPage is short than newest last page', () => {
beforeEach(() => {
newDataSize = 11;
prevDataSize = 12;
currPage = 2;
pageStartIndex = 0;
sizePerPage = 5;
});
it('should return correct page', () => {
expect(alignPage(
newDataSize,
prevDataSize,
currPage,
sizePerPage,
pageStartIndex
)).toEqual(currPage);
});
}); });
}); });
}); });
@@ -67,6 +67,19 @@ const { SearchBar } = Search;
3. You should render `SearchBar` with `searchProps` as well. The position of `SearchBar` is depends on you. 3. You should render `SearchBar` with `searchProps` as well. The position of `SearchBar` is depends on you.
### `SearchBar` Props
#### className - [string]
Custom the class on input element.
#### placeholder - [string]
Custom the placeholder on input element.
#### style - [object]
Custom the style on input element.
#### delay = [number]
milionsecond for debounce user input.
### Search Options ### Search Options
#### defaultSearch - [string] #### defaultSearch - [string]
@@ -127,6 +140,8 @@ const { SearchBar, ClearSearchButton } = Search;
</ToolkitProvider> </ToolkitProvider>
``` ```
-----
## Export CSV ## Export CSV
There are two steps to enable the export CSV functionality: There are two steps to enable the export CSV functionality:
@@ -170,12 +185,22 @@ Default is `false`. Give true to avoid to attach the csv header.
#### noAutoBOM - [bool] #### noAutoBOM - [bool]
Default is `true`. Default is `true`.
#### blobType - [string]
Default is `text/plain;charset=utf-8`. Change to update the blob type of the exported file.
#### exportAll - [bool] #### exportAll - [bool]
Default is `true`. `false` will only export current data which display on table. Default is `true`. `false` will only export current data which display on table.
#### onlyExportSelection - [bool] #### onlyExportSelection - [bool]
Default is `false`. `true` will only export the data which is selected. Default is `false`. `true` will only export the data which is selected.
#### onlyExportFiltered - [bool]
Default is `false`. `true` will only export the data which is filtered/searched.
>> When you configure this prop as true, you must turn off `exportAll`.
-----
## Column Toggle ## Column Toggle
Let's see how to render the column toggle in your react component: Let's see how to render the column toggle in your react component:
+2
View File
@@ -29,7 +29,9 @@ class ToolkitProvider extends statelessDecorator(React.Component) {
separator: PropTypes.string, separator: PropTypes.string,
ignoreHeader: PropTypes.bool, ignoreHeader: PropTypes.bool,
noAutoBOM: PropTypes.bool, noAutoBOM: PropTypes.bool,
blobType: PropTypes.string,
exportAll: PropTypes.bool, exportAll: PropTypes.bool,
onlyExportFiltered: PropTypes.bool,
onlyExportSelection: PropTypes.bool onlyExportSelection: PropTypes.bool
}) })
]) ])
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table2-toolkit", "name": "react-bootstrap-table2-toolkit",
"version": "1.3.1", "version": "2.0.1",
"description": "The toolkit for react-bootstrap-table2", "description": "The toolkit for react-bootstrap-table2",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -45,6 +45,6 @@
"react-dom": "^16.3.0" "react-dom": "^16.3.0"
}, },
"dependencies": { "dependencies": {
"file-saver": "1.3.8" "file-saver": "2.0.2"
} }
} }
@@ -42,7 +42,7 @@ export const transform = (
cellContent = m.formatter(cellContent, row, rowIndex, m.formatExtraData); cellContent = m.formatter(cellContent, row, rowIndex, m.formatExtraData);
} }
if (m.type === String) { if (m.type === String) {
return `"${cellContent}"`; return `"${`${cellContent}`.replace(/"/g, '""')}"`;
} }
return cellContent; return cellContent;
}).join(separator)).join('\n'); }).join(separator)).join('\n');
@@ -54,11 +54,12 @@ export const save = (
content, content,
{ {
noAutoBOM, noAutoBOM,
fileName fileName,
blobType
} }
) => { ) => {
FileSaver.saveAs( FileSaver.saveAs(
new Blob([content], { type: 'text/plain;charset=utf-8' }), new Blob([content], { type: blobType }),
fileName, fileName,
noAutoBOM noAutoBOM
); );
+7 -1
View File
@@ -5,6 +5,7 @@ const csvDefaultOptions = {
separator: ',', separator: ',',
ignoreHeader: false, ignoreHeader: false,
noAutoBOM: true, noAutoBOM: true,
blobType: 'text/plain;charset=utf-8',
exportAll: true, exportAll: true,
onlyExportSelection: false onlyExportSelection: false
}; };
@@ -27,19 +28,24 @@ export default Base =>
data = source; data = source;
} else if (options.exportAll) { } else if (options.exportAll) {
data = this.props.data; data = this.props.data;
} else if (options.onlyExportFiltered) {
const payload = {};
this.tableExposedAPIEmitter.emit('get.filtered.rows', payload);
data = payload.result;
} else { } else {
const payload = {}; const payload = {};
this.tableExposedAPIEmitter.emit('get.table.data', payload); this.tableExposedAPIEmitter.emit('get.table.data', payload);
data = payload.result; data = payload.result;
} }
// filter data // filter data by row selection
if (options.onlyExportSelection) { if (options.onlyExportSelection) {
const payload = {}; const payload = {};
this.tableExposedAPIEmitter.emit('get.selected.rows', payload); this.tableExposedAPIEmitter.emit('get.selected.rows', payload);
const selections = payload.result; const selections = payload.result;
data = data.filter(row => !!selections.find(sel => row[keyField] === sel)); data = data.filter(row => !!selections.find(sel => row[keyField] === sel));
} }
const content = transform(data, meta, this._.get, options); const content = transform(data, meta, this._.get, options);
save(content, options); save(content, options);
} }
@@ -54,20 +54,29 @@ class SearchBar extends React.Component {
const { const {
className, className,
style, style,
placeholder placeholder,
tableId
} = this.props; } = this.props;
return ( return (
<input <label
ref={ n => this.input = n } htmlFor={ `search-bar-${tableId}` }
type="text" className="search-label"
style={ style } >
onKeyUp={ () => this.onKeyup() } <span className="sr-only">Search this table</span>
onChange={ this.onChangeValue } <input
className={ `form-control ${className}` } ref={ n => this.input = n }
value={ this.state.value } id={ `search-bar-${tableId}` }
placeholder={ placeholder || SearchBar.defaultProps.placeholder } type="text"
/> style={ style }
aria-label="enter text you want to search"
onKeyUp={ () => this.onKeyup() }
onChange={ this.onChangeValue }
className={ `form-control ${className}` }
value={ this.state.value }
placeholder={ placeholder || SearchBar.defaultProps.placeholder }
/>
</label>
); );
} }
} }
@@ -78,7 +87,8 @@ SearchBar.propTypes = {
placeholder: PropTypes.string, placeholder: PropTypes.string,
style: PropTypes.object, style: PropTypes.object,
delay: PropTypes.number, delay: PropTypes.number,
searchText: PropTypes.string searchText: PropTypes.string,
tableId: PropTypes.string
}; };
SearchBar.defaultProps = { SearchBar.defaultProps = {
@@ -86,7 +96,8 @@ SearchBar.defaultProps = {
style: {}, style: {},
placeholder: 'Search', placeholder: 'Search',
delay: 250, delay: 250,
searchText: '' searchText: '',
tableId: '0'
}; };
export default SearchBar; export default SearchBar;
@@ -59,6 +59,10 @@ export default (options = {
} }
} }
getSearched() {
return this.state.data;
}
triggerListener(result) { triggerListener(result) {
if (this.props.dataChangeListener) { if (this.props.dataChangeListener) {
this.props.dataChangeListener.emit('filterChanged', result.length); this.props.dataChangeListener.emit('filterChanged', result.length);
@@ -0,0 +1,3 @@
.search-label {
display: block !important;
}
@@ -2,6 +2,7 @@
# yarn lockfile v1 # yarn lockfile v1
file-saver@1.3.8: file-saver@2.0.2:
version "1.3.8" version "2.0.2"
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-1.3.8.tgz#e68a30c7cb044e2fb362b428469feb291c2e09d8" resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.2.tgz#06d6e728a9ea2df2cce2f8d9e84dfcdc338ec17a"
integrity sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==
+2 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "react-bootstrap-table-next", "name": "react-bootstrap-table-next",
"version": "3.0.0", "version": "3.1.4",
"description": "Next generation of react-bootstrap-table", "description": "Next generation of react-bootstrap-table",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -37,6 +37,7 @@
], ],
"dependencies": { "dependencies": {
"classnames": "2.2.5", "classnames": "2.2.5",
"react-transition-group": "2.5.3",
"underscore": "1.9.1" "underscore": "1.9.1"
}, },
"peerDependencies": { "peerDependencies": {
+1 -2
View File
@@ -17,7 +17,6 @@ class Body extends React.Component {
super(props); super(props);
const { const {
keyField, keyField,
visibleColumnSize,
cellEdit, cellEdit,
selectRow, selectRow,
expandRow expandRow
@@ -34,7 +33,7 @@ class Body extends React.Component {
const expandRowEnabled = !!expandRow.renderer; const expandRowEnabled = !!expandRow.renderer;
if (expandRowEnabled) { if (expandRowEnabled) {
RowComponent = withRowExpansion(RowAggregator, visibleColumnSize); RowComponent = withRowExpansion(RowAggregator);
} }
if (selectRowEnabled) { if (selectRowEnabled) {
+16 -1
View File
@@ -18,6 +18,14 @@ class BootstrapTable extends PropsBaseResolver(Component) {
this.validateProps(); this.validateProps();
} }
componentWillReceiveProps(nextProps) {
if (nextProps.onDataSizeChange && !nextProps.pagination) {
if (nextProps.data.length !== this.props.data.length) {
nextProps.onDataSizeChange({ dataSize: nextProps.data.length });
}
}
}
// Exposed APIs // Exposed APIs
getData = () => { getData = () => {
return this.visibleRows(); return this.visibleRows();
@@ -159,7 +167,13 @@ BootstrapTable.propTypes = {
bgColor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), bgColor: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
hideSelectColumn: PropTypes.bool, hideSelectColumn: PropTypes.bool,
selectionRenderer: PropTypes.func, selectionRenderer: PropTypes.func,
selectionHeaderRenderer: PropTypes.func selectionHeaderRenderer: PropTypes.func,
headerColumnStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
selectColumnStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
selectColumnPosition: PropTypes.oneOf([
Const.INDICATOR_POSITION_LEFT,
Const.INDICATOR_POSITION_RIGHT
])
}), }),
expandRow: PropTypes.shape({ expandRow: PropTypes.shape({
renderer: PropTypes.func, renderer: PropTypes.func,
@@ -192,6 +206,7 @@ BootstrapTable.propTypes = {
onSort: PropTypes.func, onSort: PropTypes.func,
onFilter: PropTypes.func, onFilter: PropTypes.func,
onExternalFilter: PropTypes.func, onExternalFilter: PropTypes.func,
onDataSizeChange: PropTypes.func,
// Inject from toolkit // Inject from toolkit
search: PropTypes.shape({ search: PropTypes.shape({
searchText: PropTypes.string, searchText: PropTypes.string,
+8 -15
View File
@@ -8,7 +8,7 @@ import _ from './utils';
class Cell extends eventDelegater(Component) { class Cell extends eventDelegater(Component) {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleEditingCell = this.handleEditingCell.bind(this); this.createHandleEditingCell = this.createHandleEditingCell.bind(this);
} }
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
@@ -26,7 +26,7 @@ class Cell extends eventDelegater(Component) {
// if (nextProps.formatter) // if (nextProps.formatter)
shouldUpdate = shouldUpdate =
nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false || (nextProps.column.formatter ? !_.isEqual(this.props.row, nextProps.row) : false) ||
this.props.column.hidden !== nextProps.column.hidden || this.props.column.hidden !== nextProps.column.hidden ||
this.props.rowIndex !== nextProps.rowIndex || this.props.rowIndex !== nextProps.rowIndex ||
this.props.columnIndex !== nextProps.columnIndex || this.props.columnIndex !== nextProps.columnIndex ||
@@ -43,17 +43,10 @@ class Cell extends eventDelegater(Component) {
return shouldUpdate; return shouldUpdate;
} }
handleEditingCell(e) { createHandleEditingCell = originFunc => (e) => {
const { column, onStart, rowIndex, columnIndex, clickToEdit, dbclickToEdit } = this.props; const { onStart, rowIndex, columnIndex, clickToEdit, dbclickToEdit } = this.props;
const { events } = column; if ((clickToEdit || dbclickToEdit) && _.isFunction(originFunc)) {
if (events) { originFunc(e);
if (clickToEdit) {
const customClick = events.onClick;
if (_.isFunction(customClick)) customClick(e);
} else if (dbclickToEdit) {
const customDbClick = events.onDoubleClick;
if (_.isFunction(customDbClick)) customDbClick(e);
}
} }
if (onStart) { if (onStart) {
onStart(rowIndex, columnIndex); onStart(rowIndex, columnIndex);
@@ -85,9 +78,9 @@ class Cell extends eventDelegater(Component) {
} }
if (clickToEdit && editable) { if (clickToEdit && editable) {
attrs.onClick = this.handleEditingCell; attrs.onClick = this.createHandleEditingCell(attrs.onClick);
} else if (dbclickToEdit && editable) { } else if (dbclickToEdit && editable) {
attrs.onDoubleClick = this.handleEditingCell; attrs.onDoubleClick = this.createHandleEditingCell(attrs.onDoubleClick);
} }
return ( return (
+10
View File
@@ -23,6 +23,15 @@ const withContext = Base =>
const exposedAPIEmitter = new EventEmitter(); const exposedAPIEmitter = new EventEmitter();
exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData()); exposedAPIEmitter.on('get.table.data', payload => payload.result = this.table.getData());
exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected()); exposedAPIEmitter.on('get.selected.rows', payload => payload.result = this.selectionContext.getSelected());
exposedAPIEmitter.on('get.filtered.rows', (payload) => {
if (this.searchContext) {
payload.result = this.searchContext.getSearched();
} else if (this.filterContext) {
payload.result = this.filterContext.getFiltered();
} else {
payload.result = this.table.getData();
}
});
props.registerExposedAPI(exposedAPIEmitter); props.registerExposedAPI(exposedAPIEmitter);
} }
@@ -202,6 +211,7 @@ const withContext = Base =>
bootstrap4={ this.props.bootstrap4 } bootstrap4={ this.props.bootstrap4 }
isRemotePagination={ this.isRemotePagination } isRemotePagination={ this.isRemotePagination }
remoteEmitter={ this.remoteEmitter } remoteEmitter={ this.remoteEmitter }
onDataSizeChange={ this.props.onDataSizeChange }
> >
<this.PaginationContext.Consumer> <this.PaginationContext.Consumer>
{ {
@@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import dataOperator from '../store/operators'; import dataOperator from '../store/operators';
import _ from '../utils';
const RowExpandContext = React.createContext(); const RowExpandContext = React.createContext();
@@ -10,18 +11,35 @@ class RowExpandProvider extends React.Component {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
data: PropTypes.array.isRequired, data: PropTypes.array.isRequired,
keyField: PropTypes.string.isRequired keyField: PropTypes.string.isRequired
} };
state = { expanded: this.props.expandRow.expanded || [] }; state = { expanded: this.props.expandRow.expanded || [],
isClosing: this.props.expandRow.isClosing || [] };
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.expandRow) { if (nextProps.expandRow) {
const nextExpanded = nextProps.expandRow.expanded || this.state.expanded;
const isClosing = this.state.expanded.reduce((acc, cur) => {
if (!nextExpanded.includes(cur)) {
acc.push(cur);
}
return acc;
}, []);
this.setState(() => ({ this.setState(() => ({
expanded: nextProps.expandRow.expanded || this.state.expanded expanded: nextExpanded,
isClosing
}));
} else {
this.setState(() => ({
expanded: this.state.expanded
})); }));
} }
} }
onClosed = (closedRow) => {
this.setState({ isClosing: this.state.isClosing.filter(value => value !== closedRow) });
};
handleRowExpand = (rowKey, expanded, rowIndex, e) => { handleRowExpand = (rowKey, expanded, rowIndex, e) => {
const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props; const { data, keyField, expandRow: { onExpand, onlyOneExpanding, nonExpandable } } = this.props;
if (nonExpandable && nonExpandable.includes(rowKey)) { if (nonExpandable && nonExpandable.includes(rowKey)) {
@@ -29,11 +47,15 @@ class RowExpandProvider extends React.Component {
} }
let currExpanded = [...this.state.expanded]; let currExpanded = [...this.state.expanded];
let isClosing = [...this.state.isClosing];
if (expanded) { if (expanded) {
if (onlyOneExpanding) currExpanded = [rowKey]; if (onlyOneExpanding) {
else currExpanded.push(rowKey); isClosing = isClosing.concat(currExpanded);
currExpanded = [rowKey];
} else currExpanded.push(rowKey);
} else { } else {
isClosing.push(rowKey);
currExpanded = currExpanded.filter(value => value !== rowKey); currExpanded = currExpanded.filter(value => value !== rowKey);
} }
@@ -41,8 +63,8 @@ class RowExpandProvider extends React.Component {
const row = dataOperator.getRowByRowId(data, keyField, rowKey); const row = dataOperator.getRowByRowId(data, keyField, rowKey);
onExpand(row, expanded, rowIndex, e); onExpand(row, expanded, rowIndex, e);
} }
this.setState(() => ({ expanded: currExpanded })); this.setState(() => ({ expanded: currExpanded, isClosing }));
} };
handleAllRowExpand = (e, expandAll) => { handleAllRowExpand = (e, expandAll) => {
const { const {
@@ -60,7 +82,7 @@ class RowExpandProvider extends React.Component {
if (expandAll) { if (expandAll) {
currExpanded = expanded.concat(dataOperator.expandableKeys(data, keyField, nonExpandable)); currExpanded = expanded.concat(dataOperator.expandableKeys(data, keyField, nonExpandable));
} else { } else {
currExpanded = expanded.filter(s => typeof data.find(d => d[keyField] === s) === 'undefined'); currExpanded = expanded.filter(s => typeof data.find(d => _.get(d, keyField) === s) === 'undefined');
} }
if (onExpandAll) { if (onExpandAll) {
@@ -68,7 +90,7 @@ class RowExpandProvider extends React.Component {
} }
this.setState(() => ({ expanded: currExpanded })); this.setState(() => ({ expanded: currExpanded }));
} };
render() { render() {
const { data, keyField } = this.props; const { data, keyField } = this.props;
@@ -78,6 +100,8 @@ class RowExpandProvider extends React.Component {
...this.props.expandRow, ...this.props.expandRow,
nonExpandable: this.props.expandRow.nonExpandable, nonExpandable: this.props.expandRow.nonExpandable,
expanded: this.state.expanded, expanded: this.state.expanded,
isClosing: this.state.isClosing,
onClosed: this.onClosed,
isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded), isAnyExpands: dataOperator.isAnyExpands(data, keyField, this.state.expanded),
onRowExpand: this.handleRowExpand, onRowExpand: this.handleRowExpand,
onAllRowExpand: this.handleAllRowExpand onAllRowExpand: this.handleAllRowExpand
+9 -5
View File
@@ -11,9 +11,9 @@ const Footer = (props) => {
const SelectionFooterCellComp = () => <th />; const SelectionFooterCellComp = () => <th />;
const ExpansionFooterCellComp = () => <th />; const ExpansionFooterCellComp = () => <th />;
const isRenderExpandColumnInLeft = ( const isRenderFunctionColumnInLeft = (
expandColumnPosition = Const.INDICATOR_POSITION_LEFT position = Const.INDICATOR_POSITION_LEFT
) => expandColumnPosition === Const.INDICATOR_POSITION_LEFT; ) => position === Const.INDICATOR_POSITION_LEFT;
const childrens = columns.map((column, i) => { const childrens = columns.map((column, i) => {
if (column.footer === undefined || column.footer === null) { if (column.footer === undefined || column.footer === null) {
@@ -33,11 +33,15 @@ const Footer = (props) => {
}); });
if (selectRow && selectRow.hideSelectColumn !== true) { if (selectRow && selectRow.hideSelectColumn !== true) {
childrens.unshift(<SelectionFooterCellComp key="selection" />); if (isRenderFunctionColumnInLeft(selectRow.selectColumnPosition)) {
childrens.unshift(<SelectionFooterCellComp key="selection" />);
} else {
childrens.push(<SelectionFooterCellComp key="selection" />);
}
} }
if (expandRow.showExpandColumn) { if (expandRow.showExpandColumn) {
if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) { if (isRenderFunctionColumnInLeft(expandRow.expandColumnPosition)) {
childrens.unshift(<ExpansionFooterCellComp key="expansion" />); childrens.unshift(<ExpansionFooterCellComp key="expansion" />);
} else { } else {
childrens.push(<ExpansionFooterCellComp key="expansion" />); childrens.push(<ExpansionFooterCellComp key="expansion" />);
+2 -1
View File
@@ -40,7 +40,8 @@ const HeaderCell = (props) => {
const cellAttrs = { const cellAttrs = {
..._.isFunction(headerAttrs) ? headerAttrs(column, index) : headerAttrs, ..._.isFunction(headerAttrs) ? headerAttrs(column, index) : headerAttrs,
...headerEvents ...headerEvents,
tabIndex: 0
}; };
let sortSymbol; let sortSymbol;
+9 -5
View File
@@ -33,9 +33,9 @@ const Header = (props) => {
SelectionHeaderCellComp = withHeaderSelection(SelectionHeaderCell); SelectionHeaderCellComp = withHeaderSelection(SelectionHeaderCell);
} }
const isRenderExpandColumnInLeft = ( const isRenderFunctionColumnInLeft = (
expandColumnPosition = Const.INDICATOR_POSITION_LEFT position = Const.INDICATOR_POSITION_LEFT
) => expandColumnPosition === Const.INDICATOR_POSITION_LEFT; ) => position === Const.INDICATOR_POSITION_LEFT;
const childrens = [ const childrens = [
columns.map((column, i) => { columns.map((column, i) => {
@@ -58,11 +58,15 @@ const Header = (props) => {
]; ];
if (!selectRow.hideSelectColumn) { if (!selectRow.hideSelectColumn) {
childrens.unshift(<SelectionHeaderCellComp key="selection" />); if (isRenderFunctionColumnInLeft(selectRow.selectColumnPosition)) {
childrens.unshift(<SelectionHeaderCellComp key="selection" />);
} else {
childrens.push(<SelectionHeaderCellComp key="selection" />);
}
} }
if (expandRow.showExpandColumn) { if (expandRow.showExpandColumn) {
if (isRenderExpandColumnInLeft(expandRow.expandColumnPosition)) { if (isRenderFunctionColumnInLeft(expandRow.expandColumnPosition)) {
childrens.unshift(<ExpansionHeaderCellComp key="expansion" />); childrens.unshift(<ExpansionHeaderCellComp key="expansion" />);
} else { } else {
childrens.push(<ExpansionHeaderCellComp key="expansion" />); childrens.push(<ExpansionHeaderCellComp key="expansion" />);
@@ -1,18 +1,37 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CSSTransition } from 'react-transition-group';
const ExpandRow = ({ children, ...rest }) => ( const ExpandRow = ({ children, expanded, onClosed, ...rest }) => (
<tr className="expanding-row"> <tr>
<td { ...rest }>{ children }</td> <td className="reset-expansion-style" { ...rest }>
<CSSTransition
appear
in={ expanded }
timeout={ 400 }
classNames="row-expand-slide"
onExited={ onClosed }
>
<div>
<div className="row-expansion-style">
{ children }
</div>
</div>
</CSSTransition>
</td>
</tr> </tr>
); );
ExpandRow.propTypes = { ExpandRow.propTypes = {
children: PropTypes.node children: PropTypes.node,
expanded: PropTypes.bool,
onClosed: PropTypes.func
}; };
ExpandRow.defaultProps = { ExpandRow.defaultProps = {
children: null children: null,
expanded: false,
onClosed: null
}; };
export default ExpandRow; export default ExpandRow;
@@ -3,13 +3,13 @@ import React from 'react';
import ExpandRow from './expand-row'; import ExpandRow from './expand-row';
import ExpansionContext from '../contexts/row-expand-context'; import ExpansionContext from '../contexts/row-expand-context';
export default (Component, visibleColumnSize) => { export default (Component) => {
const renderWithExpansion = (props, expandRow) => { const renderWithExpansion = (props, expandRow) => {
const key = props.value; const key = props.value;
const expanded = expandRow.expanded.includes(key); const expanded = expandRow.expanded.includes(key);
const isClosing = expandRow.isClosing.includes(key);
const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key); const expandable = !expandRow.nonExpandable || !expandRow.nonExpandable.includes(key);
return [ return [
<Component <Component
{ ...props } { ...props }
@@ -18,9 +18,11 @@ export default (Component, visibleColumnSize) => {
expandable={ expandable } expandable={ expandable }
expandRow={ { ...expandRow } } expandRow={ { ...expandRow } }
/>, />,
expanded ? <ExpandRow expanded || isClosing ? <ExpandRow
key={ `${key}-expanding` } key={ `${key}-expanding` }
colSpan={ visibleColumnSize } colSpan={ props.visibleColumnSize }
expanded={ expanded }
onClosed={ () => expandRow.onClosed(key) }
> >
{ expandRow.renderer(props.row) } { expandRow.renderer(props.row) }
</ExpandRow> : null </ExpandRow> : null
@@ -5,6 +5,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Const from '../const'; import Const from '../const';
import _ from '../utils';
import { BootstrapContext } from '../contexts/bootstrap'; import { BootstrapContext } from '../contexts/bootstrap';
export default class SelectionCell extends Component { export default class SelectionCell extends Component {
@@ -17,7 +18,8 @@ export default class SelectionCell extends Component {
rowIndex: PropTypes.number, rowIndex: PropTypes.number,
tabIndex: PropTypes.number, tabIndex: PropTypes.number,
clickToSelect: PropTypes.bool, clickToSelect: PropTypes.bool,
selectionRenderer: PropTypes.func selectionRenderer: PropTypes.func,
selectColumnStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func])
} }
constructor() { constructor() {
@@ -31,7 +33,8 @@ export default class SelectionCell extends Component {
this.props.selected !== nextProps.selected || this.props.selected !== nextProps.selected ||
this.props.disabled !== nextProps.disabled || this.props.disabled !== nextProps.disabled ||
this.props.rowKey !== nextProps.rowKey || this.props.rowKey !== nextProps.rowKey ||
this.props.tabIndex !== nextProps.tabIndex; this.props.tabIndex !== nextProps.tabIndex ||
this.props.selectColumnStyle !== nextProps.selectColumnStyle;
return shouldUpdate; return shouldUpdate;
} }
@@ -43,12 +46,10 @@ export default class SelectionCell extends Component {
selected, selected,
onRowSelect, onRowSelect,
disabled, disabled,
rowIndex, rowIndex
clickToSelect
} = this.props; } = this.props;
e.stopPropagation();
if (disabled) return; if (disabled) return;
if (clickToSelect) return;
const checked = inputType === Const.ROW_SELECT_SINGLE const checked = inputType === Const.ROW_SELECT_SINGLE
? true ? true
@@ -59,17 +60,28 @@ export default class SelectionCell extends Component {
render() { render() {
const { const {
rowKey,
mode: inputType, mode: inputType,
selected, selected,
disabled, disabled,
tabIndex, tabIndex,
rowIndex, rowIndex,
selectionRenderer selectionRenderer,
selectColumnStyle
} = this.props; } = this.props;
const attrs = {}; const attrs = {};
if (tabIndex !== -1) attrs.tabIndex = tabIndex; if (tabIndex !== -1) attrs.tabIndex = tabIndex;
attrs.style = _.isFunction(selectColumnStyle) ?
selectColumnStyle({
checked: selected,
disabled,
rowIndex,
rowKey
}) :
selectColumnStyle;
return ( return (
<BootstrapContext.Consumer> <BootstrapContext.Consumer>
{ {
@@ -3,6 +3,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Const from '../const'; import Const from '../const';
import { BootstrapContext } from '../contexts/bootstrap'; import { BootstrapContext } from '../contexts/bootstrap';
import _ from '../utils';
export const CheckBox = ({ className, checked, indeterminate }) => ( export const CheckBox = ({ className, checked, indeterminate }) => (
<input <input
@@ -28,7 +29,8 @@ export default class SelectionHeaderCell extends Component {
checkedStatus: PropTypes.string, checkedStatus: PropTypes.string,
onAllRowsSelect: PropTypes.func, onAllRowsSelect: PropTypes.func,
hideSelectAll: PropTypes.bool, hideSelectAll: PropTypes.bool,
selectionHeaderRenderer: PropTypes.func selectionHeaderRenderer: PropTypes.func,
headerColumnStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func])
} }
constructor() { constructor() {
@@ -64,7 +66,13 @@ export default class SelectionHeaderCell extends Component {
CHECKBOX_STATUS_CHECKED, CHECKBOX_STATUS_INDETERMINATE, ROW_SELECT_MULTIPLE CHECKBOX_STATUS_CHECKED, CHECKBOX_STATUS_INDETERMINATE, ROW_SELECT_MULTIPLE
} = Const; } = Const;
const { mode, checkedStatus, selectionHeaderRenderer, hideSelectAll } = this.props; const {
mode,
checkedStatus,
selectionHeaderRenderer,
hideSelectAll,
headerColumnStyle
} = this.props;
if (hideSelectAll) { if (hideSelectAll) {
return <th data-row-selection />; return <th data-row-selection />;
} }
@@ -79,6 +87,10 @@ export default class SelectionHeaderCell extends Component {
attrs.onClick = this.handleCheckBoxClick; attrs.onClick = this.handleCheckBoxClick;
} }
attrs.style = _.isFunction(headerColumnStyle) ?
headerColumnStyle(checkedStatus) :
headerColumnStyle;
return ( return (
<BootstrapContext.Consumer> <BootstrapContext.Consumer>
{ {
+14 -9
View File
@@ -37,18 +37,18 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
this.props.selectable !== nextProps.selectable || this.props.selectable !== nextProps.selectable ||
this.shouldUpdatedBySelfProps(nextProps) this.shouldUpdatedBySelfProps(nextProps)
) { ) {
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps); this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps);
return true; return true;
} }
this.shouldUpdateRowContent = this.shouldUpdateChild(nextProps); this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps);
return this.shouldUpdateRowContent; return this.shouldUpdateRowContent;
} }
isRenderExpandColumnInLeft( isRenderFunctionColumnInLeft(
expandColumnPosition = Const.INDICATOR_POSITION_LEFT position = Const.INDICATOR_POSITION_LEFT
) { ) {
return expandColumnPosition === Const.INDICATOR_POSITION_LEFT; return position === Const.INDICATOR_POSITION_LEFT;
} }
render() { render() {
@@ -71,7 +71,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
...rest ...rest
} = this.props; } = this.props;
const key = _.get(row, keyField); const key = _.get(row, keyField);
const { hideSelectColumn, clickToSelect } = selectRow; const { hideSelectColumn, selectColumnPosition, clickToSelect } = selectRow;
const { showExpandColumn, expandColumnPosition } = expandRow; const { showExpandColumn, expandColumnPosition } = expandRow;
const newAttrs = this.delegate({ ...attrs }); const newAttrs = this.delegate({ ...attrs });
@@ -95,7 +95,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
)]; )];
if (!hideSelectColumn) { if (!hideSelectColumn) {
childrens.unshift(( const selectCell = (
<SelectionCell <SelectionCell
{ ...selectRow } { ...selectRow }
key="selection-cell" key="selection-cell"
@@ -105,7 +105,12 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
disabled={ !selectable } disabled={ !selectable }
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 } tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
/> />
)); );
if (this.isRenderFunctionColumnInLeft(selectColumnPosition)) {
childrens.unshift(selectCell);
} else {
childrens.push(selectCell);
}
} }
if (showExpandColumn) { if (showExpandColumn) {
@@ -120,7 +125,7 @@ export default class RowAggregator extends shouldUpdater(eventDelegater(React.Co
tabIndex={ tabIndexCell ? tabIndexStart++ : -1 } tabIndex={ tabIndexCell ? tabIndexStart++ : -1 }
/> />
); );
if (this.isRenderExpandColumnInLeft(expandColumnPosition)) { if (this.isRenderFunctionColumnInLeft(expandColumnPosition)) {
childrens.unshift(expandCell); childrens.unshift(expandCell);
} else { } else {
childrens.push(expandCell); childrens.push(expandCell);
+8 -2
View File
@@ -8,7 +8,8 @@ export default ExtendBase =>
return ( return (
nextProps.editingRowIdx === nextProps.rowIndex || nextProps.editingRowIdx === nextProps.rowIndex ||
(this.props.editingRowIdx === nextProps.rowIndex && (this.props.editingRowIdx === nextProps.rowIndex &&
nextProps.editingRowIdx === null) nextProps.editingRowIdx === null) ||
this.props.editingRowIdx === nextProps.rowIndex
); );
} }
@@ -26,7 +27,7 @@ export default ExtendBase =>
return true; return true;
} }
for (let i = 0; i < this.props.columns.length; i += 1) { for (let i = 0; i < this.props.columns.length; i += 1) {
if (this.props.columns[i].hidden !== nextProps.columns[i].hidden) { if (!_.isEqual(this.props.columns[i], nextProps.columns[i])) {
return true; return true;
} }
} }
@@ -47,4 +48,9 @@ export default ExtendBase =>
return this.shouldUpdateByCellEditing(nextProps) || return this.shouldUpdateByCellEditing(nextProps) ||
this.shouldUpdatedByNormalProps(nextProps); this.shouldUpdatedByNormalProps(nextProps);
} }
shouldRowContentUpdate(nextProps) {
return this.shouldUpdateChild(nextProps) ||
this.shouldUpdateByColumnsForSimpleCheck(nextProps);
}
}; };
+1 -2
View File
@@ -15,8 +15,7 @@ class SimpleRow extends shouldUpdater(eventDelegater(Component)) {
shouldComponentUpdate(nextProps) { shouldComponentUpdate(nextProps) {
this.shouldUpdateRowContent = false; this.shouldUpdateRowContent = false;
this.shouldUpdateRowContent = this.shouldUpdateRowContent = this.shouldRowContentUpdate(nextProps);
this.shouldUpdateChild(nextProps) || this.shouldUpdateByColumnsForSimpleCheck(nextProps);
if (this.shouldUpdateRowContent) return true; if (this.shouldUpdateRowContent) return true;
return this.shouldUpdatedBySelfProps(nextProps); return this.shouldUpdatedBySelfProps(nextProps);
+2 -1
View File
@@ -1,4 +1,5 @@
import _ from '../utils';
export const matchRow = (keyField, id) => row => row[keyField] === id; export const matchRow = (keyField, id) => row => _.get(row, keyField) === id;
export const getRowByRowId = (data, keyField, id) => data.find(matchRow(keyField, id)); export const getRowByRowId = (data, keyField, id) => data.find(matchRow(keyField, id));
@@ -68,10 +68,6 @@
text-align: center; text-align: center;
} }
tr.expanding-row {
padding: 5px;
}
td.react-bootstrap-table-editing-cell { td.react-bootstrap-table-editing-cell {
.animated { .animated {
animation-fill-mode: both; animation-fill-mode: both;
@@ -161,4 +157,26 @@
animation-name: bounceOut; animation-name: bounceOut;
} }
} }
} .reset-expansion-style{
padding: 0;
}
.row-expansion-style{
padding: 8px;
}
.row-expand-slide-appear{
max-height: 0;
overflow: hidden;
}
.row-expand-slide-appear-active{
max-height: 1000px;
transition: max-height 3s linear;
}
.row-expand-slide-exit{
max-height: 1000px;
}
.row-expand-slide-exit-active{
max-height: 0;
overflow: hidden;
transition: max-height 400ms cubic-bezier(0, 0.95, 0, 0.95)
}
}
@@ -124,10 +124,10 @@ describe('Cell', () => {
onClick: sinon.stub() onClick: sinon.stub()
}; };
}); });
it('should calling custom onClick callback also', () => {
it('should call onStart correctly', () => {
wrapper.find('td').simulate('click'); wrapper.find('td').simulate('click');
expect(onStartCallBack.callCount).toBe(1); expect(onStartCallBack.callCount).toBe(1);
expect(column.events.onClick.callCount).toBe(1);
}); });
}); });
}); });
@@ -164,10 +164,10 @@ describe('Cell', () => {
onDoubleClick: sinon.stub() onDoubleClick: sinon.stub()
}; };
}); });
it('should calling custom onDoubleClick callback also', () => {
it('should call onStart correctly', () => {
wrapper.find('td').simulate('doubleclick'); wrapper.find('td').simulate('doubleclick');
expect(onStartCallBack.callCount).toBe(1); expect(onStartCallBack.callCount).toBe(1);
expect(column.events.onDoubleClick.callCount).toBe(1);
}); });
}); });
}); });
@@ -147,7 +147,7 @@ describe('<SelectionCell />', () => {
/>, />,
{ bootstrap4: false } { bootstrap4: false }
); );
wrapper.find('td').simulate('click'); wrapper.find('td').simulate('click', { stopPropagation: jest.fn() });
}); });
it('should calling handleRowClicked', () => { it('should calling handleRowClicked', () => {
@@ -173,7 +173,7 @@ describe('<SelectionCell />', () => {
/>, />,
{ bootstrap4: false } { bootstrap4: false }
); );
wrapper.find('td').simulate('click'); wrapper.find('td').simulate('click', { stopPropagation: jest.fn() });
}); });
it('should calling handleRowClicked', () => { it('should calling handleRowClicked', () => {
@@ -201,7 +201,7 @@ describe('<SelectionCell />', () => {
it('should be called with correct paramters', () => { it('should be called with correct paramters', () => {
// first click // first click
wrapper.find('td').simulate('click'); wrapper.find('td').simulate('click', { stopPropagation: jest.fn() });
expect(mockOnRowSelect.callCount).toBe(1); expect(mockOnRowSelect.callCount).toBe(1);
expect(mockOnRowSelect.calledWith(rowKey, true, rowIndex)).toBe(true); expect(mockOnRowSelect.calledWith(rowKey, true, rowIndex)).toBe(true);
}); });
@@ -223,9 +223,9 @@ describe('<SelectionCell />', () => {
it('should be called with correct parameters', () => { it('should be called with correct parameters', () => {
// first click // first click
wrapper.find('td').simulate('click'); wrapper.find('td').simulate('click', { stopPropagation: jest.fn() });
expect(mockOnRowSelect.callCount).toBe(1); expect(mockOnRowSelect.callCount).toBe(1);
expect(mockOnRowSelect.calledWith(rowKey, false, rowIndex, undefined)).toBe(true); expect(mockOnRowSelect.calledWith(rowKey, false, rowIndex)).toBe(true);
}); });
}); });
}); });