Compare commits

...
19 Commits
Author SHA1 Message Date
Tanner Linsley a1e724c483 5.5.3 2017-04-17 12:00:29 -06:00
Tanner Linsley 741660c915 Use webpack to compile umd 2017-04-17 12:00:17 -06:00
Tanner Linsley 1f8062501f Better npm scripts for ci and publishing 2017-04-17 11:27:20 -06:00
Tanner Linsley fb51afd0ae Keep tags up to date with releases 2017-04-17 09:30:02 -06:00
Tanner Linsley a64c6a3a76 5.5.2 2017-04-17 09:29:06 -06:00
Tanner Linsley f502ef4e2b Immutablely decorate with _viewIndex
#203
2017-04-17 09:28:31 -06:00
theCmakerandTanner Linsley c58c96c84f Fixed issue #14 Default CSS overwrites the checkbox appearance if included into a custom cell. (#197) 2017-04-17 09:15:53 -06:00
Tanner Linsley 7202776c86 5.5.1 2017-04-13 10:49:15 -06:00
Mike DeVitaandGitHub 734ba48e9c Update ISSUE_TEMPLATE.md
fix the system information section to use bulleted lists
2017-04-10 10:12:04 -07:00
Alejandro BrozzoandTanner Linsley db84ecf789 Fixed code highlights (#179) 2017-04-10 10:21:31 -06:00
AlejandroandTanner Linsley 50668fe90f Avoid page refresh if same page, set NaN to current page (#178)
* Avoid page refresh if same page, set NaN to current page

* Fixed styling rule errors
2017-04-07 17:07:42 -06:00
Aaron SchwartzandGitHub 52f2c9fdac Fix descending sort being non-deterministic
Descending sort would sort differently for the same data on rerender for items that evaluated to the same value.
2017-04-06 15:25:56 -07:00
Tanner Linsley 3b39f523be 5.5.0 2017-04-05 18:51:31 -06:00
Aaron SchwartzandTanner Linsley 9d85981c5b Resize columns (#170)
* Add column resizing for non pivot columns.

* Fixing resizing UI issues and mobile functionality.

* Remove calling onChange during resize events so that server example doesn't refetch data every time a column resizes.
2017-04-05 17:47:55 -06:00
Eric AbbottandTanner Linsley b779a98d7a Change precedence in 'getResolvedState' (#166)
* Change precedence in 'getResolvedState'
  * Previously existing props would overwrite passed in state
  * Now passed in state gets precedence

* added a controlled table example to storybook
2017-04-05 01:10:17 -06:00
Jolyon RussandTanner Linsley 1f4c9afd2b Updated README - wrapped example in render function (#168) 2017-04-04 13:24:03 -06:00
Aaron SchwartzandTanner Linsley cef7fbd780 Add filterRender column option to customize the filter that is shown (#162)
* Add filterRender column option to completely customize the filter that is shown

* Refactor filterRender as a defaultProp.
2017-03-31 15:41:57 -06:00
Tanner Linsley e8ebf7c780 5.4.1 2017-03-30 17:03:47 -06:00
Aaron SchwartzandTanner Linsley ac20220d55 Set page to max page available if data changes and has less pages than before (#160)
* Add column filtering.

* Fix javascript warning from yarn test. Compile storybook and docs.

* Pass standard linting

* Add support for filtering pivot columns.

* Build distribution files.

* Set page to max page available if data changes and has less pages than before.

Closes #159
2017-03-30 17:02:39 -06:00
24 changed files with 837 additions and 226 deletions
+2
View File
@@ -25,6 +25,7 @@ import CustomExpanderPosition from '../stories/CustomExpanderPosition.js'
import NoDataText from '../stories/NoDataText.js'
import Footers from '../stories/Footers.js'
import Filtering from '../stories/Filtering.js'
import ControlledTable from '../stories/ControlledTable.js'
//
configure(() => {
storiesOf('1. Docs')
@@ -55,4 +56,5 @@ configure(() => {
.add('Custom "No Data" Text', NoDataText)
.add('Footers', Footers)
.add('Custom Filtering', Filtering)
.add('Controlled Component', ControlledTable)
}, module)
+1
View File
@@ -14,4 +14,5 @@ h1 {
p {
margin-bottom: 15px;
line-height: 22px;
}
+5 -5
View File
@@ -8,8 +8,8 @@ include a detailed explanation of the problem here...
2. to reproduce the issue
## System Information
**Browser & Browser Version:**
**Node Version:**
**OS Version:**
**NPM Version:**
**Yarn Version:**
* **Browser & Browser Version:**
* **Node Version:**
* **OS Version:**
* **NPM Version:**
* **Yarn Version:**
+56 -34
View File
@@ -90,37 +90,39 @@ import 'react-table/react-table.css'
```javascript
import ReactTable from 'react-table'
const data = [{
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23,
}
},{
...
}]
render() {
const data = [{
name: 'Tanner Linsley',
age: 26,
friend: {
name: 'Jason Maurer',
age: 23,
}
},{
...
}]
const columns = [{
header: 'Name',
accessor: 'name' // String-based value accessors!
}, {
header: 'Age',
accessor: 'age',
render: props => <span className='number'>{props.value}</span> // Custom cell components!
}, {
id: 'friendName', // Required because our accessor is not a string
header: 'Friend Name',
accessor: d => d.friend.name // Custom value accessors!
}, {
header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age'
}]
const columns = [{
header: 'Name',
accessor: 'name' // String-based value accessors!
}, {
header: 'Age',
accessor: 'age',
render: props => <span className='number'>{props.value}</span> // Custom cell components!
}, {
id: 'friendName', // Required because our accessor is not a string
header: 'Friend Name',
accessor: d => d.friend.name // Custom value accessors!
}, {
header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age'
}]
<ReactTable
data={data}
columns={columns}
/>
<ReactTable
data={data}
columns={columns}
/>
}
```
## Data
@@ -151,11 +153,13 @@ These are all of the available props (and their default values) for the main `<R
const id = filter.pivotId || filter.id
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
},
resizable: true,
defaultResizing: [],
// Controlled State Overrides (see Fully Controlled Component section)
page: undefined,
pageSize: undefined,
sorting: undefined
sorting: undefined,
// Controlled State Callbacks
onExpandSubComponent: undefined,
@@ -163,6 +167,7 @@ These are all of the available props (and their default values) for the main `<R
onPageSizeChange: undefined,
onSortingChange: undefined,
onFilteringChange: undefined,
onResize: undefined,
// Pivoting
pivotBy: undefined,
@@ -207,6 +212,7 @@ These are all of the available props (and their default values) for the main `<R
getPaginationProps: () => ({}),
getLoadingProps: () => ({}),
getNoDataProps: () => ({}),
getResizerProps: () => ({}),
// Global Column Defaults
column: {
@@ -229,7 +235,16 @@ These are all of the available props (and their default values) for the main `<R
footerStyle: {},
getFooterProps: () => ({}),
filterMethod: undefined,
hideFilter: false
hideFilter: false,
filterRender: ({filter, onFilterChange}) => (
<input type='text'
style={{
width: '100%'
}}
value={filter ? filter.value : ''}
onChange={(event) => onFilterChange(event.target.value)}
/>
)
},
// Text
@@ -303,7 +318,7 @@ Or just define them as props
columns: [...], // See Header Groups section below
// Footer
footer: 'Header Name' or JSX eg. ({data, column}) => <div>Header Name</div>,
footer: 'Footer Name' or JSX eg. ({data, column}) => <div>Footer Name</div>,
footerClassName: '', // Set the classname of the `td` element of the column's footer
footerStyle: {}, // Set the style of the `td` element of the column's footer
getFooterProps: (state, rowInfo, column, instance) => ({}), // A function that returns props to decorate the `td` element of the column's footer
@@ -313,7 +328,8 @@ Or just define them as props
// filter == an object specifying which filter is being applied. Format: {id: [the filter column's id], value: [the value the user typed in the filter field], pivotId: [if filtering on a pivot column, the pivotId will be set to the pivot column's id and the `id` field will be set to the top level pivoting column]}
// row == the row of data supplied to the table
// column == the column that the filter is on
hideFilter: false // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
hideFilter: false, // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
filterRender: JSX // eg. ({filter, onFilterChange}) => <select onChange={event => onFilterChange(event.target.value)} value={filter ? filter.value : ''}></select> // The value passed to onFilterChange will be the value passed to filter.value of the filterMethod
}]
```
@@ -437,6 +453,8 @@ Every single built-in component's props can be dynamically extended using any on
getTdProps={fn}
getPaginationProps={fn}
getLoadingProps={fn}
getNoDataProps: {fn},
getResizerProps: {fn}
/>
```
@@ -622,7 +640,8 @@ Here are the props and their corresponding callbacks that control the state of t
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data
onSortingChange={(column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held. If the column is a pivoted column, `column` will be an array of columns
onExpandRow={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
onFilteringChange={(column, event) => {...}} // Called when a user enters a value into a filter input field. The event is the onChange event of the input field.
onFilteringChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFilterChange handler by the filterRender option.
onResize={(column, event, isTouch) => {...}} // Called when a user clicks on a resizing component (the right edge of a column header)
/>
```
@@ -675,6 +694,8 @@ By default the table tries to filter by checking if the row's value starts with
If you want to override a particular column's filtering method, you can set the `filterMethod` option on a column.
To completely override the filter that is shown, you can set the `filterRender` column option. Using this option you can specify the JSX that is shown. The option is passed an `onFilterChange` method which must be called with the the value that you wan't to pass to the `filterMethod` option whenever the filter has changed.
See <a href="http://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Custom%20Filtering&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel" target="\_parent">Custom Filtering</a> demo for examples.
## Component Overrides
@@ -697,6 +718,7 @@ Object.assign(ReactTableDefaults, {
NextComponent: undefined,
LoadingComponent: component,
NoDataComponent: component,
ResizerComponent: component
})
// Or change per instance
+1 -1
View File
@@ -16,7 +16,7 @@
<body>
<div id="root"></div>
<div id="error-display"></div>
<script src="static/preview.31fe462e1d0d70b4c4a4.bundle.js"></script>
<script src="static/preview.0cd0bb2bf09f3220bea7.bundle.js"></script>
</body>
</html>
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"version":3,"file":"static/preview.0cd0bb2bf09f3220bea7.bundle.js","sources":["webpack:///static/preview.0cd0bb2bf09f3220bea7.bundle.js"],"mappings":"AAAA;AAkuDA;AA62DA;AAwtFA;AAsiFA;AA0uOA;AAgmGA;AA6rDA;AA0iEA;AA0xDA;AA25DA;AAmqDA;AA0vDA;AA+9CA;AAg5DA;AAwoDA;AAk7CA;AA2pDA;AAmjEA;AA27DA;AAghCA;AA4vDA;AA8kDA;AAwpEA;AAk3DA;AAy0DA;AA8xCA;AAu3EA;AAi4GA;AAwoDA;AAk+CA;AA+oCA;AAutCA;AA4jDA;AAwcA;AA+jFA","sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"version":3,"file":"static/preview.31fe462e1d0d70b4c4a4.bundle.js","sources":["webpack:///static/preview.31fe462e1d0d70b4c4a4.bundle.js"],"mappings":"AAAA;AAkuDA;AAw+DA;AAurFA;AAgmFA;AA87OA;AAuwFA;AA6xDA;AAy/DA;AA+uDA;AAi8DA;AA+lDA;AA4yDA;AA28CA;AAw7DA;AAooDA;AA67CA;AAiqDA;AAynEA;AAwxDA;AA+rCA;AA+mDA;AA2lDA;AAkqEA;AAs2DA;AA2zDA;AAo4CA;AAosFA;AAmjGA;AA2sDA;AA82CA;AAooCA;AAg9CA;AA67CA;AAoDA;AA+jFA","sourceRoot":""}
+6 -9
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "5.4.0",
"version": "5.5.3",
"description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -30,8 +30,10 @@
"watch:node": "onchange 'src/**/*.js' -i -- npm run build:node",
"watch:css": "onchange 'src/**/*.styl' -i -- npm run build:css",
"test": "standard",
"umd": "rimraf react-table.js && browserify lib/index.js -s reactTable -x react -t babelify -g uglifyify -o react-table.js",
"prepublish": "npm-run-all build:* && npm run umd",
"umd": "rimraf react-table.js && webpack --config umd.webpack.js",
"build": "npm-run-all build:*",
"prepublish": "npm run build && npm run umd",
"postpublish": "git push --tags",
"storybook": "start-storybook -p 8000 -c .storybook",
"docs": "build-storybook -o docs && cp .storybook/CNAME docs/CNAME"
},
@@ -49,8 +51,6 @@
"babel-preset-es2015": "6.14.0",
"babel-preset-react": "6.11.1",
"babel-preset-stage-2": "6.13.0",
"babelify": "^7.3.0",
"browserify": "13.1.0",
"github-markdown-css": "^2.4.1",
"html-loader": "^0.4.4",
"markdown-loader": "^0.1.7",
@@ -65,10 +65,7 @@
"standard": "^8.0.0",
"storybook": "^0.0.0",
"stylus": "^0.54.5",
"uglifyify": "3.0.3"
},
"browserify-shim": {
"react": "global:React"
"webpack": "^2.4.1"
},
"standard": {
"parser": "babel-eslint",
+16 -2
View File
@@ -27,6 +27,8 @@ export default {
const id = filter.pivotId || filter.id
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
},
resizable: true,
defaultResizing: [],
// Controlled State Overrides
// page: undefined,
@@ -39,6 +41,7 @@ export default {
onPageSizeChange: undefined,
onSortingChange: undefined,
onFilteringChange: undefined,
onResize: undefined,
// Pivoting
pivotBy: undefined,
@@ -82,6 +85,7 @@ export default {
getPaginationProps: emptyObj,
getLoadingProps: emptyObj,
getNoDataProps: emptyObj,
getResizerProps: emptyObj,
// Global Column Defaults
column: {
@@ -104,7 +108,16 @@ export default {
footerStyle: {},
getFooterProps: emptyObj,
filterMethod: undefined,
hideFilter: false
hideFilter: false,
filterRender: ({filter, onFilterChange}) => (
<input type='text'
style={{
width: '100%'
}}
value={filter ? filter.value : ''}
onChange={(event) => onFilterChange(event.target.value)}
/>
)
},
// Text
@@ -161,5 +174,6 @@ export default {
</div>
</div>
),
NoDataComponent: _.makeTemplateComponent('rt-noData')
NoDataComponent: _.makeTemplateComponent('rt-noData'),
ResizerComponent: _.makeTemplateComponent('rt-resizer')
}
+112 -67
View File
@@ -39,18 +39,21 @@ export default React.createClass({
getPaginationProps,
getLoadingProps,
getNoDataProps,
getResizerProps,
showPagination,
expanderColumnWidth,
manual,
loadingText,
noDataText,
showFilters,
resizable,
// State
loading,
pageSize,
page,
sorting,
filtering,
resizing,
pages,
// Pivoting State
pivotValKey,
@@ -71,6 +74,7 @@ export default React.createClass({
LoadingComponent,
SubComponent,
NoDataComponent,
ResizerComponent,
// Data model
resolvedData,
allVisibleColumns,
@@ -83,30 +87,39 @@ export default React.createClass({
// Pagination
const startRow = pageSize * page
const endRow = startRow + pageSize
const pageRows = manual ? resolvedData : sortedData.slice(startRow, endRow)
let pageRows = manual ? resolvedData : sortedData.slice(startRow, endRow)
const minRows = this.getMinRows()
const padRows = _.range(Math.max(minRows - pageRows.length, 0))
const hasColumnFooter = allVisibleColumns.some(d => d.footer)
const recurseRowsViewIndex = (rows, path = [], index = -1) => {
rows.forEach((row, i) => {
index++
row._viewIndex = index
const newPath = path.concat([i])
if (row[subRowsKey] && _.get(expandedRows, newPath)) {
index = recurseRowsViewIndex(row[subRowsKey], newPath, index)
}
})
return index
return [
rows.map((row, i) => {
index++
const rowWithViewIndex = {
...row,
_viewIndex: index
}
const newPath = path.concat([i])
if (rowWithViewIndex[subRowsKey] && _.get(expandedRows, newPath)) {
[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index)
}
return rowWithViewIndex
}),
index
]
}
recurseRowsViewIndex(pageRows)
[pageRows] = recurseRowsViewIndex(pageRows)
const canPrevious = page > 0
const canNext = page + 1 < pages
const rowMinWidth = _.sum(allVisibleColumns.map(d => _.getFirstDefined(d.width, d.minWidth)))
const rowMinWidth = _.sum(allVisibleColumns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.minWidth)
}))
let rowIndex = -1
@@ -149,9 +162,18 @@ export default React.createClass({
}
const makeHeaderGroup = (column, i) => {
const flex = _.sum(column.columns.map(d => d.width ? 0 : d.minWidth))
const width = _.sum(column.columns.map(d => _.getFirstDefined(d.width, d.minWidth)))
const maxWidth = _.sum(column.columns.map(d => _.getFirstDefined(d.width, d.maxWidth)))
const flex = _.sum(column.columns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return d.width || resized.value ? 0 : d.minWidth
}))
const width = _.sum(column.columns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.minWidth)
}))
const maxWidth = _.sum(column.columns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.maxWidth)
}))
const theadGroupThProps = _.splitProps(getTheadGroupThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -255,10 +277,11 @@ export default React.createClass({
}
const makeHeader = (column, i) => {
const resized = resizing.find(x => x.id === column.id) || {}
const sort = sorting.find(d => d.id === column.id)
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(column.width, column.minWidth)
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
const theadThProps = _.splitProps(getTheadThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -279,6 +302,14 @@ export default React.createClass({
...columnHeaderProps.rest
}
const resizer = resizable ? (
<ResizerComponent
onMouseDown={e => this.resizeColumnStart(column, e, false)}
onTouchStart={e => this.resizeColumnStart(column, e, true)}
{...resizerProps}
/>
) : null
if (column.expander) {
if (column.pivotColumns) {
const pivotSort = sorting.find(d => d.id === column.id)
@@ -287,6 +318,7 @@ export default React.createClass({
key={i}
className={classnames(
'rt-pivot-header',
'rt-resizable-header',
column.sortable && '-cursor-pointer',
classes,
pivotSort ? (pivotSort.desc ? '-sort-desc' : '-sort-asc') : ''
@@ -302,19 +334,22 @@ export default React.createClass({
}}
{...rest}
>
{column.pivotColumns.map((pivotColumn, i) => {
return (
<span key={pivotColumn.id}>
{_.normalizeComponent(pivotColumn.header, {
data: sortedData,
column: column
})}
{i < column.pivotColumns.length - 1 && (
<ExpanderComponent />
)}
</span>
)
})}
<div className='rt-resizable-header-content'>
{column.pivotColumns.map((pivotColumn, i) => {
return (
<span key={pivotColumn.id}>
{_.normalizeComponent(pivotColumn.header, {
data: sortedData,
column: column
})}
{i < column.pivotColumns.length - 1 && (
<ExpanderComponent />
)}
</span>
)
})}
</div>
{resizer}
</ThComponent>
)
}
@@ -340,6 +375,7 @@ export default React.createClass({
key={i}
className={classnames(
classes,
'rt-resizable-header',
sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '',
column.sortable && '-cursor-pointer',
!show && '-hidden',
@@ -355,10 +391,13 @@ export default React.createClass({
}}
{...rest}
>
{_.normalizeComponent(column.header, {
data: sortedData,
column: column
})}
<div className='rt-resizable-header-content'>
{_.normalizeComponent(column.header, {
data: sortedData,
column: column
})}
</div>
{resizer}
</ThComponent>
)
}
@@ -387,8 +426,9 @@ export default React.createClass({
}
const makeFilter = (column, i) => {
const width = _.getFirstDefined(column.width, column.minWidth)
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
const resized = resizing.find(x => x.id === column.id) || {}
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
const theadFilterThProps = _.splitProps(getTheadFilterThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -417,16 +457,16 @@ export default React.createClass({
const filter = filtering.find(filter => filter.id === column.id && filter.pivotId === col.id)
pivotCols.push(
<span key={col.id}
style={{display: 'flex', alignContent: 'flex-end', flex: 1}}>
style={{flex: 1}}>
{!col.hideFilter ? (
<input type='text'
style={{
flex: 1,
width: 20
}}
value={filter ? filter.value : ''}
onChange={(event) => this.filterColumn(column, event, col)}
/>
_.normalizeComponent(col.filterRender,
{
col,
filter,
onFilterChange: (value) => (this.filterColumn(column, value, col))
},
defaults.column.filterRender
)
) : null}
</span>
)
@@ -489,13 +529,14 @@ export default React.createClass({
{...rest}
>
{!column.hideFilter ? (
<input type='text'
style={{
width: `100%`
}}
value={filter ? filter.value : ''}
onChange={(event) => this.filterColumn(column, event)}
/>
_.normalizeComponent(column.filterRender,
{
column,
filter,
onFilterChange: (value) => (this.filterColumn(column, value))
},
defaults.column.filterRender
)
) : null}
</ThComponent>
)
@@ -529,9 +570,10 @@ export default React.createClass({
{...trProps.rest}
>
{allVisibleColumns.map((column, i2) => {
const resized = resizing.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(column.width, column.minWidth)
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
const tdProps = _.splitProps(getTdProps(finalState, rowInfo, column, this))
const columnProps = _.splitProps(column.getProps(finalState, rowInfo, column, this))
@@ -593,15 +635,15 @@ export default React.createClass({
{...rowInfo}
value={rowInfo.rowValues[pivotValKey]}
/>
) : <span>{row[pivotValKey]} ({rowInfo.subRows.length})</span>}
) : <span>{row[pivotValKey]} ({rowInfo.subRows.length})</span>}
</span>
) : SubComponent ? (
<span>
<ExpanderComponent
isExpanded={isExpanded}
/>
</span>
) : null}
) : SubComponent ? (
<span>
<ExpanderComponent
isExpanded={isExpanded}
/>
</span>
) : null}
</TdComponent>
)
}
@@ -680,9 +722,10 @@ export default React.createClass({
style={trProps.style || {}}
>
{allVisibleColumns.map((column, i2) => {
const resized = resizing.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(column.width, column.minWidth)
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this))
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
@@ -742,9 +785,10 @@ export default React.createClass({
{...tFootTrProps.rest}
>
{allVisibleColumns.map((column, i2) => {
const resized = resizing.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(column.width, column.minWidth)
const maxWidth = _.getFirstDefined(column.width, column.maxWidth)
const width = _.getFirstDefined(resized.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth)
const tFootTdProps = _.splitProps(getTfootTdProps(finalState, undefined, undefined, this))
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
const columnFooterProps = _.splitProps(column.getFooterProps(finalState, undefined, column, this))
@@ -840,6 +884,7 @@ export default React.createClass({
const paginationProps = _.splitProps(getPaginationProps(finalState, undefined, undefined, this))
const loadingProps = getLoadingProps(finalState, undefined, undefined, this)
const noDataProps = getNoDataProps(finalState, undefined, undefined, this)
const resizerProps = getResizerProps(finalState, undefined, undefined, this)
const makeTable = () => (
<div
@@ -887,7 +932,7 @@ export default React.createClass({
style={paginationProps.style}
{...paginationProps.rest}
/>
) : null}
) : null}
{!pageRows.length && (
<NoDataComponent
{...noDataProps}
+33 -1
View File
@@ -18,6 +18,11 @@ $expandSize = 7px
.rt-thead
display: flex
flex-direction: column
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
&.-headerGroups
background: alpha(black, .03)
border-bottom: 1px solid alpha(black, .05)
@@ -36,6 +41,9 @@ $expandSize = 7px
.rt-th
.rt-td
padding: 5px 5px
line-height: normal
position: relative
border-right: 1px solid alpha(black, .05)
transition box-shadow .3s $easeOutBack
box-shadow:inset 0 0 0 0 transparent
@@ -47,6 +55,16 @@ $expandSize = 7px
cursor: pointer
&:last-child
border-right: 0
.rt-resizable-header
overflow: visible
&:last-child
overflow: hidden
.rt-resizable-header-content
overflow: hidden
text-overflow: ellipsis
.rt-tbody
display: flex
flex-direction: column
@@ -105,6 +123,17 @@ $expandSize = 7px
cursor: pointer
&.-open:after
transform: translate(-50%, -50%) rotate(0deg)
.rt-resizer
display: inline-block
position: absolute
width: 36px
top: 0
bottom: 0
right: -18px
cursor: col-resize
z-index: 10
.rt-tfoot
display: flex
flex-direction: column
@@ -231,7 +260,6 @@ $expandSize = 7px
input
select
appearance: none
border: 1px solid rgba(0,0,0,0.1)
background: white
padding: 5px 7px
@@ -240,6 +268,10 @@ $expandSize = 7px
font-weight: normal
outline:none
input:not([type="checkbox"]):not([type="radio"])
select
appearance: none
.select-wrap
position:relative
display:inline-block
+6 -2
View File
@@ -12,15 +12,18 @@ export default {
pageSize: this.props.defaultPageSize || 10,
sorting: this.props.defaultSorting,
expandedRows: {},
filtering: this.props.defaultFiltering
filtering: this.props.defaultFiltering,
resizing: this.props.defaultResizing,
currentlyResizing: undefined,
skipNextSort: false
}
},
getResolvedState (props, state) {
const resolvedState = {
..._.compactObject(this.state),
..._.compactObject(state),
..._.compactObject(this.props),
..._.compactObject(state),
..._.compactObject(props)
}
return resolvedState
@@ -105,6 +108,7 @@ export default {
// Calculate pageSize all the time
if (newResolvedState.sortedData) {
newResolvedState.pages = newResolvedState.manual ? newResolvedState.pages : Math.ceil(newResolvedState.sortedData.length / newResolvedState.pageSize)
newResolvedState.page = Math.max(newResolvedState.page >= newResolvedState.pages ? newResolvedState.pages - 1 : newResolvedState.page, 0)
}
return this.setState(newResolvedState, cb)
+111 -23
View File
@@ -10,10 +10,7 @@ export default {
pivotValKey,
subRowsKey,
expanderColumnWidth,
SubComponent,
page,
pages,
pageSize
SubComponent
} = newState
// Determine Header Groups
@@ -192,14 +189,14 @@ export default {
// Group the rows together for this level
let groupedRows = Object.entries(
_.groupBy(rows, keys[i]))
.map(([key, value]) => {
return {
[pivotIDKey]: keys[i],
[pivotValKey]: key,
[keys[i]]: key,
[subRowsKey]: value
}
})
.map(([key, value]) => {
return {
[pivotIDKey]: keys[i],
[pivotValKey]: key,
[keys[i]]: key,
[subRowsKey]: value
}
})
// Recurse into the subRows
groupedRows = groupedRows.map(rowGroup => {
let subRows = groupRecursively(rowGroup[subRowsKey], keys, i + 1)
@@ -214,9 +211,6 @@ export default {
resolvedData = groupRecursively(resolvedData, pivotBy)
}
const newPages = _.getFirstDefined(pages, Math.ceil(resolvedData.length / pageSize))
const newPage = page > newPages ? newPage - 1 : page
return {
...newState,
resolvedData,
@@ -224,8 +218,7 @@ export default {
allVisibleColumns,
headerGroups,
allDecoratedColumns,
hasHeaderGroups,
page: Math.max(newPage, 0)
hasHeaderGroups
}
},
getSortedData (resolvedState) {
@@ -363,7 +356,19 @@ export default {
})
},
sortColumn (column, additive) {
const {sorting} = this.getResolvedState()
const {sorting, skipNextSort} = this.getResolvedState()
// we can't stop event propagation from the column resize move handlers
// attached to the document because of react's synthetic events
// so we have to prevent the sort function from actually sorting
// if we click on the column resize element within a header.
if (skipNextSort) {
this.setStateWithData({
skipNextSort: false
})
return
}
const {onSortingChange} = this.props
if (onSortingChange) {
return onSortingChange(column, additive)
@@ -447,12 +452,12 @@ export default {
this.fireOnChange()
})
},
filterColumn (column, event, pivotColumn) {
filterColumn (column, value, pivotColumn) {
const {filtering} = this.getResolvedState()
const {onFilteringChange} = this.props
if (onFilteringChange) {
return onFilteringChange(column, event)
return onFilteringChange(column, value, pivotColumn)
}
// Remove old filter first if it exists
@@ -468,19 +473,102 @@ export default {
}
})
if (event.target.value !== '') {
if (value !== '') {
newFiltering.push({
id: column.id,
value: event.target.value,
value: value,
pivotId: pivotColumn ? pivotColumn.id : undefined
})
}
this.setStateWithData({
page: 0,
filtering: newFiltering
}, () => {
this.fireOnChange()
})
},
resizeColumnStart (column, event, isTouch) {
const {onResize} = this.props
if (onResize) {
return onResize(column, event, isTouch)
}
const parentWidth = event.target.parentElement.getBoundingClientRect().width
let pageX
if (isTouch) {
pageX = event.changedTouches[0].pageX
} else {
pageX = event.pageX
}
this.setStateWithData({
currentlyResizing: {
id: column.id,
startX: pageX,
parentWidth: parentWidth
}
}, () => {
if (isTouch) {
document.addEventListener('touchmove', this.resizeColumnMoving)
document.addEventListener('touchcancel', this.resizeColumnEnd)
document.addEventListener('touchend', this.resizeColumnEnd)
} else {
document.addEventListener('mousemove', this.resizeColumnMoving)
document.addEventListener('mouseup', this.resizeColumnEnd)
document.addEventListener('mouseleave', this.resizeColumnEnd)
}
})
},
resizeColumnEnd (event) {
let isTouch = event.type === 'touchend' || event.type === 'touchcancel'
if (isTouch) {
document.removeEventListener('touchmove', this.resizeColumnMoving)
document.removeEventListener('touchcancel', this.resizeColumnEnd)
document.removeEventListener('touchend', this.resizeColumnEnd)
}
// If its a touch event clear the mouse one's as well because sometimes
// the mouseDown event gets called as well, but the mouseUp event doesn't
document.removeEventListener('mousemove', this.resizeColumnMoving)
document.removeEventListener('mouseup', this.resizeColumnEnd)
document.removeEventListener('mouseleave', this.resizeColumnEnd)
// The touch events don't propagate up to the sorting's onMouseDown event so
// no need to prevent it from happening or else the first click after a touch
// event resize will not sort the column.
if (!isTouch) {
this.setStateWithData({
skipNextSort: true
})
}
},
resizeColumnMoving (event) {
const {resizing, currentlyResizing} = this.getResolvedState()
// Delete old value
const newResizing = resizing.filter(x => x.id !== currentlyResizing.id)
let pageX
if (event.type === 'touchmove') {
pageX = event.changedTouches[0].pageX
} else if (event.type === 'mousemove') {
pageX = event.pageX
}
// Set the min size to 10 to account for margin and border or else the group headers don't line up correctly
const newWidth = Math.max(currentlyResizing.parentWidth + pageX - currentlyResizing.startX, 11)
newResizing.push({
id: currentlyResizing.id,
value: newWidth
})
this.setStateWithData({
resizing: newResizing
})
}
}
+6 -1
View File
@@ -17,12 +17,17 @@ export default React.createClass({
this.setState({page: nextProps.page})
},
getSafePage (page) {
if (isNaN(page)) {
page = this.props.page
}
return Math.min(Math.max(page, 0), this.props.pages - 1)
},
changePage (page) {
page = this.getSafePage(page)
this.setState({page})
this.props.onPageChange(page)
if (this.props.page !== page) {
this.props.onPageChange(page)
}
},
applyPage (e) {
e && e.preventDefault()
+1 -1
View File
@@ -80,7 +80,7 @@ function orderBy (arr, funcs, dirs) {
}
return dirs[0]
? a.__index - b.__index
: b.__index - b.__index
: b.__index - a.__index
})
}
+1
View File
@@ -161,6 +161,7 @@ const columns = [{
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
+153
View File
@@ -0,0 +1,153 @@
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index'
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
class ControlledTable extends React.Component {
constructor() {
super()
this.sortChange = this.sortChange.bind(this)
this.state = {
sorting: [],
page: 0,
pageSize: 10
}
}
sortChange(column, shift) {
if(shift)
alert('Shift click not implemented in this demo')
var sort = {id: column.id}
if(this.state.sorting.length && this.state.sorting[0].id == column.id)
this.state.sorting[0].asc ? sort.desc = true : sort.asc = true
else
sort.asc = true
this.setState({
sorting: [sort]
})
}
render() {
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
sorting={this.state.sorting}
onSortingChange={this.sortChange}
page={this.state.page}
onPageChange={page => this.setState({page})}
pageSize={this.state.pageSize}
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: For simplicity, multi-sort is not implemented in this demo</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
}
}
function getCode () {
return `const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
class ControlledTable extends React.Component {
constructor() {
super()
this.sortChange = this.sortChange.bind(this)
this.state = {
sorting: [],
page: 0,
pageSize: 10
}
}
sortChange(column, shift) {
if(shift)
alert('Shift click not implemented in this demo')
var sort = {id: column.id}
if(this.state.sorting.length && this.state.sorting[0].id == column.id)
this.state.sorting[0].asc ? sort.desc = true : sort.asc = true
else
sort.asc = true
this.setState({
sorting: [sort]
})
}
render() {
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
sorting={this.state.sorting}
onSortingChange={this.sortChange}
page={this.state.page}
onPageChange={page => this.setState({page})}
pageSize={this.state.pageSize}
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
/>
)
}
}`
}
export default () => <ControlledTable />
+77 -19
View File
@@ -7,7 +7,7 @@ import ReactTable from '../src/index'
class Filtering extends React.Component {
constructor(props) {
constructor (props) {
super(props)
const data = _.map(_.range(5553), d => {
@@ -33,10 +33,10 @@ class Filtering extends React.Component {
data: data
}
this.setTableOption = this.setTableOption.bind(this);
this.setTableOption = this.setTableOption.bind(this)
}
render() {
render () {
const columns = [{
header: 'Name',
columns: [{
@@ -54,26 +54,51 @@ class Filtering extends React.Component {
columns: [{
header: 'Age',
accessor: 'age'
}]
}, {
header: 'Over 21',
accessor: 'age',
id: 'over',
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
filterMethod: (filter, row) => {
if (filter.value === 'all') {
return true
}
if (filter.value === 'true') {
return row[filter.id] >= 21
}
return row[filter.id] < 21
},
filterRender: ({filter, onFilterChange}) => (
<select
onChange={event => onFilterChange(event.target.value)}
style={{width: '100%'}}
value={filter ? filter.value : 'all'}>
<option value="all"></option>
<option value="true">Can Drink</option>
<option value="false">Can't Drink</option>
</select>
)
}
]
}]
return (
<div>
<div style={{float: "left"}}>
<div style={{float: 'left'}}>
<h1>Table Options</h1>
<table>
<tbody>
{
Object.keys(this.state.tableOptions).map(optionKey => {
const optionValue = this.state.tableOptions[optionKey];
const optionValue = this.state.tableOptions[optionKey]
return (
<tr key={optionKey}>
<td>{optionKey}</td>
<td style={{paddingLeft: 10, paddingTop: 5}}>
<input type="checkbox"
name={optionKey}
checked={optionValue}
onChange={this.setTableOption}
name={optionKey}
checked={optionValue}
onChange={this.setTableOption}
/>
</td>
</tr>
@@ -122,21 +147,30 @@ class Filtering extends React.Component {
</div>
<div>
<h1>Custom Filters In This Example</h1>
<p>The default filter for all columns of a table if it is not specified in the configuration is set to match on values that start with the filter text. Example: age.startsWith("2").</p>
<p>This example overrides the default filter behavior by setting the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the filter text. Example: age == "23")</p>
<p>The default filter for all columns of a table if it is not specified in the configuration is set to match
on values that start with the filter text. Example: age.startsWith("2").</p>
<p>This example overrides the default filter behavior by setting
the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the
filter text. Example: age == "23")</p>
<p>Each column can also be customized with the column <strong>filterMethod</strong> option:</p>
<p>In this example the firstName column filters on the value starting with and ending with the filter value.</p>
<p>In this example the lastName column filters on the value including the filter value anywhere in its text.</p>
<p>In this example the firstName column filters on the value starting with and ending with the filter
value.</p>
<p>In this example the lastName column filters on the value including the filter value anywhere in its
text.</p>
<p>To completely override the filter that is shown, you can set the <strong>filterRender</strong> column
option. Using this option you can specify the JSX that is shown. The option is passed
an <strong>onFilterChange</strong> method that must be called with the value that you wan't to
pass to the <strong>filterMethod</strong> option whenever the filter has changed.</p>
</div>
<CodeHighlight>{() => this.getCode()}</CodeHighlight>
</div>
)
}
setTableOption(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
setTableOption (event) {
const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name
this.setState({
tableOptions: {
...this.state.tableOptions,
@@ -145,7 +179,7 @@ class Filtering extends React.Component {
})
}
getCode() {
getCode () {
return `
const columns = [{
header: 'Name',
@@ -164,6 +198,30 @@ const columns = [{
columns: [{
header: 'Age',
accessor: 'age'
}, {
header: 'Over 21',
accessor: 'age',
id: 'over',
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
filterMethod: (filter, row) => {
if (filter.value === 'all') {
return true
}
if (filter.value === 'true') {
return row[filter.id] >= 21
}
return row[filter.id] < 21
},
filterRender: ({filter, onFilterChange}) => (
<select
onChange={event => onFilterChange(event.target.value)}
style={{width: '100%'}}
value={filter ? filter.value : 'all'}>
<option value="all"></option>
<option value="true">Can Drink</option>
<option value="false">Can't Drink</option>
</select>
)
}]
}]
@@ -203,4 +261,4 @@ export default (
}
}
export default () => <Filtering/>
export default () => <Filtering />
+32 -3
View File
@@ -88,23 +88,52 @@ const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
accessor: 'firstName',
footer: (
<span><strong>Popular:</strong> {
_.first(
_.reduce(
_.map(
_.groupBy(
data, d => d.firstName
)
),
(a, b) => a.length > b.length ? a : b
)
).firstName}
</span>
)
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
accessor: d => d.lastName,
footer: (
<span><strong>Longest:</strong> {
_.reduce(
_.map(
_.groupBy(
data, d => d.lastName
),
(d, key) => key
),
(a, b) => a.length > b.length ? a : b
)}
</span>
)
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
accessor: 'age',
footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
}]
}]
// Display your table!
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
+1
View File
@@ -77,6 +77,7 @@ const columns = [{
// Display your table!
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
+20
View File
@@ -0,0 +1,20 @@
const webpack = require('webpack')
module.exports = {
entry: './lib/index.js',
output: {
filename: './react-table.js',
libraryTarget: 'umd',
library: 'ReactTable'
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
}
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
+159 -20
View File
@@ -121,6 +121,12 @@ accepts@~1.3.3:
mime-types "~2.1.11"
negotiator "0.6.1"
acorn-dynamic-import@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
dependencies:
acorn "^4.0.3"
acorn-globals@^1.0.4:
version "1.0.9"
resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf"
@@ -145,10 +151,14 @@ acorn@^3.0.0, acorn@^3.0.4, acorn@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
acorn@^4.0.1:
acorn@^4.0.1, acorn@^4.0.3:
version "4.0.4"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
acorn@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
airbnb-js-shims@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-1.0.1.tgz#7d5a7d772c8c6fdeb624ea3cef62506091b180b5"
@@ -162,7 +172,7 @@ airbnb-js-shims@^1.0.1:
string.prototype.padend "^3.0.0"
string.prototype.padstart "^3.0.0"
ajv-keywords@^1.0.0:
ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
@@ -344,6 +354,12 @@ async@^1.3.0, async@^1.4.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.1.2:
version "2.3.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
dependencies:
lodash "^4.14.0"
async@~0.2.6:
version "0.2.10"
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
@@ -1445,7 +1461,7 @@ buffer-xor@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
buffer@^4.1.0, buffer@^4.9.0:
buffer@^4.1.0, buffer@^4.3.0, buffer@^4.9.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
dependencies:
@@ -1550,7 +1566,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chokidar@^1.0.0, chokidar@^1.5.1, chokidar@~1.6.0:
chokidar@^1.0.0, chokidar@^1.4.3, chokidar@^1.5.1, chokidar@~1.6.0:
version "1.6.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
dependencies:
@@ -1845,7 +1861,7 @@ crypto-browserify@3.3.0:
ripemd160 "0.2.0"
sha.js "2.2.6"
crypto-browserify@^3.0.0:
crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
version "3.11.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522"
dependencies:
@@ -2175,6 +2191,15 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
enhanced-resolve@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.1.0.tgz#9f4b626f577245edcf4b2ad83d86e17f4f421dec"
dependencies:
graceful-fs "^4.1.2"
memory-fs "^0.4.0"
object-assign "^4.0.1"
tapable "^0.2.5"
enhanced-resolve@~0.9.0:
version "0.9.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
@@ -3355,7 +3380,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
json5@^0.5.0:
json5@^0.5.0, json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
@@ -3437,6 +3462,10 @@ load-json-file@^1.0.0:
pinkie-promise "^2.0.0"
strip-bom "^2.0.0"
loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
loader-utils@0.2.x, loader-utils@^0.2.11, loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^0.2.7, loader-utils@~0.2.2, loader-utils@~0.2.5:
version "0.2.16"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d"
@@ -3514,7 +3543,7 @@ lodash.uniq@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
lodash@4.x.x, lodash@^4.0.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
lodash@4.x.x, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -3598,16 +3627,16 @@ memory-fs@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
memory-fs@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
memory-fs@^0.4.0, memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
dependencies:
errno "^0.1.3"
readable-stream "^2.0.1"
memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
memory-fs@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
dependencies:
errno "^0.1.3"
readable-stream "^2.0.1"
@@ -3817,6 +3846,34 @@ node-libs-browser@^0.7.0:
util "^0.10.3"
vm-browserify "0.0.4"
node-libs-browser@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.0.0.tgz#a3a59ec97024985b46e958379646f96c4b616646"
dependencies:
assert "^1.1.1"
browserify-zlib "^0.1.4"
buffer "^4.3.0"
console-browserify "^1.1.0"
constants-browserify "^1.0.0"
crypto-browserify "^3.11.0"
domain-browser "^1.1.1"
events "^1.0.0"
https-browserify "0.0.1"
os-browserify "^0.2.0"
path-browserify "0.0.0"
process "^0.11.0"
punycode "^1.2.4"
querystring-es3 "^0.2.0"
readable-stream "^2.0.5"
stream-browserify "^2.0.1"
stream-http "^2.3.1"
string_decoder "^0.10.25"
timers-browserify "^2.0.2"
tty-browserify "0.0.0"
url "^0.11.0"
util "^0.10.3"
vm-browserify "0.0.4"
node-pre-gyp@^0.6.29:
version "0.6.32"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.32.tgz#fc452b376e7319b3d255f5f34853ef6fd8fe1fd5"
@@ -4958,15 +5015,15 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
rimraf@2, rimraf@^2.2.8, rimraf@~2.5.1, rimraf@~2.5.4:
version "2.5.4"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
rimraf@2, rimraf@^2.2.8, rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"
rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
rimraf@~2.5.1, rimraf@~2.5.4:
version "2.5.4"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
dependencies:
glob "^7.0.5"
@@ -5160,6 +5217,10 @@ source-list-map@^0.1.4, source-list-map@~0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
source-list-map@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.1.tgz#1a33ac210ca144d1e561f906ebccab5669ff4cb4"
source-map-support@^0.4.2:
version "0.4.10"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.10.tgz#d7b19038040a14c0837a18e630a196453952b378"
@@ -5299,7 +5360,7 @@ strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
string-width@^1.0.1:
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
dependencies:
@@ -5442,6 +5503,10 @@ tapable@^0.1.8, tapable@~0.1.8:
version "0.1.10"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
tapable@^0.2.5, tapable@~0.2.5:
version "0.2.6"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.6.tgz#206be8e188860b514425375e6f1ae89bfb01fd8d"
tar-pack@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae"
@@ -5562,6 +5627,15 @@ uglify-js@2.7.x, uglify-js@2.x.x, uglify-js@~2.7.3:
uglify-to-browserify "~1.0.0"
yargs "~3.10.0"
uglify-js@^2.8.5:
version "2.8.22"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-to-browserify@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
@@ -5693,6 +5767,14 @@ watchpack@^0.2.1:
chokidar "^1.0.0"
graceful-fs "^4.1.2"
watchpack@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87"
dependencies:
async "^2.1.2"
chokidar "^1.4.3"
graceful-fs "^4.1.2"
webidl-conversions@^3.0.0, webidl-conversions@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
@@ -5722,6 +5804,13 @@ webpack-hot-middleware@^2.13.2:
querystring "^0.2.0"
strip-ansi "^3.0.0"
webpack-sources@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb"
dependencies:
source-list-map "^1.1.1"
source-map "~0.5.3"
webpack@^1.13.1:
version "1.14.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-1.14.0.tgz#54f1ffb92051a328a5b2057d6ae33c289462c823"
@@ -5742,6 +5831,32 @@ webpack@^1.13.1:
watchpack "^0.2.1"
webpack-core "~0.6.9"
webpack@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.4.1.tgz#15a91dbe34966d8a4b99c7d656efd92a2e5a6f6a"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
ajv "^4.7.0"
ajv-keywords "^1.1.1"
async "^2.1.2"
enhanced-resolve "^3.0.0"
interpret "^1.0.0"
json-loader "^0.5.4"
json5 "^0.5.1"
loader-runner "^2.3.0"
loader-utils "^0.2.16"
memory-fs "~0.4.1"
mkdirp "~0.5.0"
node-libs-browser "^2.0.0"
source-map "^0.5.3"
supports-color "^3.1.0"
tapable "~0.2.5"
uglify-js "^2.8.5"
watchpack "^1.3.1"
webpack-sources "^0.2.3"
yargs "^6.0.0"
whatwg-encoding@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4"
@@ -5857,6 +5972,12 @@ yargs-parser@^2.4.1:
camelcase "^3.0.0"
lodash.assign "^4.0.6"
yargs-parser@^4.2.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
dependencies:
camelcase "^3.0.0"
yargs@^4.7.1:
version "4.8.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
@@ -5876,6 +5997,24 @@ yargs@^4.7.1:
y18n "^3.2.1"
yargs-parser "^2.4.1"
yargs@^6.0.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
dependencies:
camelcase "^3.0.0"
cliui "^3.2.0"
decamelize "^1.1.1"
get-caller-file "^1.0.1"
os-locale "^1.4.0"
read-pkg-up "^1.0.1"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^1.0.2"
which-module "^1.0.0"
y18n "^3.2.1"
yargs-parser "^4.2.0"
yargs@~3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"