Compare commits

...
Author SHA1 Message Date
Aaron Schwartz ad803c2d6d Remove unused prop from readme. 2017-05-11 12:03:02 -07:00
Aaron Schwartz 4a9ab56cae Remove unused prop 2017-05-11 12:02:10 -07:00
Aaron Schwartz 080e82abfe Cleanup Changelog and lint errors 2017-05-11 12:00:50 -07:00
Aaron Schwartz e3753d1733 Rename showFilters->filterable, hideFilter->filterable 2017-05-11 11:38:11 -07:00
Aaron Schwartz 8f0fb3536e Standardize global and column level resizable and sortable properties 2017-05-11 09:38:15 -07:00
Aaron Schwartz c5ce633049 Cleanup Readme 2017-05-11 08:50:07 -07:00
Aaron Schwartz ea2968b14c Rename onExpanded->onExpandedChange 2017-05-10 16:56:40 -07:00
Aaron Schwartz 171ff37bcd Rename resizing->resized, defaultResizing->defaultResized, onResize->onResizedChange 2017-05-10 16:52:45 -07:00
Aaron Schwartz 7e0bca8a17 Rename expandedRows->expanded, onExpandRow->onExpanded 2017-05-10 16:37:26 -07:00
Aaron Schwartz e9c27952b5 filtering->filtered, onFilteringChange->onFilteredChange, defaultFiltering->defaultFiltered 2017-05-10 16:28:02 -07:00
Aaron Schwartz e9bdc8e3c6 Rename sorting->sorted, onSortingChange->onSortedChange, defaultSorting->defaultSorted 2017-05-10 16:14:51 -07:00
Aaron Schwartz 6be71dc4a1 Add defaultExpanded prop 2017-05-10 15:52:34 -07:00
Tanner Linsley cfdc688501 Handle edge cases in expandable hover states and event handlers 2017-05-10 15:48:29 -06:00
Tanner Linsley 7c7e688811 Use Correct PivotingOptions source 2017-05-10 15:47:46 -06:00
Tanner Linsley 9cb9b2ba75 6.0.0 2017-05-10 15:24:36 -06:00
Tanner Linsley bdefce7e03 Updated Changelog 2017-05-10 15:23:38 -06:00
Tanner Linsley 31e852f387 Fix SubComponent Story 2017-05-10 15:21:40 -06:00
Tanner Linsley dff84eb368 Finish fixing up stories with better source 2017-05-10 14:42:13 -06:00
Tanner Linsley bdf759c8f8 Better custom sorting 2017-05-10 13:57:34 -06:00
Aaron Schwartz 53c6d17b40 Fix up stories. 2017-05-09 16:45:58 -07:00
Tanner Linsley 0191b3bc55 Trying generalize expanders to work on any column 2017-05-09 13:40:35 -06:00
Tanner Linsley ad7ea2f5d3 Remove console.log 2017-05-09 13:15:14 -06:00
Tanner Linsley c24cc37c7d +Key constants, prop/callback changes, controllable filters and resizing, subRow + pivoting expansion 2017-05-09 13:12:18 -06:00
Tanner Linsley 307d37421e Resizing Fixes, custom sorting, new api names 2017-05-09 01:23:04 -06:00
Tanner Linsley 2d35148c75 Fixed Typo 2017-05-08 17:27:34 -06:00
Tanner Linsley c90914f585 Updated Renderer Keys and Stories (+ story cleanup) 2017-05-08 17:26:18 -06:00
Tanner Linsley d236097201 Better expanding and aggregation control 2017-05-08 16:24:35 -06:00
Tanner Linsley 3babdd1f66 Use separate columns for Pivots and Expanders, more render options 2017-05-08 14:54:32 -06:00
40 changed files with 2126 additions and 2801 deletions
+4
View File
@@ -13,6 +13,7 @@ import Readme from '../README.md'
import Simple from '../stories/Simple.js' import Simple from '../stories/Simple.js'
import CellRenderers from '../stories/CellRenderers.js' import CellRenderers from '../stories/CellRenderers.js'
import DefaultSorting from '../stories/DefaultSorting.js' import DefaultSorting from '../stories/DefaultSorting.js'
import CustomSorting from '../stories/CustomSorting.js'
import CustomWidths from '../stories/CustomWidths.js' import CustomWidths from '../stories/CustomWidths.js'
import CustomComponentProps from '../stories/CustomComponentProps.js' import CustomComponentProps from '../stories/CustomComponentProps.js'
import ServerSide from '../stories/ServerSide.js' import ServerSide from '../stories/ServerSide.js'
@@ -28,6 +29,7 @@ import Filtering from '../stories/Filtering.js'
import ControlledTable from '../stories/ControlledTable.js' import ControlledTable from '../stories/ControlledTable.js'
import PivotingOptions from '../stories/PivotingOptions.js' import PivotingOptions from '../stories/PivotingOptions.js'
import EditableTable from '../stories/EditableTable.js' import EditableTable from '../stories/EditableTable.js'
import SubRows from '../stories/SubRows.js'
// //
configure(() => { configure(() => {
storiesOf('1. Docs') storiesOf('1. Docs')
@@ -46,6 +48,7 @@ configure(() => {
.add('Simple Table', Simple) .add('Simple Table', Simple)
.add('Cell Renderers & Custom Components', CellRenderers) .add('Cell Renderers & Custom Components', CellRenderers)
.add('Default Sorting', DefaultSorting) .add('Default Sorting', DefaultSorting)
.add('Custom Sorting', CustomSorting)
.add('Custom Column Widths', CustomWidths) .add('Custom Column Widths', CustomWidths)
.add('Custom Component Props', CustomComponentProps) .add('Custom Component Props', CustomComponentProps)
.add('Server-side Data', ServerSide) .add('Server-side Data', ServerSide)
@@ -61,4 +64,5 @@ configure(() => {
.add('Custom Filtering', Filtering) .add('Custom Filtering', Filtering)
.add('Controlled Component', ControlledTable) .add('Controlled Component', ControlledTable)
.add('Editable table', EditableTable) .add('Editable table', EditableTable)
// .add('Sub Rows', SubRows)
}, module) }, module)
+40 -7
View File
@@ -1,11 +1,44 @@
## 6.0.0 ## 6.0.0
* Pivot Columns can now be sorted and filtered individually. ##### New Features
* More control over Pivot Column rendering. - New Renderers:
* Prevent transitions while column resizing for a smoother resize effect. - `Aggregated` - Custom renderer for aggregated cells
* Disable text selection while resizing columns. - `Pivot` - Custom renderer for Pivoted Cells (utilizes `Expander` and `PivotValue`)
- `PivotValue` - Custom renderer for Pivot cell values (deprecates the undocumented `pivotRender` option)
- `Expander` - Custom renderer for Pivot cell Expander
- Added custom sorting methods per table via `defaultSortMethod` and per column via `column.sortMethod`
- Pivot columns are now visibly separate and sorted/filtered independently.
- Added `column.resizable` to override global table `resizable` option for specific columns.
- Added `column.sortable` to override global table `sortable` option for specific columns.
- Added `column.filterable` to override global table `filterable` option for specific columns.
- Added `defaultExpanded` table option.
- All callbacks can now be utilized without needing to hoist and manage the piece of state they export. That is what their prop counterparts are for, so now the corresponding prop is used instead of the callback to detect a "fully controlled" state.
- Prevent transitions while column resizing for a smoother resize effect.
- Disable text selection while resizing columns.
##### Breaking API Changes ##### Breaking API Changes
* Removed `pivotRender` column option. You can now control how the value is displayed by overriding the `PivotValueComponent`. - New Renderers:
* Changed how special `expander: true` column renders pivot columns. - `Cell` - deprecates and replaces `render`
See [Pivoting Options Story](https://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Pivoting%20Options&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel) for a reference on how to customize pivot column rendering. - `Header` - deprecates and replaces `header`
- `Footer` - deprecates and replaces `footer`
- `Filter`- deprecates and replaces `filterRender`
- Callbacks now provide the destination state as the primary parameter(s). This makes hoisting and controlling the state in redux or component state much easier. eg.
- `onSorting` no longer requires you to build your own toggle logic
- `onResize` no longer requires you to build your own resize logic
- Renamed `onChange` callback -> `onFetchData` which will always fire when a new data model needs to be fetched (or if not using `manual`, when new data is materialized internally).
- Renamed `filtering` -> `filtered`
- Renamed `sorting` -> `sorted`
- Renamed `expandedRows` -> `expanded`
- Renamed `resizing` -> `resized`
- Renamed `defaultResizing` -> `defaultResized`
- Renamed `defaultFiltering` -> `defaultFiltered`
- Renamed `defaultSorting` -> `defaultSorted`
- Renamed `onSortingChange` -> `onSortedChange`
- Renamed `onFilteringChange` -> `onFilteredChange`
- Renamed `onResize` -> `onResizedChange`
- Renamed `onExpandRow` -> `onExpandedChange`
- Renamed `showFilters` -> `filterable`
- Renamed `hideFilter` -> `filterable` (Column option. Note the true/false value is now flipped.)
- `cellInfo.row` and `rowInfo.row` now reference the materialize data for the table. To reference the original row, use `cellInfo.original` and `rowInfo.original`
- Removed `pivotRender` column option. You can now control how the value is displayed by overriding the `PivotValueComponent` or the individual column's `PivotValue` renderer. See [Pivoting Options Story](https://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Pivoting%20Options&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel) for a reference on how to customize pivot column rendering.
+216 -93
View File
@@ -28,8 +28,14 @@
<img alt="" src="https://img.shields.io/badge/%24-Donate-brightgreen.svg" /> <img alt="" src="https://img.shields.io/badge/%24-Donate-brightgreen.svg" />
</a> </a>
## Features ## Versions
This document refers to version 6.x.x of react-table.
Previous versions:
[5.x.x Readme](https://github.com/tannerlinsley/react-table/blob/ad7d31cd3978eb45da7c6194dbab93c1e9a8594d/README.md)
## Features
- Lightweight at 7kb (and just 2kb more for styles) - Lightweight at 7kb (and just 2kb more for styles)
- Fully customizable JSX templating - Fully customizable JSX templating
- Supports both Client-side & Server-side pagination and multi-sorting - Supports both Client-side & Server-side pagination and multi-sorting
@@ -115,18 +121,18 @@ render() {
}] }]
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
accessor: 'name' // String-based value accessors! accessor: 'name' // String-based value accessors!
}, { }, {
header: 'Age', Header: 'Age',
accessor: 'age', accessor: 'age',
render: props => <span className='number'>{props.value}</span> // Custom cell components! Cell: props => <span className='number'>{props.value}</span> // Custom cell components!
}, { }, {
id: 'friendName', // Required because our accessor is not a string id: 'friendName', // Required because our accessor is not a string
header: 'Friend Name', Header: 'Friend Name',
accessor: d => d.friend.name // Custom value accessors! accessor: d => d.friend.name // Custom value accessors!
}, { }, {
header: props => <span>Friend Age</span>, // Custom header components! Header: props => <span>Friend Age</span>, // Custom header components!
accessor: 'friend.age' accessor: 'friend.age'
}] }]
@@ -157,43 +163,66 @@ These are all of the available props (and their default values) for the main `<R
collapseOnPageChange: true, collapseOnPageChange: true,
collapseOnDataChange: true, collapseOnDataChange: true,
freezeWhenExpanded: false, freezeWhenExpanded: false,
defaultSorting: [], sortable: true,
showFilters: false, resizable: true,
defaultFiltering: [], filterable: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
defaultExpanded: {},
defaultFilterMethod: (filter, row, column) => { defaultFilterMethod: (filter, row, column) => {
const id = filter.pivotId || filter.id const id = filter.pivotId || filter.id
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
}, },
resizable: true, defaultSortMethod: (a, b) => {
defaultResizing: [], // force null and undefined to the bottom
a = (a === null || a === undefined) ? -Infinity : a
b = (b === null || b === undefined) ? -Infinity : b
// force any string values to lowercase
a = a === 'string' ? a.toLowerCase() : a
b = b === 'string' ? b.toLowerCase() : b
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1
}
if (a < b) {
return -1
}
// returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker
return 0
},
// Controlled State Overrides (see Fully Controlled Component section) // Controlled State Overrides (see Fully Controlled Component section)
page: undefined, page: undefined,
pageSize: undefined, pageSize: undefined,
sorting: undefined, sorted: [],
filtered: [],
resized: [],
expanded: {},
// Controlled State Callbacks // Controlled State Callbacks
onExpandSubComponent: undefined,
onPageChange: undefined, onPageChange: undefined,
onPageSizeChange: undefined, onPageSizeChange: undefined,
onSortingChange: undefined, onSortedChange: undefined,
onFilteringChange: undefined, onFilteredChange: undefined,
onResize: undefined, onResizedChange: undefined,
onExpandedChange: undefined,
// Pivoting // Pivoting
pivotBy: undefined, pivotBy: undefined,
// Key Constants
pivotValKey: '_pivotVal', pivotValKey: '_pivotVal',
pivotIDKey: '_pivotID', pivotIDKey: '_pivotID',
subRowsKey: '_subRows', subRowsKey: '_subRows',
aggregatedKey: '_aggregated',
nestingLevelKey: '_nestingLevel',
originalKey: '_original',
indexKey: '_index',
groupedByPivotKey: '_groupedByPivot',
// Pivoting State Overrides (see Fully Controlled Component section) // Server-side callbacks
expandedRows: {}, onFetchData: () => null,
// Pivoting State Callbacks
onExpandRow: undefined,
// General Callbacks
onChange: () => null,
// Classes // Classes
className: '', className: '',
@@ -226,50 +255,47 @@ These are all of the available props (and their default values) for the main `<R
// Global Column Defaults // Global Column Defaults
column: { column: {
sortable: true, // Renderers
Cell: undefined,
Header: undefined,
Footer: undefined,
Aggregated: undefined,
Pivot: undefined,
PivotValue: undefined,
Expander: undefined,
Filter: undefined,
// Standard options
sortable: undefined, // use table default
resizable: undefined, // use table default
filterable: undefined, // use table default
show: true, show: true,
minWidth: 100, minWidth: 100,
// Cells only // Cells only
render: undefined,
className: '', className: '',
style: {}, style: {},
getProps: () => ({}), getProps: () => ({}),
// Headers only // Headers only
header: undefined,
headerClassName: '', headerClassName: '',
headerStyle: {}, headerStyle: {},
getHeaderProps: () => ({}) getHeaderProps: () => ({})
// Footers only // Footers only
footer: undefined,
footerClassName: '', footerClassName: '',
footerStyle: {}, footerStyle: {},
getFooterProps: () => ({}), getFooterProps: () => ({}),
filterMethod: undefined, filterMethod: undefined,
hideFilter: false, sortMethod: undefined
filterRender: ({filter, onFilterChange}) => (
<input type='text'
style={{
width: '100%'
}}
value={filter ? filter.value : ''}
onChange={(event) => onFilterChange(event.target.value)}
/>
)
}, },
// Global Expander Column Defaults // Global Expander Column Defaults
expanderDefaults: { expanderDefaults: {
sortable: false, sortable: false,
width: 35, resizable: false,
hideFilter: true filterable: false,
// render: will be overriden in methods.js to display ExpanderComponent width: 35
}, },
// Global Pivot Column Defaults // Global Pivot Column Defaults
pivotDefaults: { pivotDefaults: {},
filterRender: undefined
// render: will be overriden in methods.js to display ExpanderComponent and PivotValueComponent
},
// Text // Text
previousText: 'Previous', previousText: 'Previous',
@@ -309,37 +335,49 @@ Or just define them as props
```javascript ```javascript
[{ [{
// Renderers - For more information, see "Renderers" section below
Cell: JSX | String | Function // Used to render a standard cell, defaults to the accessed value
Header: JSX | String | Function // Used to render the header of a column or column group
Footer: JSX | String | Function // Used to render the footer of a column
Filter: JSX | cellInfo => ( // Used to render the filter UI of a filter-enabled column
<select onChange={event => onFiltersChange(event.target.value)} value={filter ? filter.value : ''}></select>
// The value passed to onFiltersChange will be the value passed to filter.value of the filterMethod
)
Aggregated: JSX | String | Function // Used to render aggregated cells. Defaults to a comma separated list of values.
Pivot: JSX | String | Function | cellInfo => ( // Used to render a pivoted cell
<span>
<Expander/><PivotValue /> // By default, will utilize the the PivotValue and Expander components at run time
</span>
),
PivotValue: JSX | String | Function // Used to render the value inside of a Pivot cell
Expander: JSX | String | Function // Used to render the expander in both Pivot and Expander cells
// General // General
accessor: 'propertyName', // or Accessor eg. (row) => row.propertyName (see "Accessors" section for more details) accessor: 'propertyName', // or Accessor eg. (row) => row.propertyName (see "Accessors" section for more details)
id: 'myProperty', // Conditional - A unique ID is required if the accessor is not a string or if you would like to override the column name used in server-side calls id: 'myProperty', // Conditional - A unique ID is required if the accessor is not a string or if you would like to override the column name used in server-side calls
sortable: true, sortable: boolean, // Overrides the table option
resizable: boolean, // Overrides the table option
filterable: boolean, // Overrides the table option
show: true, // can be used to hide a column show: true, // can be used to hide a column
width: undefined, // A hardcoded width for the column. This overrides both min and max width options width: undefined, // A hardcoded width for the column. This overrides both min and max width options
minWidth: 100, // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set) minWidth: 100, // A minimum width for this column. If there is extra room, column will flex to fill available space (up to the max-width, if set)
maxWidth: undefined, // A maximum width for this column. maxWidth: undefined, // A maximum width for this column.
// Special // Special
// Turns this column into a special column for specifying expander and pivot column options. pivot: false,
// If this option is true and there is NOT a pivot column, the `expanderDefaults` options will be applied on top of the column options. // Turns this column into a special column for specifying pivot position in your column definitions.
// If this option is true and there IS a pivot column, the `pivotDefaults` options will be applied on top of the column options. // The `pivotDefaults` options will be applied on top of this column's options.
// Adding a column with the `expander` option set will allow you to rearrange expander and pivot column orderings in the table. // It will also let you specify rendering of the header (and header group if this special column is placed in the `columns` option of another column)
expander: false,
// Turns this column into a special column for specifying expander position and options in your column definitions.
// The `expanderDefaults` options will be applied on top of this column's options.
// It will also let you specify rendering of the header (and header group if this special column is placed in the `columns` option of another column) and // It will also let you specify rendering of the header (and header group if this special column is placed in the `columns` option of another column) and
// the rendering of the expander itself. // the rendering of the expander itself via the `Expander` property
expander: false,
// Cell Options // Cell Options
className: '', // Set the classname of the `td` element of the column className: '', // Set the classname of the `td` element of the column
style: {}, // Set the style of the `td` element of the column style: {}, // Set the style of the `td` element of the column
render: JSX eg. (cellInfo: {value, rowValues, row, column, index, viewIndex}) => <span>{value}</span>, // Provide a JSX element or stateless function to render whatever you want as the column's cell with access to the entire row
// value == the accessed value of the column
// rowValues == an object of all of the accessed values for the row
// row == the original row of data supplied to the table
// column == the column properties (id, header, sortable, ...)
// index == the original index of the data supplied to the table
// viewIndex == the index of the row in the current page
// Header & HeaderGroup Options // Header & HeaderGroup Options
header: 'Header Name', a function that returns a primitive, or JSX / React Component eg. ({data, column}) => <div>Header Name</div>,
headerClassName: '', // Set the classname of the `th` element of the column headerClassName: '', // Set the classname of the `th` element of the column
headerStyle: {}, // Set the style of the `th` element of the column headerStyle: {}, // Set the style of the `th` element of the column
getHeaderProps: (state, rowInfo, column, instance) => ({}), // a function that returns props to decorate the `th` element of the column getHeaderProps: (state, rowInfo, column, instance) => ({}), // a function that returns props to decorate the `th` element of the column
@@ -348,7 +386,6 @@ Or just define them as props
columns: [...], // See Header Groups section below columns: [...], // See Header Groups section below
// Footer // Footer
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 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 footerStyle: {}, // Set the style of the `td` element of the column's footer
getFooterProps: (state, rowInfo, column, instance) => ({}), // A function that returns props to decorate the `td` element of the column's footer getFooterProps: (state, rowInfo, column, instance) => ({}), // A function that returns props to decorate the `td` element of the column's footer
@@ -358,11 +395,54 @@ 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]} // 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 // row == the row of data supplied to the table
// column == the column that the filter is on // column == the column that the filter is on
hideFilter: false, // If `showFilters` is set on the table, this option will let you selectively hide the filter on a particular row
filterRender: JSX // eg. ({filter, onFilterChange}) => <select onChange={event => onFilterChange(event.target.value)} value={filter ? filter.value : ''}></select> // The value passed to onFilterChange will be the value passed to filter.value of the filterMethod
}] }]
``` ```
## Renderers
React Table supports very flexible renderers for just about everything:
- `Cell` - Renders a standard cell
- `Header` - Renders a column header or column group header
- `Footer` - Renders a column footer
- `Filter` - Renders a column's filter UI
- `Aggregated` - Renders an aggregated cell
- `Pivot` - Renders a pivoted cell (by default, will utilize `Expander` and `PivotValue` renderers)
- `PivotValue` - Renders the value inside a `Pivot` renderer
- `Expander` - Renders the Expander used in both the default `Pivot` renderer and any expander-designated column
Any of these renderers can be one of the following:
- A React Class
- JSX or any rendered react component
- Stateless functional component
- Function that returns any primitive
All of these formats receive the following props:
```javascript
{
// Row-level props
row: Object, // the materialized row of data
original: , // the original row of data
index: '', // the index of the row in the original arra
viewIndex: '', // the index of the row relative to the current view
level: '', // the nesting level of this row
nestingPath: '', // the nesting path of this row
aggregated: '', // true if this row's values were aggregated
groupedByPivot: '', // true if this row was produced by a pivot
subRows: '', // any sub rows defined by the `subRowKey` prop
// Cells-level props
isExpanded: '', // true if this row is expanded
value: '', // the materialized value of this cell
resized: '', // the resize information for this cell's column
show: '', // true if the column is visible
width: '', // the resolved width of this cell
maxWidth: '', // the resolved maxWidth of this cell
tdProps: '', // the resolved tdProps from `getTdProps` for this cell
columnProps: '', // the resolved column props from 'getProps' for this cell's column
classes: '', // the resolved array of classes for this cell
styles: '' // the resolved styles for this cell
}
```
## Accessors ## Accessors
Accessors are functions that return the value to populate the row's value for the column. Accessors are functions that return the value to populate the row's value for the column.
This lets the render function not have to worry about accessing the correct data, the value is automatically populated in it's props. This lets the render function not have to worry about accessing the correct data, the value is automatically populated in it's props.
@@ -390,16 +470,16 @@ If your data has a field/key with a dot (`.`) you will need to supply a custom a
To group columns with another header column, just nest your columns in a header column. Header columns utilize the same header properties as regular columns. To group columns with another header column, just nest your columns in a header column. Header columns utilize the same header properties as regular columns.
```javascript ```javascript
const columns = [{ const columns = [{
header: 'Favorites', Header: 'Favorites',
headerClassName: 'my-favorites-column-header-group' headerClassName: 'my-favorites-column-header-group'
columns: [{ columns: [{
header: 'Color', Header: 'Color',
accessor: 'favorites.color' accessor: 'favorites.color'
}, { }, {
header: 'Food', Header: 'Food',
accessor: 'favorites.food' accessor: 'favorites.food'
} { } {
header: 'Actor', Header: 'Actor',
accessor: 'favorites.actor' accessor: 'favorites.actor'
}] }]
}] }]
@@ -408,7 +488,7 @@ const columns = [{
## Custom Cell, Header and Footer Rendering ## Custom Cell, Header and Footer Rendering
You can use any react component or JSX to display content in column headers, cells and footers. Any component you use will be passed the following props (if available): You can use any react component or JSX to display content in column headers, cells and footers. Any component you use will be passed the following props (if available):
- `row` - Original row from your data - `row` - Original row from your data
- `rowValues` - The post-accessed values from the original row - `row` - The post-accessed values from the original row
- `index` - The index of the row - `index` - The index of the row
- `viewIndex` - the index of the row relative to the current page - `viewIndex` - the index of the row relative to the current page
- `level` - The nesting depth (zero-indexed) - `level` - The nesting depth (zero-indexed)
@@ -420,9 +500,9 @@ You can use any react component or JSX to display content in column headers, cel
// This column uses a stateless component to produce a different colored bar depending on the value // This column uses a stateless component to produce a different colored bar depending on the value
// You can also use stateful components or any other function that returns JSX // You can also use stateful components or any other function that returns JSX
const columns = [{ const columns = [{
header: () => <span><i className='fa-tasks' /> Progress</span>, Header: () => <span><i className='fa-tasks' /> Progress</span>,
accessor: 'progress', accessor: 'progress',
render: row => ( Cell: row => (
<div <div
style={{ style={{
width: '100%', width: '100%',
@@ -565,15 +645,15 @@ Naturally when grouping rows together, you may want to aggregate the rows inside
```javascript ```javascript
// In this example, we use lodash to sum and average the values, but you can use whatever you want to aggregate. // In this example, we use lodash to sum and average the values, but you can use whatever you want to aggregate.
const columns = [{ const columns = [{
header: 'Age', Header: 'Age',
accessor: 'age', accessor: 'age',
aggregate: (values, rows) => _.round(_.mean(values)), aggregate: (values, rows) => _.round(_.mean(values)),
render: row => { Aggregated: row => {
// You can even render the cell differently if it's an aggregated cell // You can even render the cell differently if it's an aggregated cell
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span> return <span>row.value (avg)</span>
} }
}, { }, {
header: 'Visits', Header: 'Visits',
accessor: 'visits', accessor: 'visits',
aggregate: (values, rows) => _.sum(values) aggregate: (values, rows) => _.sum(values)
}] }]
@@ -604,8 +684,8 @@ If you want to handle pagination, sorting, and filtering on the server, `react-t
1. Feed React Table `data` from somewhere dynamic. eg. `state`, a redux store, etc... 1. Feed React Table `data` from somewhere dynamic. eg. `state`, a redux store, etc...
1. Add `manual` as a prop. This informs React Table that you'll be handling sorting and pagination server-side 1. Add `manual` as a prop. This informs React Table that you'll be handling sorting and pagination server-side
1. Subscribe to the `onChange` prop. This function is called at `compomentDidMount` and any time sorting or pagination is changed by the user 1. Subscribe to the `onFetchData` prop. This function is called at `compomentDidMount` and any time sorting, pagination or filterting is changed in the table
1. In the `onChange` callback, request your data using the provided information in the params of the function (state and instance) 1. In the `onFetchData` callback, request your data using the provided information in the params of the function (current state and instance)
1. Update your data with the rows to be displayed 1. Update your data with the rows to be displayed
1. Optionally set how many pages there are total 1. Optionally set how many pages there are total
@@ -616,15 +696,15 @@ If you want to handle pagination, sorting, and filtering on the server, `react-t
pages={this.state.pages} // should default to -1 (which means we don't know how many pages we have) pages={this.state.pages} // should default to -1 (which means we don't know how many pages we have)
loading={this.state.loading} loading={this.state.loading}
manual // informs React Table that you'll be handling sorting and pagination server-side manual // informs React Table that you'll be handling sorting and pagination server-side
onChange={(state, instance) => { onFetchData={(state, instance) => {
// show the loading overlay // show the loading overlay
this.setState({loading: true}) this.setState({loading: true})
// fetch your data // fetch your data
Axios.post('mysite.com/data', { Axios.post('mysite.com/data', {
page: state.page, page: state.page,
pageSize: state.pageSize, pageSize: state.pageSize,
sorting: state.sorting, sorted: state.sorted,
filtering: state.filtering filtered: state.filtered
}) })
.then((res) => { .then((res) => {
// Update react-table // Update react-table
@@ -649,29 +729,37 @@ Here are the props and their corresponding callbacks that control the state of t
// Props // Props
page={0} // the index of the page you wish to display page={0} // the index of the page you wish to display
pageSize={20} // the number of rows per page to be displayed pageSize={20} // the number of rows per page to be displayed
sorting={[{ sorting={[{ // the sorting model for the table
id: 'lastName', id: 'lastName',
desc: true desc: true
}, { }, {
id: 'firstName', id: 'firstName',
desc: true desc: true
}]} // the sorting model for the table }]}
expandedRows={{ expandedRows={{ // The nested row indexes on the current page that should appear expanded
1: true, 1: true,
4: true, 4: true,
5: { 5: {
2: true, 2: true,
3: true 3: true
} }
}} // The nested row indexes on the current page that should appear expanded }}
filters={[{ // the current filters model
id: 'lastName',
value: 'linsley'
}]}
resizing={[{ // the current resized column model
"id": "lastName",
"value": 446.25
}]}
// Callbacks // Callbacks
onPageChange={(pageIndex) => {...}} // Called when the page index is changed by the user onPageChange={(pageIndex) => {...}} // Called when the page index is changed by the user
onPageSizeChange={(pageSize, pageIndex) => {...}} // Called when the pageSize is changed by the user. The resolve page is also sent to maintain approximate position in the data 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 onSortedChange={(newSorted, column, shiftKey) => {...}} // Called when a sortable column header is clicked with the column itself and if the shiftkey was held. If the column is a pivoted column, `column` will be an array of columns
onExpandRow={(index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows` onExpandedChange={(newExpanded, index, event) => {...}} // Called when an expander is clicked. Use this to manage `expandedRows`
onFilteringChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFilterChange handler by the filterRender option. onFilteredChange={(column, value) => {...}} // Called when a user enters a value into a filter input field or the value passed to the onFiltersChange handler by the filterRender option.
onResize={(column, event, isTouch) => {...}} // Called when a user clicks on a resizing component (the right edge of a column header) onResizedChange={(newResized, event) => {...}} // Called when a user clicks on a resizing component (the right edge of a column header)
/> />
``` ```
@@ -712,19 +800,51 @@ Accessing internal state and wrapping with more UI:
The possibilities are endless! The possibilities are endless!
## Sorting
Sorting comes built in with React-Table. Click column header to sort by its column. Click it again to reverse the sort.
## Multi-Sort ## Multi-Sort
When clicking on a column header, hold shift to multi-sort! You can toggle `ascending` `descending` and `none` for multi-sort columns. Clicking on a header without holding shift will clear the multi-sort and replace it with the single sort of that column. It's quite handy! When clicking on a column header, hold shift to multi-sort! You can toggle `ascending` `descending` and `none` for multi-sort columns. Clicking on a header without holding shift will clear the multi-sort and replace it with the single sort of that column. It's quite handy!
## Filtering ## Custom Sorting Algorithm
Filtering can be enabled by setting the `showFilters` option on the table. To override the default sorting algorithm for the whole table use the `defaultSortMethod` prop.
If you don't want particular column to be filtered you can set the `hideFilter` option on the column. To override the sorting algorithm for a single column, use the `sortMethod` column property.
Supply a function that implements the native javascript [`Array.sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) interface. This is React Table's default sorting algorithm:
- `a` the first value to compare
- `b` the second value to compare
- `dir` the
```javascript
defaultSortMethod = (a, b) => {
// force null and undefined to the bottom
a = (a === null || a === undefined) ? -Infinity : a
b = (b === null || b === undefined) ? -Infinity : b
// force any string values to lowercase
a = a === 'string' ? a.toLowerCase() : a
b = b === 'string' ? b.toLowerCase() : b
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1
}
if (a < b) {
return -1
}
// returning 0 or undefined will use any subsequent column sorting methods or the row index as a tiebreaker
return 0
}
```
## Filtering
Filtering can be enabled by setting the `filterable` option on the table.
If you don't want particular column to be filtered you can set the `filterable={false}` option on the column.
By default the table tries to filter by checking if the row's value starts with the filter text. The default method for filtering the table can be set with the table's `defaultFilterMethod` option. By default the table tries to filter by checking if the row's value starts with the filter text. The default method for filtering the table can be set with the table's `defaultFilterMethod` option.
If you want to override a particular column's filtering method, you can set the `filterMethod` option on a column. 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. To completely override the filter that is shown, you can set the `Filter` column option. Using this option you can specify the JSX that is shown. The option is passed an `onChange` method which must be called with the the value that you wan't to pass to the `filterMethod` option whenever the filter has changed.
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. 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.
@@ -743,7 +863,10 @@ Object.assign(ReactTableDefaults, {
TdComponent: component, TdComponent: component,
TfootComponent: component, TfootComponent: component,
ExpanderComponent: component, ExpanderComponent: component,
AggregatedComponent: component,
PivotValueComponent: component, PivotValueComponent: component,
PivotComponent: component,
FilterComponent: component,
PaginationComponent: component, PaginationComponent: component,
PreviousComponent: undefined, PreviousComponent: undefined,
NextComponent: undefined, NextComponent: undefined,
+1 -1
View File
@@ -16,7 +16,7 @@
<body> <body>
<div id="root"></div> <div id="root"></div>
<div id="error-display"></div> <div id="error-display"></div>
<script src="static/preview.5f0262046fdd8adfb130.bundle.js"></script> <script src="static/preview.b5270b38a18bc77dc351.bundle.js"></script>
</body> </body>
</html> </html>
+1 -1
View File
@@ -38,7 +38,7 @@
</head> </head>
<body style="margin: 0;"> <body style="margin: 0;">
<div id="root"></div> <div id="root"></div>
<script src="static/manager.2e7b063c56eb89efa1fe.bundle.js"></script> <script src="static/manager.9a120eb2943ac2bf0331.bundle.js"></script>
</body> </body>
</html> </html>
@@ -1 +0,0 @@
{"version":3,"file":"static/manager.2e7b063c56eb89efa1fe.bundle.js","sources":["webpack:///static/manager.2e7b063c56eb89efa1fe.bundle.js"],"mappings":"AAAA;AAkuDA;AA84DA;AA28DA;AA00DA;AAsvEA;AAuhDA;AAsrDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAoxDA;AAsrDA;AA+yDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"version":3,"file":"static/manager.9a120eb2943ac2bf0331.bundle.js","sources":["webpack:///static/manager.9a120eb2943ac2bf0331.bundle.js"],"mappings":"AAAA;AAmuDA;AA64DA;AA28DA;AA00DA;AAsvEA;AAuhDA;AAsrDA;AAsiDA;AAg6DA;AA2nDA;AA++CA;AAkvDA;AAsnEA;AA2oDA;AAivCA;AA+nDA;AAkpDA;AA6lEA;AAs4DA;AAquDA;AA+pDA;AAoxDA;AAsrDA;AAizDA;AA88GA;AAj6CA;AAopGA;AAsuFA;AA+zEA;AAtMA;AAizEA","sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"version":3,"file":"static/preview.5f0262046fdd8adfb130.bundle.js","sources":["webpack:///static/preview.5f0262046fdd8adfb130.bundle.js"],"mappings":"AAAA;AAkuDA;AAmgEA;AA2jFA;AAinFA;AAgsPA;AA+6EA;AAytDA;AA+jEA;AAixDA;AAuzDA;AAk1DA;AA6pDA;AA2+CA;AA+4DA;AAqpDA;AA89CA;AA0nDA;AA2jEA;AA03DA;AA6gCA;AA80DA;AAooDA;AA2nEA;AAw1DA;AA64DA;AAixCA;AAyrFA;AAmjGA;AA4lDA;AA+zCA;AA8vCA;AAshCA;AAwpDA;AA+rCA;AAsCA;AA+jFA","sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"version":3,"file":"static/preview.b5270b38a18bc77dc351.bundle.js","sources":["webpack:///static/preview.b5270b38a18bc77dc351.bundle.js"],"mappings":"AAAA;AAmrDA;AA8uCA;AAqoIA;AA2wGA;AA0pPA;AA65CA;AAk2DA;AA88DA;AAg0DA;AAsgEA;AAmlDA;AAgjDA;AA2hDA;AA6+DA;AAslDA;AA4+CA;AAimDA;AA09DA;AAy4DA;AAwxCA;AAknDA;AA+qDA;AA+nEA;AA4yDA;AAwwCA;AA8tDA;AAuqGA;AA65FA;AAg3CA;AA+1CA;AAkqCA;AAqlCA;AAkgDA;AAo2CA;AAsCA;AA+jFA","sourceRoot":""}
+3 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "react-table", "name": "react-table",
"version": "5.6.0", "version": "6.0.0",
"description": "A fast, lightweight, opinionated table and datagrid built on React", "description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT", "license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme", "homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -38,7 +38,8 @@
"docs": "build-storybook -o docs && cp .storybook/CNAME docs/CNAME" "docs": "build-storybook -o docs && cp .storybook/CNAME docs/CNAME"
}, },
"dependencies": { "dependencies": {
"classnames": "^2.2.5" "classnames": "^2.2.5",
"raw-loader": "^0.5.1"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^15.x.x" "react": "^15.x.x"
+83 -39
View File
@@ -19,43 +19,66 @@ export default {
collapseOnPageChange: true, collapseOnPageChange: true,
collapseOnDataChange: true, collapseOnDataChange: true,
freezeWhenExpanded: false, freezeWhenExpanded: false,
defaultSorting: [], sortable: true,
showFilters: false, resizable: true,
defaultFiltering: [], filterable: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
defaultExpanded: {},
defaultFilterMethod: (filter, row, column) => { defaultFilterMethod: (filter, row, column) => {
const id = filter.pivotId || filter.id const id = filter.pivotId || filter.id
return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true return row[id] !== undefined ? String(row[id]).startsWith(filter.value) : true
}, },
resizable: true, defaultSortMethod: (a, b) => {
defaultResizing: [], // force null and undefined to the bottom
a = (a === null || a === undefined) ? -Infinity : a
b = (b === null || b === undefined) ? -Infinity : b
// force any string values to lowercase
a = a === 'string' ? a.toLowerCase() : a
b = b === 'string' ? b.toLowerCase() : b
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1
}
if (a < b) {
return -1
}
// returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker
return 0
},
// Controlled State Overrides // Controlled State Props
// page: undefined, // page: undefined,
// pageSize: undefined, // pageSize: undefined,
// sorting: undefined, // sorted: [],
// filtered: [],
// resized: [],
// expanded: {},
// Controlled State Callbacks // Controlled State Callbacks
onExpandSubComponent: undefined,
onPageChange: undefined, onPageChange: undefined,
onPageSizeChange: undefined, onPageSizeChange: undefined,
onSortingChange: undefined, onSortedChange: undefined,
onFilteringChange: undefined, onFilteredChange: undefined,
onResize: undefined, onResizedChange: undefined,
onExpandedChange: undefined,
// Pivoting // Pivoting
pivotBy: undefined, pivotBy: undefined,
// Key Constants
pivotValKey: '_pivotVal', pivotValKey: '_pivotVal',
pivotIDKey: '_pivotID', pivotIDKey: '_pivotID',
subRowsKey: '_subRows', subRowsKey: '_subRows',
aggregatedKey: '_aggregated',
nestingLevelKey: '_nestingLevel',
originalKey: '_original',
indexKey: '_index',
groupedByPivotKey: '_groupedByPivot',
// Pivoting State Overrides // Server-side Callbacks
// expandedRows: {}, onFetchData: () => null,
// Pivoting State Callbacks
onExpandRow: undefined,
// General Callbacks
onChange: () => null,
// Classes // Classes
className: '', className: '',
@@ -87,49 +110,49 @@ export default {
// Global Column Defaults // Global Column Defaults
column: { column: {
sortable: true, // Renderers
Cell: undefined,
Header: undefined,
Footer: undefined,
Aggregated: undefined,
Pivot: undefined,
PivotValue: undefined,
Expander: undefined,
Filter: undefined,
// All Columns
sortable: undefined, // use table default
resizable: undefined, // use table default
filterable: undefined, // use table default
show: true, show: true,
minWidth: 100, minWidth: 100,
// Cells only // Cells only
render: undefined,
className: '', className: '',
style: {}, style: {},
getProps: emptyObj, getProps: emptyObj,
// Pivot only
aggregate: undefined,
// Headers only // Headers only
header: undefined,
headerClassName: '', headerClassName: '',
headerStyle: {}, headerStyle: {},
getHeaderProps: emptyObj, getHeaderProps: emptyObj,
// Footers only // Footers only
footer: undefined,
footerClassName: '', footerClassName: '',
footerStyle: {}, footerStyle: {},
getFooterProps: emptyObj, getFooterProps: emptyObj,
filterMethod: undefined, filterMethod: undefined,
hideFilter: false, sortMethod: undefined
filterRender: ({filter, onFilterChange}) => (
<input type='text'
style={{
width: '100%'
}}
value={filter ? filter.value : ''}
onChange={(event) => onFilterChange(event.target.value)}
/>
)
}, },
// Global Expander Column Defaults // Global Expander Column Defaults
expanderDefaults: { expanderDefaults: {
sortable: false, sortable: false,
width: 35, resizable: false,
hideFilter: true filterable: false,
// render: will be overriden in methods.js to display ExpanderComponent width: 35
}, },
// Global Pivot Column Defaults
pivotDefaults: { pivotDefaults: {
filterRender: undefined // extend the defaults for pivoted columns here
// render: will be overriden in methods.js to display ExpanderComponent and PivotValueComponent
}, },
// Text // Text
@@ -162,6 +185,15 @@ export default {
}, },
TdComponent: _.makeTemplateComponent('rt-td'), TdComponent: _.makeTemplateComponent('rt-td'),
TfootComponent: _.makeTemplateComponent('rt-tfoot'), TfootComponent: _.makeTemplateComponent('rt-tfoot'),
FilterComponent: ({filter, onChange}) => (
<input type='text'
style={{
width: '100%'
}}
value={filter ? filter.value : ''}
onChange={(event) => onChange(event.target.value)}
/>
),
ExpanderComponent: ({isExpanded}) => ( ExpanderComponent: ({isExpanded}) => (
<div className={classnames('rt-expander', isExpanded && '-open')}> <div className={classnames('rt-expander', isExpanded && '-open')}>
&bull; &bull;
@@ -170,6 +202,18 @@ export default {
PivotValueComponent: ({subRows, value}) => ( PivotValueComponent: ({subRows, value}) => (
<span>{value} {subRows && `(${subRows.length})`}</span> <span>{value} {subRows && `(${subRows.length})`}</span>
), ),
AggregatedComponent: ({subRows, column}) => {
const previewValues = subRows
.filter(d => typeof d[column.id] !== 'undefined')
.map((row, i) => (
<span key={i}>{row[column.id]}{i < subRows.length - 1 ? ', ' : ''}</span>
))
return (
<span>{previewValues}</span>
)
},
PivotComponent: undefined, // this is a computed default generated using
// the ExpanderComponent and PivotValueComponent at run-time in methods.js
PaginationComponent: Pagination, PaginationComponent: Pagination,
PreviousComponent: undefined, PreviousComponent: undefined,
NextComponent: undefined, NextComponent: undefined,
+186 -165
View File
@@ -17,7 +17,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
this.getResolvedState = this.getResolvedState.bind(this) this.getResolvedState = this.getResolvedState.bind(this)
this.getDataModel = this.getDataModel.bind(this) this.getDataModel = this.getDataModel.bind(this)
this.getSortedData = this.getSortedData.bind(this) this.getSortedData = this.getSortedData.bind(this)
this.fireOnChange = this.fireOnChange.bind(this) this.fireFetchData = this.fireFetchData.bind(this)
this.getPropOrState = this.getPropOrState.bind(this) this.getPropOrState = this.getPropOrState.bind(this)
this.getStateOrProp = this.getStateOrProp.bind(this) this.getStateOrProp = this.getStateOrProp.bind(this)
this.filterData = this.filterData.bind(this) this.filterData = this.filterData.bind(this)
@@ -33,11 +33,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
this.state = { this.state = {
page: 0, page: 0,
pageSize: props.defaultPageSize || 10, pageSize: props.defaultPageSize,
sorting: props.defaultSorting, sorted: props.defaultSorted,
expandedRows: {}, expanded: props.defaultExpanded,
filtering: props.defaultFiltering, filtered: props.defaultFiltered,
resizing: props.defaultResizing, resized: props.defaultResized,
currentlyResizing: false, currentlyResizing: false,
skipNextSort: false skipNextSort: false
} }
@@ -75,22 +75,28 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
manual, manual,
loadingText, loadingText,
noDataText, noDataText,
showFilters, sortable,
resizable, resizable,
filterable,
// Pivoting State
pivotIDKey,
pivotValKey,
pivotBy,
subRowsKey,
aggregatedKey,
originalKey,
indexKey,
groupedByPivotKey,
// State // State
loading, loading,
pageSize, pageSize,
page, page,
sorting, sorted,
filtering, filtered,
resizing, resized,
expanded,
pages, pages,
// Pivoting State onExpandedChange,
pivotValKey,
pivotBy,
subRowsKey,
expandedRows,
onExpandRow,
// Components // Components
TableComponent, TableComponent,
TheadComponent, TheadComponent,
@@ -105,6 +111,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
SubComponent, SubComponent,
NoDataComponent, NoDataComponent,
ResizerComponent, ResizerComponent,
ExpanderComponent,
PivotValueComponent,
PivotComponent,
AggregatedComponent,
FilterComponent,
// Data model // Data model
resolvedData, resolvedData,
allVisibleColumns, allVisibleColumns,
@@ -122,7 +133,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const minRows = this.getMinRows() const minRows = this.getMinRows()
const padRows = _.range(Math.max(minRows - pageRows.length, 0)) const padRows = _.range(Math.max(minRows - pageRows.length, 0))
const hasColumnFooter = allVisibleColumns.some(d => d.footer || (d.pivotColumns && d.pivotColumns.some(e => e.footer))) const hasColumnFooter = allVisibleColumns.some(d => d.Footer)
const hasFilters = filterable || allVisibleColumns.some(d => d.filterable)
const recurseRowsViewIndex = (rows, path = [], index = -1) => { const recurseRowsViewIndex = (rows, path = [], index = -1) => {
return [ return [
@@ -133,7 +145,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
_viewIndex: index _viewIndex: index
} }
const newPath = path.concat([i]) const newPath = path.concat([i])
if (rowWithViewIndex[subRowsKey] && _.get(expandedRows, newPath)) { if (rowWithViewIndex[subRowsKey] && _.get(expanded, newPath)) {
[rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index) [rowWithViewIndex[subRowsKey], index] = recurseRowsViewIndex(rowWithViewIndex[subRowsKey], newPath, index)
} }
return rowWithViewIndex return rowWithViewIndex
@@ -148,8 +160,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const canNext = page + 1 < pages const canNext = page + 1 < pages
const rowMinWidth = _.sum(allVisibleColumns.map(d => { const rowMinWidth = _.sum(allVisibleColumns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {} const resizedColumn = resized.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.minWidth) return _.getFirstDefined(resizedColumn.value, d.width, d.minWidth)
})) }))
let rowIndex = -1 let rowIndex = -1
@@ -193,22 +205,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeHeaderGroup = (column, i) => { const makeHeaderGroup = (column, i) => {
const resizedValue = col => (resizing.find(x => x.id === col.id) || {}).value const resizedValue = col => (resized.find(x => x.id === col.id) || {}).value
const flex = _.sum(column.columns.map(col => col.width || resizedValue(col) ? 0 : col.minWidth))
const flex = _.sum(column.columns.map(d => { const width = _.sum(column.columns.map(col => _.getFirstDefined(resizedValue(col), col.width, col.minWidth)))
const widthFunction = col => col.width || resizedValue(col) ? 0 : col.minWidth const maxWidth = _.sum(column.columns.map(col => _.getFirstDefined(resizedValue(col), col.width, col.maxWidth)))
return d.pivotColumns ? _.sum(d.pivotColumns.map(widthFunction)) : widthFunction(d)
}))
const width = _.sum(column.columns.map(d => {
const widthFunction = col => _.getFirstDefined(resizedValue(col), col.width, col.minWidth)
return d.pivotColumns ? _.sum(d.pivotColumns.map(widthFunction)) : widthFunction(d)
}))
const maxWidth = _.sum(column.columns.map(d => {
const widthFunction = col => _.getFirstDefined(resizedValue(col), col.width, col.maxWidth)
return d.pivotColumns ? _.sum(d.pivotColumns.map(widthFunction)) : widthFunction(d)
}))
const theadGroupThProps = _.splitProps(getTheadGroupThProps(finalState, undefined, column, this)) const theadGroupThProps = _.splitProps(getTheadGroupThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -248,7 +248,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}} }}
{...rest} {...rest}
> >
{_.normalizeComponent(column.header, { {_.normalizeComponent(column.Header, {
data: sortedData, data: sortedData,
column: column column: column
})} })}
@@ -280,11 +280,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeHeader = (column, i) => { const makeHeader = (column, i) => {
const resized = resizing.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const sort = sorting.find(d => d.id === column.id) const sort = sorted.find(d => d.id === column.id)
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(resized.value, column.width, column.minWidth) const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth) const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const theadThProps = _.splitProps(getTheadThProps(finalState, undefined, column, this)) const theadThProps = _.splitProps(getTheadThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -305,7 +305,8 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
...columnHeaderProps.rest ...columnHeaderProps.rest
} }
const resizer = resizable ? ( const isResizable = _.getFirstDefined(column.resizable, resizable, false)
const resizer = isResizable ? (
<ResizerComponent <ResizerComponent
onMouseDown={e => this.resizeColumnStart(column, e, false)} onMouseDown={e => this.resizeColumnStart(column, e, false)}
onTouchStart={e => this.resizeColumnStart(column, e, true)} onTouchStart={e => this.resizeColumnStart(column, e, true)}
@@ -314,9 +315,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
/> />
) : null ) : null
if (column.pivotColumns) { const isSortable = _.getFirstDefined(column.sortable, sortable, false)
return column.pivotColumns.map(makeHeader)
}
return ( return (
<ThComponent <ThComponent
@@ -325,7 +324,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
classes, classes,
'rt-resizable-header', 'rt-resizable-header',
sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '', sort ? (sort.desc ? '-sort-desc' : '-sort-asc') : '',
column.sortable && '-cursor-pointer', isSortable && '-cursor-pointer',
!show && '-hidden', !show && '-hidden',
pivotBy && pivotBy.slice(0, -1).includes(column.id) && 'rt-header-pivot' pivotBy && pivotBy.slice(0, -1).includes(column.id) && 'rt-header-pivot'
)} )}
@@ -336,12 +335,12 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
maxWidth: `${maxWidth}px` maxWidth: `${maxWidth}px`
}} }}
toggleSort={(e) => { toggleSort={(e) => {
column.sortable && this.sortColumn(column, e.shiftKey) isSortable && this.sortColumn(column, e.shiftKey)
}} }}
{...rest} {...rest}
> >
<div className='rt-resizable-header-content'> <div className='rt-resizable-header-content'>
{_.normalizeComponent(column.header, { {_.normalizeComponent(column.Header, {
data: sortedData, data: sortedData,
column: column column: column
})} })}
@@ -375,9 +374,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeFilter = (column, i) => { const makeFilter = (column, i) => {
const resized = resizing.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const width = _.getFirstDefined(resized.value, column.width, column.minWidth) const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth) const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const theadFilterThProps = _.splitProps(getTheadFilterThProps(finalState, undefined, column, this)) const theadFilterThProps = _.splitProps(getTheadFilterThProps(finalState, undefined, column, this))
const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this)) const columnHeaderProps = _.splitProps(column.getHeaderProps(finalState, undefined, column, this))
@@ -398,11 +397,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
...columnHeaderProps.rest ...columnHeaderProps.rest
} }
if (!column.filterRender && column.pivotColumns) { const filter = filtered.find(filter => filter.id === column.id)
return column.pivotColumns.map(makeFilter)
}
const filter = filtering.find(filter => filter.id === column.id) const ResolvedFilterComponent = column.Filter || FilterComponent
const isFilterable = _.getFirstDefined(column.filterable, filterable, false)
return ( return (
<ThComponent <ThComponent
@@ -418,14 +417,14 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
}} }}
{...rest} {...rest}
> >
{!column.hideFilter ? ( {isFilterable ? (
_.normalizeComponent(column.filterRender, _.normalizeComponent(ResolvedFilterComponent,
{ {
column, column,
filter, filter,
onFilterChange: (value) => (this.filterColumn(column, value)) onChange: (value) => (this.filterColumn(column, value))
}, },
defaultProps.column.filterRender defaultProps.column.Filter
) )
) : null} ) : null}
</ThComponent> </ThComponent>
@@ -434,16 +433,17 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
const makePageRow = (row, i, path = []) => { const makePageRow = (row, i, path = []) => {
const rowInfo = { const rowInfo = {
row: row.__original, original: row[originalKey],
rowValues: row, row: row,
index: row.__index, index: row[indexKey],
viewIndex: ++rowIndex, viewIndex: ++rowIndex,
level: path.length, level: path.length,
nestingPath: path.concat([i]), nestingPath: path.concat([i]),
aggregated: !!row[subRowsKey], aggregated: row[aggregatedKey],
groupedByPivot: row[groupedByPivotKey],
subRows: row[subRowsKey] subRows: row[subRowsKey]
} }
const isExpanded = _.get(expandedRows, rowInfo.nestingPath) const isExpanded = _.get(expanded, rowInfo.nestingPath)
const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this) const trGroupProps = getTrGroupProps(finalState, rowInfo, undefined, this)
const trProps = _.splitProps(getTrProps(finalState, rowInfo, undefined, this)) const trProps = _.splitProps(getTrProps(finalState, rowInfo, undefined, this))
return ( return (
@@ -460,11 +460,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...trProps.rest} {...trProps.rest}
> >
{allVisibleColumns.map((column, i2) => { {allVisibleColumns.map((column, i2) => {
const cellInfo = { ...rowInfo, column: {...column} } const resizedCol = resized.find(x => x.id === column.id) || {}
const resized = resizing.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(resized.value, column.width, column.minWidth) const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth) const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const tdProps = _.splitProps(getTdProps(finalState, rowInfo, column, this)) const tdProps = _.splitProps(getTdProps(finalState, rowInfo, column, this))
const columnProps = _.splitProps(column.getProps(finalState, rowInfo, column, this)) const columnProps = _.splitProps(column.getProps(finalState, rowInfo, column, this))
@@ -480,83 +479,128 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
...columnProps.style ...columnProps.style
} }
const extraProps = {} const cellInfo = {
...rowInfo,
isExpanded,
column: {...column},
value: rowInfo.row[column.id],
pivoted: column.pivoted,
expander: column.expander,
resized,
show,
width,
maxWidth,
tdProps,
columnProps,
classes,
styles
}
if (column.expander) { const value = cellInfo.value
const onTdClick = (e) => {
if (onExpandRow) { let interactionProps
return onExpandRow(cellInfo.nestingPath, e) let isBranch
} let isPreview
let newExpandedRows = _.clone(expandedRows)
if (isExpanded) { const onExpanderClick = (e) => {
return this.setStateWithData({ let newExpanded = _.clone(expanded)
expandedRows: _.set(newExpandedRows, cellInfo.nestingPath, false) if (isExpanded) {
}) newExpanded = _.set(newExpanded, cellInfo.nestingPath, false)
} } else {
return this.setStateWithData({ newExpanded = _.set(newExpanded, cellInfo.nestingPath, {})
expandedRows: _.set(newExpandedRows, cellInfo.nestingPath, {})
})
} }
if (onExpandedChange) {
onExpandedChange(newExpanded, cellInfo.nestingPath, e)
}
// If expanded is being controlled, don't manage internal state
if (this.props.expanded) {
return
}
return this.setStateWithData({
expanded: newExpanded
})
}
extraProps['onClick'] = onTdClick // Default to a standard cell
let resolvedCell = _.normalizeComponent(column.Cell, cellInfo, value)
if (column.pivotColumns) { // Resolve Renderers
const pivotFlex = _.sum(column.pivotColumns.map(d => { const ResolvedAggregatedComponent = column.Aggregated || (!column.aggregate ? AggregatedComponent : column.Cell)
const resized = resizing.find(x => x.id === d.id) || {} const ResolvedExpanderComponent = column.Expander || ExpanderComponent
return d.width || resized.value ? 0 : d.minWidth const ResolvedPivotValueComponent = column.PivotValue || PivotValueComponent
})) const DefaultResolvedPivotComponent = PivotComponent || (
const pivotWidth = _.sum(column.pivotColumns.map(d => { props => (
const resized = resizing.find(x => x.id === d.id) || {} <div>
return _.getFirstDefined(resized.value, d.width, d.minWidth) <ResolvedExpanderComponent {...props} />
})) <ResolvedPivotValueComponent {...props} />
const pivotMaxWidth = _.sum(column.pivotColumns.map(d => { </div>
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.maxWidth)
}))
// Return the pivot expander cell
return (
<TdComponent
key={i2}
className={classnames(
'rt-pivot',
classes
)}
style={{
...styles,
paddingLeft: rowInfo.nestingPath.length === 1 ? undefined : `${30 * (cellInfo.nestingPath.length - 1)}px`,
flex: `${pivotFlex} 0 auto`,
width: `${pivotWidth}px`,
maxWidth: `${pivotMaxWidth}px`
}}
{...tdProps.rest}
onClick={onTdClick}
>
{cellInfo.subRows ? (
_.normalizeComponent(column.render, {
...cellInfo,
value: row[pivotValKey],
isExpanded
}, cellInfo.rowValues[column.id])
) : SubComponent ? (
_.normalizeComponent(column.render, {
...cellInfo,
value: cellInfo.rowValues[column.id],
isExpanded
}, cellInfo.rowValues[column.id])
) : null}
</TdComponent>
) )
)
const ResolvedPivotComponent = column.Pivot || DefaultResolvedPivotComponent
// Is this cell expandable?
if (cellInfo.pivoted || cellInfo.expander) {
// Make it expandable by defualt
cellInfo.expandable = true
interactionProps = {
onClick: onExpanderClick
}
// If pivoted, has no subRows, and does not have a subComponent, do not make expandable
if (cellInfo.pivoted) {
if (!cellInfo.subRows) {
if (!SubComponent) {
cellInfo.expandable = false
interactionProps = {}
}
}
} }
} }
// Return regular cell if (cellInfo.pivoted) {
// Is this column a branch?
isBranch = rowInfo.row[pivotIDKey] === column.id &&
cellInfo.subRows
// Should this column be blank?
isPreview = pivotBy.indexOf(column.id) > pivotBy.indexOf(rowInfo.row[pivotIDKey]) &&
cellInfo.subRows
// Pivot Cell Render Override
if (isBranch) {
// isPivot
resolvedCell = _.normalizeComponent(ResolvedPivotComponent, {
...cellInfo,
value: row[pivotValKey]
}, row[pivotValKey])
} else if (isPreview) {
// Show the pivot preview
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value)
} else {
resolvedCell = null
}
} else if (cellInfo.aggregated) {
resolvedCell = _.normalizeComponent(ResolvedAggregatedComponent, cellInfo, value)
}
if (cellInfo.expander) {
resolvedCell = _.normalizeComponent(ResolvedExpanderComponent, cellInfo, row[pivotValKey])
if (pivotBy) {
if (cellInfo.groupedByPivot) {
resolvedCell = null
}
if (!cellInfo.subRows && !SubComponent) {
resolvedCell = null
}
}
}
// Return the cell
return ( return (
<TdComponent <TdComponent
key={i2 + '-' + column.id} key={i2 + '-' + column.id}
className={classnames( className={classnames(
classes, classes,
!show && 'hidden' !show && 'hidden',
cellInfo.expandable && 'rt-expandable',
(isBranch || isPreview) && 'rt-pivot'
)} )}
style={{ style={{
...styles, ...styles,
@@ -565,13 +609,9 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
maxWidth: `${maxWidth}px` maxWidth: `${maxWidth}px`
}} }}
{...tdProps.rest} {...tdProps.rest}
{...extraProps} {...interactionProps}
> >
{_.normalizeComponent(column.render, { {resolvedCell}
...cellInfo,
value: cellInfo.rowValues[column.id],
isExpanded
}, cellInfo.rowValues[column.id])}
</TdComponent> </TdComponent>
) )
})} })}
@@ -609,11 +649,11 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makePadColumn = (column, i) => { const makePadColumn = (column, i) => {
const resized = resizing.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function' ? column.show() : column.show
let width = _.getFirstDefined(resized.value, column.width, column.minWidth) let width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
let flex = width let flex = width
let maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth) let maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this)) const tdProps = _.splitProps(getTdProps(finalState, undefined, column, this))
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this)) const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
@@ -629,21 +669,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
...columnProps.style ...columnProps.style
} }
if (column.pivotColumns) {
flex = _.sum(column.pivotColumns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return d.width || resized.value ? 0 : d.minWidth
}))
width = _.sum(column.pivotColumns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.minWidth)
}))
maxWidth = _.sum(column.pivotColumns.map(d => {
const resized = resizing.find(x => x.id === d.id) || {}
return _.getFirstDefined(resized.value, d.width, d.maxWidth)
}))
}
return ( return (
<TdComponent <TdComponent
key={i + '-' + column.id} key={i + '-' + column.id}
@@ -690,10 +715,10 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
} }
const makeColumnFooter = (column, i) => { const makeColumnFooter = (column, i) => {
const resized = resizing.find(x => x.id === column.id) || {} const resizedCol = resized.find(x => x.id === column.id) || {}
const show = typeof column.show === 'function' ? column.show() : column.show const show = typeof column.show === 'function' ? column.show() : column.show
const width = _.getFirstDefined(resized.value, column.width, column.minWidth) const width = _.getFirstDefined(resizedCol.value, column.width, column.minWidth)
const maxWidth = _.getFirstDefined(resized.value, column.width, column.maxWidth) const maxWidth = _.getFirstDefined(resizedCol.value, column.width, column.maxWidth)
const tFootTdProps = _.splitProps(getTfootTdProps(finalState, undefined, undefined, this)) const tFootTdProps = _.splitProps(getTfootTdProps(finalState, undefined, undefined, this))
const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this)) const columnProps = _.splitProps(column.getProps(finalState, undefined, column, this))
const columnFooterProps = _.splitProps(column.getFooterProps(finalState, undefined, column, this)) const columnFooterProps = _.splitProps(column.getFooterProps(finalState, undefined, column, this))
@@ -712,10 +737,6 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
...columnFooterProps.style ...columnFooterProps.style
} }
if (!column.footer && column.pivotColumns) {
return column.pivotColumns.map(makeColumnFooter)
}
return ( return (
<TdComponent <TdComponent
key={i + '-' + column.id} key={i + '-' + column.id}
@@ -733,7 +754,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
{...tFootTdProps.rest} {...tFootTdProps.rest}
{...columnFooterProps.rest} {...columnFooterProps.rest}
> >
{_.normalizeComponent(column.footer, { {_.normalizeComponent(column.Footer, {
data: sortedData, data: sortedData,
column: column column: column
})} })}
@@ -772,7 +793,7 @@ export default class ReactTable extends Methods(Lifecycle(Component)) {
> >
{hasHeaderGroups ? makeHeaderGroups() : null} {hasHeaderGroups ? makeHeaderGroups() : null}
{makeHeaders()} {makeHeaders()}
{showFilters ? makeFilters() : null} {hasFilters ? makeFilters() : null}
<TbodyComponent <TbodyComponent
className={classnames(tBodyProps.className)} className={classnames(tBodyProps.className)}
style={{ style={{
+2 -2
View File
@@ -102,7 +102,7 @@ $expandSize = 7px
border-right:1px solid alpha(black, .02) border-right:1px solid alpha(black, .02)
&:last-child &:last-child
border-right:0 border-right:0
.rt-pivot .rt-expandable
cursor: pointer cursor: pointer
.rt-tr-group .rt-tr-group
display: flex display: flex
@@ -318,4 +318,4 @@ $expandSize = 7px
.rt-td .rt-td
transition: none!important transition: none!important
cursor: col-resize cursor: col-resize
user-select none user-select none
+33 -19
View File
@@ -5,30 +5,44 @@ export default Base => class extends Base {
} }
componentDidMount () { componentDidMount () {
this.fireOnChange() this.fireFetchData()
} }
componentWillReceiveProps (nextProps, nextState) { componentWillReceiveProps (nextProps, nextState) {
const oldState = this.getResolvedState() const oldState = this.getResolvedState()
const newState = this.getResolvedState(nextProps, nextState) const newState = this.getResolvedState(nextProps, nextState)
if (oldState.defaultSorting !== newState.defaultSorting) { // Do a deep compare of new and old `defaultOption` and
newState.sorting = newState.defaultSorting // if they are different reset `option = defaultOption`
} const defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded']
defaultableOptions.forEach(x => {
const defaultName = `default${x.charAt(0).toUpperCase() + x.slice(1)}`
if (JSON.stringify(oldState[defaultName]) !== JSON.stringify(newState[defaultName])) {
newState[x] = newState[defaultName]
}
})
if ((oldState.showFilters !== newState.showFilters) || // If they change these table options, we need to reset defaults
(oldState.showFilters !== newState.showFilters)) { // or else we could get into a state where the user has changed the UI
newState.filtering = newState.defaultFiltering // and then disabled the ability to change it back.
} // e.g. If `filterable` has changed, set `filtered = defaultFiltered`
const resettableOptions = ['sortable', 'filterable', 'resizable']
resettableOptions.forEach(x => {
if (oldState[x] !== newState[x]) {
const baseName = x.replace('able', '')
const optionName = `${baseName}ed`
const defaultName = `default${optionName.charAt(0).toUpperCase() + optionName.slice(1)}`
newState[optionName] = newState[defaultName]
}
})
// Props that trigger a data update // Props that trigger a data update
if ( if (
oldState.data !== newState.data || oldState.data !== newState.data ||
oldState.columns !== newState.columns || oldState.columns !== newState.columns ||
oldState.pivotBy !== newState.pivotBy || oldState.pivotBy !== newState.pivotBy ||
oldState.sorting !== newState.sorting || oldState.sorted !== newState.sorted ||
oldState.showFilters !== newState.showFilters || oldState.filtered !== newState.filtered
oldState.filtering !== newState.filtering
) { ) {
this.setStateWithData(this.getDataModel(newState)) this.setStateWithData(this.getDataModel(newState))
} }
@@ -45,9 +59,9 @@ export default Base => class extends Base {
// If freezeWhenExpanded is set, check for frozen conditions // If freezeWhenExpanded is set, check for frozen conditions
if (freezeWhenExpanded) { if (freezeWhenExpanded) {
// if any rows are expanded, freeze the existing data and sorting // if any rows are expanded, freeze the existing data and sorting
const keys = Object.keys(newResolvedState.expandedRows) const keys = Object.keys(newResolvedState.expanded)
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
if (newResolvedState.expandedRows[keys[i]]) { if (newResolvedState.expanded[keys[i]]) {
newResolvedState.frozen = true newResolvedState.frozen = true
break break
} }
@@ -58,19 +72,19 @@ export default Base => class extends Base {
// sorting model has changed, update the data // sorting model has changed, update the data
if ( if (
(oldState.frozen && !newResolvedState.frozen) || (oldState.frozen && !newResolvedState.frozen) ||
oldState.sorting !== newResolvedState.sorting || oldState.sorted !== newResolvedState.sorted ||
oldState.filtering !== newResolvedState.filtering || oldState.filtered !== newResolvedState.filtered ||
oldState.showFilters !== newResolvedState.showFilters || oldState.showFilters !== newResolvedState.showFilters ||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData) (!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData)
) { ) {
// Handle collapseOnSortingChange & collapseOnDataChange // Handle collapseOnsortedChange & collapseOnDataChange
if ( if (
(oldState.sorting !== newResolvedState.sorting && this.props.collapseOnSortingChange) || (oldState.sorted !== newResolvedState.sorted && this.props.collapseOnSortingChange) ||
(oldState.filtering !== newResolvedState.filtering) || (oldState.filtered !== newResolvedState.filtered) ||
(oldState.showFilters !== newResolvedState.showFilters) || (oldState.showFilters !== newResolvedState.showFilters) ||
(!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnDataChange) (!newResolvedState.frozen && oldState.resolvedData !== newResolvedState.resolvedData && this.props.collapseOnDataChange)
) { ) {
newResolvedState.expandedRows = {} newResolvedState.expanded = {}
} }
Object.assign(newResolvedState, this.getSortedData(newResolvedState)) Object.assign(newResolvedState, this.getSortedData(newResolvedState))
+182 -139
View File
@@ -20,6 +20,11 @@ export default Base => class extends Base {
pivotIDKey, pivotIDKey,
pivotValKey, pivotValKey,
subRowsKey, subRowsKey,
aggregatedKey,
nestingLevelKey,
originalKey,
indexKey,
groupedByPivotKey,
SubComponent SubComponent
} = newState } = newState
@@ -31,20 +36,6 @@ export default Base => class extends Base {
} }
}) })
// Build Header Groups
const headerGroups = []
let currentSpan = []
// A convenience function to add a header and reset the currentSpan
const addHeader = (columns, column = columns[0]) => {
headerGroups.push({
...this.props.column,
...column,
columns: columns
})
currentSpan = []
}
let columnsWithExpander = [...columns] let columnsWithExpander = [...columns]
let expanderColumn = columns.find(col => col.expander || (col.columns && col.columns.some(col2 => col2.expander))) let expanderColumn = columns.find(col => col.expander || (col.columns && col.columns.some(col2 => col2.expander)))
@@ -53,30 +44,17 @@ export default Base => class extends Base {
expanderColumn = expanderColumn.columns.find(col => col.expander) expanderColumn = expanderColumn.columns.find(col => col.expander)
} }
// If it has subrows or pivot columns we need to make sure we have an expander column // If we have SubComponent's we need to make sure we have an expander column
if ((SubComponent || pivotBy.length) && !expanderColumn) { if (SubComponent && !expanderColumn) {
expanderColumn = {expander: true} expanderColumn = {expander: true}
columnsWithExpander = [expanderColumn, ...columnsWithExpander] columnsWithExpander = [expanderColumn, ...columnsWithExpander]
} }
const makeDecoratedColumn = (column) => { const makeDecoratedColumn = (column) => {
let dcol let dcol
if (pivotBy.length && column.expander) { if (column.expander) {
dcol = { dcol = {
...this.props.column, ...this.props.column,
render: (props) => (
<div>
<this.props.ExpanderComponent {...props} />
<this.props.PivotValueComponent {...props} />
</div>
),
...this.props.pivotDefaults,
...column
}
} else if (column.expander) {
dcol = {
...this.props.column,
render: this.props.ExpanderComponent,
...this.props.expanderDefaults, ...this.props.expanderDefaults,
...column ...column
} }
@@ -148,34 +126,55 @@ export default Base => class extends Base {
return column.columns ? column.columns.length : pivotBy.indexOf(column.id) > -1 ? false : _.getFirstDefined(column.show, true) return column.columns ? column.columns.length : pivotBy.indexOf(column.id) > -1 ? false : _.getFirstDefined(column.show, true)
}) })
// Move the pivot columns into a single column if needed // Find any custom pivot location
const pivotIndex = visibleColumns.findIndex(col => col.pivot)
// Handle Pivot Columns
if (pivotBy.length) { if (pivotBy.length) {
// Retrieve the pivot columns in the correct pivot order
const pivotColumns = [] const pivotColumns = []
for (var i = 0; i < allDecoratedColumns.length; i++) { pivotBy.forEach(pivotID => {
if (pivotBy.indexOf(allDecoratedColumns[i].id) > -1) { const found = allDecoratedColumns.find(d => d.id === pivotID)
pivotColumns.push(allDecoratedColumns[i]) if (found) {
pivotColumns.push(found)
} }
})
let pivotColumnGroup = {
header: () => <strong>Group</strong>,
columns: pivotColumns.map(col => ({
...this.props.pivotDefaults,
...col,
pivoted: true
}))
} }
const pivotExpanderColumn = visibleColumns.findIndex(col => col.expander || (col.columns && col.columns.some(col2 => col2.expander))) // Place the pivotColumns back into the visibleColumns
if (pivotExpanderColumn >= 0) { if (pivotIndex >= 0) {
const pivotColumn = { pivotColumnGroup = {
...visibleColumns[pivotExpanderColumn], ...visibleColumns[pivotIndex],
pivotColumns ...pivotColumnGroup
} }
visibleColumns[pivotExpanderColumn] = pivotColumn visibleColumns.splice(pivotIndex, 1, pivotColumnGroup)
} else { } else {
// If the expander column wasn't on the top level column, find it in the `columns` option. visibleColumns.unshift(pivotColumnGroup)
const pivotExpanderSubColumn = visibleColumns[pivotExpanderColumn].columns.findIndex(col => col.expander)
const pivotColumn = {
...visibleColumns[pivotExpanderColumn].columns[pivotExpanderSubColumn],
pivotColumns
}
// Add the pivot columns to the expander column
visibleColumns[pivotExpanderColumn].columns[pivotExpanderSubColumn] = pivotColumn
} }
} }
// Build Header Groups
const headerGroups = []
let currentSpan = []
// A convenience function to add a header and reset the currentSpan
const addHeader = (columns, column) => {
headerGroups.push({
...this.props.column,
...column,
columns: columns
})
currentSpan = []
}
// Build flast list of allVisibleColumns and HeaderGroups // Build flast list of allVisibleColumns and HeaderGroups
visibleColumns.forEach((column, i) => { visibleColumns.forEach((column, i) => {
if (column.columns) { if (column.columns) {
@@ -194,17 +193,23 @@ export default Base => class extends Base {
} }
// Access the data // Access the data
let resolvedData = data.map((d, i) => { const accessRow = (d, i, level = 0) => {
const row = { const row = {
__original: d, [originalKey]: d,
__index: i [indexKey]: i,
[subRowsKey]: d[subRowsKey],
[nestingLevelKey]: level
} }
allDecoratedColumns.forEach(column => { allDecoratedColumns.forEach(column => {
if (column.expander) return if (column.expander) return
row[column.id] = column.accessor(d) row[column.id] = column.accessor(d)
}) })
if (row[subRowsKey]) {
row[subRowsKey] = row[subRowsKey].map((d, i) => accessRow(d, i, level + 1))
}
return row return row
}) }
let resolvedData = data.map((d, i) => accessRow(d, i))
// If pivoting, recursively group the data // If pivoting, recursively group the data
const aggregate = (rows) => { const aggregate = (rows) => {
@@ -215,10 +220,10 @@ export default Base => class extends Base {
}) })
return aggregationValues return aggregationValues
} }
// TODO: Make it possible to fabricate nested rows without pivoting
const aggregatingColumns = allVisibleColumns.filter(d => !d.expander && d.aggregate) const aggregatingColumns = allVisibleColumns.filter(d => !d.expander && d.aggregate)
let pivotColumn
if (pivotBy.length) { if (pivotBy.length) {
pivotColumn = allVisibleColumns[0]
const groupRecursively = (rows, keys, i = 0) => { const groupRecursively = (rows, keys, i = 0) => {
// This is the last level, just return the rows // This is the last level, just return the rows
if (i === keys.length) { if (i === keys.length) {
@@ -232,7 +237,9 @@ export default Base => class extends Base {
[pivotIDKey]: keys[i], [pivotIDKey]: keys[i],
[pivotValKey]: key, [pivotValKey]: key,
[keys[i]]: key, [keys[i]]: key,
[subRowsKey]: value [subRowsKey]: value,
[nestingLevelKey]: i,
[groupedByPivotKey]: true
} }
}) })
// Recurse into the subRows // Recurse into the subRows
@@ -241,6 +248,7 @@ export default Base => class extends Base {
return { return {
...rowGroup, ...rowGroup,
[subRowsKey]: subRows, [subRowsKey]: subRows,
[aggregatedKey]: true,
...aggregate(subRows) ...aggregate(subRows)
} }
}) })
@@ -252,7 +260,6 @@ export default Base => class extends Base {
return { return {
...newState, ...newState,
resolvedData, resolvedData,
pivotColumn,
allVisibleColumns, allVisibleColumns,
headerGroups, headerGroups,
allDecoratedColumns, allDecoratedColumns,
@@ -263,22 +270,39 @@ export default Base => class extends Base {
getSortedData (resolvedState) { getSortedData (resolvedState) {
const { const {
manual, manual,
sorting, sorted,
filtering, filtered,
showFilters,
defaultFilterMethod, defaultFilterMethod,
resolvedData, resolvedData,
allVisibleColumns allVisibleColumns,
allDecoratedColumns
} = resolvedState } = resolvedState
const sortMethodsByColumnID = {}
allDecoratedColumns
.filter(col => col.sortMethod)
.forEach(col => {
sortMethodsByColumnID[col.id] = col.sortMethod
})
// Resolve the data from either manual data or sorted data // Resolve the data from either manual data or sorted data
return { return {
sortedData: manual ? resolvedData : this.sortData(this.filterData(resolvedData, showFilters, filtering, defaultFilterMethod, allVisibleColumns), sorting) sortedData: manual ? resolvedData : this.sortData(
this.filterData(
resolvedData,
filtered,
defaultFilterMethod,
allVisibleColumns
),
sorted,
sortMethodsByColumnID
)
} }
} }
fireOnChange () { fireFetchData () {
this.props.onChange(this.getResolvedState(), this) this.props.onFetchData(this.getResolvedState(), this)
} }
getPropOrState (key) { getPropOrState (key) {
@@ -289,11 +313,11 @@ export default Base => class extends Base {
return _.getFirstDefined(this.state[key], this.props[key]) return _.getFirstDefined(this.state[key], this.props[key])
} }
filterData (data, showFilters, filtering, defaultFilterMethod, allVisibleColumns) { filterData (data, filtered, defaultFilterMethod, allVisibleColumns) {
let filteredData = data let filteredData = data
if (showFilters && filtering.length) { if (filtered.length) {
filteredData = filtering.reduce( filteredData = filtered.reduce(
(filteredSoFar, nextFilter) => { (filteredSoFar, nextFilter) => {
return filteredSoFar.filter( return filteredSoFar.filter(
(row) => { (row) => {
@@ -306,9 +330,9 @@ export default Base => class extends Base {
column = column.pivotColumns.find(x => x.id === nextFilter.id) column = column.pivotColumns.find(x => x.id === nextFilter.id)
} }
// Don't filter hidden columns // Don't filter hidden columns or columns that have had their filters disabled
if (!column) { if (!column || column.filterable === false) {
return return true
} }
const filterMethod = column.filterMethod || defaultFilterMethod const filterMethod = column.filterMethod || defaultFilterMethod
@@ -327,7 +351,7 @@ export default Base => class extends Base {
} }
return { return {
...row, ...row,
[this.props.subRowsKey]: this.filterData(row[this.props.subRowsKey], showFilters, filtering, defaultFilterMethod, allVisibleColumns) [this.props.subRowsKey]: this.filterData(row[this.props.subRowsKey], filtered, defaultFilterMethod, allVisibleColumns)
} }
}).filter(row => { }).filter(row => {
if (!row[this.props.subRowsKey]) { if (!row[this.props.subRowsKey]) {
@@ -340,29 +364,36 @@ export default Base => class extends Base {
return filteredData return filteredData
} }
sortData (data, sorting) { sortData (data, sorted, sortMethodsByColumnID = {}) {
if (!sorting.length) { if (!sorted.length) {
return data return data
} }
const sorted = _.orderBy(data, sorting.map(sort => { const sortedData = (this.props.orderByMethod || _.orderBy)(
return row => { data,
if (row[sort.id] === null || row[sort.id] === undefined) { sorted.map(sort => {
return -Infinity // Support custom sorting methods for each column
if (sortMethodsByColumnID[sort.id]) {
return (a, b) => {
return sortMethodsByColumnID[sort.id](a[sort.id], b[sort.id])
}
} }
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id] return (a, b) => {
} return this.props.defaultSortMethod(a[sort.id], b[sort.id])
}), sorting.map(d => !d.desc)) }
}),
sorted.map(d => !d.desc),
this.props.indexKey
)
return sorted.map(row => { sortedData.forEach(row => {
if (!row[this.props.subRowsKey]) { if (!row[this.props.subRowsKey]) {
return row return
}
return {
...row,
[this.props.subRowsKey]: this.sortData(row[this.props.subRowsKey], sorting)
} }
row[this.props.subRowsKey] = this.sortData(row[this.props.subRowsKey], sorted, sortMethodsByColumnID)
}) })
return sortedData
} }
getMinRows () { getMinRows () {
@@ -372,18 +403,19 @@ export default Base => class extends Base {
// User actions // User actions
onPageChange (page) { onPageChange (page) {
const {onPageChange, collapseOnPageChange} = this.props const {onPageChange, collapseOnPageChange} = this.props
if (onPageChange) { onPageChange && onPageChange(page)
return onPageChange(page) // If controlled, do not keep track of state
if (typeof this.props.page !== 'undefined') {
this.fireFetchData()
return
} }
const newState = {page} const newState = {page}
if (collapseOnPageChange) { if (collapseOnPageChange) {
newState.expandedRows = {} newState.expanded = {}
} }
this.setStateWithData( this.setStateWithData(newState, () => {
newState this.fireFetchData()
, () => { })
this.fireOnChange()
})
} }
onPageSizeChange (newPageSize) { onPageSizeChange (newPageSize) {
@@ -394,20 +426,22 @@ export default Base => class extends Base {
const currentRow = pageSize * page const currentRow = pageSize * page
const newPage = Math.floor(currentRow / newPageSize) const newPage = Math.floor(currentRow / newPageSize)
if (onPageSizeChange) { onPageSizeChange && onPageSizeChange(newPageSize, newPage)
return onPageSizeChange(newPageSize, newPage) if (typeof this.props.page !== 'undefined') {
this.fireFetchData()
return
} }
this.setStateWithData({ this.setStateWithData({
pageSize: newPageSize, pageSize: newPageSize,
page: newPage page: newPage
}, () => { }, () => {
this.fireOnChange() this.fireFetchData()
}) })
} }
sortColumn (column, additive) { sortColumn (column, additive) {
const {sorting, skipNextSort} = this.getResolvedState() const {sorted, skipNextSort} = this.getResolvedState()
// we can't stop event propagation from the column resize move handlers // we can't stop event propagation from the column resize move handlers
// attached to the document because of react's synthetic events // attached to the document because of react's synthetic events
@@ -420,40 +454,38 @@ export default Base => class extends Base {
return return
} }
const {onSortingChange} = this.props const {onSortedChange} = this.props
if (onSortingChange) {
return onSortingChange(column, additive) let newSorted = _.clone(sorted || []).map(d => {
}
let newSorting = _.clone(sorting || []).map(d => {
d.desc = _.isSortingDesc(d) d.desc = _.isSortingDesc(d)
return d return d
}) })
if (!_.isArray(column)) { if (!_.isArray(column)) {
// Single-Sort // Single-Sort
const existingIndex = newSorting.findIndex(d => d.id === column.id) const existingIndex = newSorted.findIndex(d => d.id === column.id)
if (existingIndex > -1) { if (existingIndex > -1) {
const existing = newSorting[existingIndex] const existing = newSorted[existingIndex]
if (existing.desc) { if (existing.desc) {
if (additive) { if (additive) {
newSorting.splice(existingIndex, 1) newSorted.splice(existingIndex, 1)
} else { } else {
existing.desc = false existing.desc = false
newSorting = [existing] newSorted = [existing]
} }
} else { } else {
existing.desc = true existing.desc = true
if (!additive) { if (!additive) {
newSorting = [existing] newSorted = [existing]
} }
} }
} else { } else {
if (additive) { if (additive) {
newSorting.push({ newSorted.push({
id: column.id, id: column.id,
desc: false desc: false
}) })
} else { } else {
newSorting = [{ newSorted = [{
id: column.id, id: column.id,
desc: false desc: false
}] }]
@@ -461,59 +493,61 @@ export default Base => class extends Base {
} }
} else { } else {
// Multi-Sort // Multi-Sort
const existingIndex = newSorting.findIndex(d => d.id === column[0].id) const existingIndex = newSorted.findIndex(d => d.id === column[0].id)
// Existing Sorted Column // Existing Sorted Column
if (existingIndex > -1) { if (existingIndex > -1) {
const existing = newSorting[existingIndex] const existing = newSorted[existingIndex]
if (existing.desc) { if (existing.desc) {
if (additive) { if (additive) {
newSorting.splice(existingIndex, column.length) newSorted.splice(existingIndex, column.length)
} else { } else {
column.forEach((d, i) => { column.forEach((d, i) => {
newSorting[existingIndex + i].desc = false newSorted[existingIndex + i].desc = false
}) })
} }
} else { } else {
column.forEach((d, i) => { column.forEach((d, i) => {
newSorting[existingIndex + i].desc = true newSorted[existingIndex + i].desc = true
}) })
} }
if (!additive) { if (!additive) {
newSorting = newSorting.slice(existingIndex, column.length) newSorted = newSorted.slice(existingIndex, column.length)
} }
} else { } else {
// New Sort Column // New Sort Column
if (additive) { if (additive) {
newSorting = newSorting.concat(column.map(d => ({ newSorted = newSorted.concat(column.map(d => ({
id: d.id, id: d.id,
desc: false desc: false
}))) })))
} else { } else {
newSorting = column.map(d => ({ newSorted = column.map(d => ({
id: d.id, id: d.id,
desc: false desc: false
})) }))
} }
} }
} }
// If controlled, do not keep track of state
onSortedChange && onSortedChange(newSorted, column, additive)
if (typeof this.props.sorted !== 'undefined') {
this.fireFetchData()
return
}
this.setStateWithData({ this.setStateWithData({
page: ((!sorting.length && newSorting.length) || !additive) ? 0 : this.state.page, page: ((!sorted.length && newSorted.length) || !additive) ? 0 : this.state.page,
sorting: newSorting sorted: newSorted
}, () => { }, () => {
this.fireOnChange() this.fireFetchData()
}) })
} }
filterColumn (column, value) { filterColumn (column, value) {
const {filtering} = this.getResolvedState() const {filtered} = this.getResolvedState()
const {onFilteringChange} = this.props const {onFilteredChange} = this.props
if (onFilteringChange) {
return onFilteringChange(column, value)
}
// Remove old filter first if it exists // Remove old filter first if it exists
const newFiltering = (filtering || []).filter(x => { const newFiltering = (filtered || []).filter(x => {
if (x.id !== column.id) { if (x.id !== column.id) {
return true return true
} }
@@ -526,20 +560,22 @@ export default Base => class extends Base {
}) })
} }
onFilteredChange && onFilteredChange(newFiltering, column, value)
// If filters is being controlled, do not manage state internally
if (this.props.filtered) {
this.fireFetchData()
return
}
this.setStateWithData({ this.setStateWithData({
filtering: newFiltering filtered: newFiltering
}, () => { }, () => {
this.fireOnChange() this.fireFetchData()
}) })
} }
resizeColumnStart (column, event, isTouch) { resizeColumnStart (column, event, isTouch) {
const {onResize} = this.props
if (onResize) {
return onResize(column, event, isTouch)
}
const parentWidth = event.target.parentElement.getBoundingClientRect().width const parentWidth = event.target.parentElement.getBoundingClientRect().width
let pageX let pageX
@@ -595,10 +631,11 @@ export default Base => class extends Base {
} }
resizeColumnMoving (event) { resizeColumnMoving (event) {
const {resizing, currentlyResizing} = this.getResolvedState() const {onResizedChange} = this.props
const {resized, currentlyResizing} = this.getResolvedState()
// Delete old value // Delete old value
const newResizing = resizing.filter(x => x.id !== currentlyResizing.id) const newResized = resized.filter(x => x.id !== currentlyResizing.id)
let pageX let pageX
@@ -611,13 +648,19 @@ export default Base => class extends Base {
// Set the min size to 10 to account for margin and border or else the group headers don't line up correctly // 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) const newWidth = Math.max(currentlyResizing.parentWidth + pageX - currentlyResizing.startX, 11)
newResizing.push({ newResized.push({
id: currentlyResizing.id, id: currentlyResizing.id,
value: newWidth value: newWidth
}) })
onResizedChange && onResizedChange(newResized, event)
if (this.props.resized) {
return
}
this.setStateWithData({ this.setStateWithData({
resizing: newResizing resized: newResized
}) })
} }
} }
+8 -11
View File
@@ -64,23 +64,20 @@ function range (n) {
return arr return arr
} }
function orderBy (arr, funcs, dirs) { function orderBy (arr, funcs, dirs, indexKey) {
return arr.sort((a, b) => { return arr.sort((rowA, rowB) => {
for (let i = 0; i < funcs.length; i++) { for (let i = 0; i < funcs.length; i++) {
const comp = funcs[i] const comp = funcs[i]
const ca = comp(a)
const cb = comp(b)
const desc = dirs[i] === false || dirs[i] === 'desc' const desc = dirs[i] === false || dirs[i] === 'desc'
if (ca > cb) { const sortInt = comp(rowA, rowB)
return desc ? -1 : 1 if (sortInt) {
} return desc ? -sortInt : sortInt
if (ca < cb) {
return desc ? 1 : -1
} }
} }
// Use the row index for tie breakers
return dirs[0] return dirs[0]
? a.__index - b.__index ? rowA[indexKey] - rowB[indexKey]
: b.__index - a.__index : rowB[indexKey] - rowA[indexKey]
}) })
} }
+89 -152
View File
@@ -2,170 +2,107 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
const statusChance = Math.random() const data = _.map(_.range(5553), d => {
return { const statusChance = Math.random()
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
progress: Math.floor(Math.random() * 100), lastName: namor.generate({ words: 1, numLen: 0 }),
status: statusChance > 0.66 ? 'relationship' progress: Math.floor(Math.random() * 100),
: statusChance > 0.33 ? 'complicated' status: statusChance > 0.66 ? 'relationship'
: 'single' : statusChance > 0.33 ? 'complicated'
} : 'single'
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName Header: 'Profile Progress',
}] accessor: 'progress',
}, { Cell: row => (
header: 'Info',
columns: [{
header: 'Profile Progress',
accessor: 'progress',
render: row => (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#dadada',
borderRadius: '2px'
}}
>
<div <div
style={{ style={{
width: `${row.value}%`, width: '100%',
height: '100%', height: '100%',
backgroundColor: row.value > 66 ? '#85cc00' backgroundColor: '#dadada',
: row.value > 33 ? '#ffbf00' borderRadius: '2px'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}} }}
>
<div
style={{
width: `${row.value}%`,
height: '100%',
backgroundColor: row.value > 66 ? '#85cc00'
: row.value > 33 ? '#ffbf00'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}}
/>
</div>
)
}, {
Header: 'Status',
accessor: 'status',
Cell: row => (
<span>
<span style={{
color: row.value === 'relationship' ? '#ff2e00'
: row.value === 'complicated' ? '#ffbf00'
: '#57d500',
transition: 'all .3s ease'
}}>
&#x25cf;
</span> {
row.value === 'relationship' ? 'In a relationship'
: row.value === 'complicated' ? `It's complicated`
: 'Single'
}
</span>
)
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/> />
</div> </div>
) <div style={{textAlign: 'center'}}>
}, { <br />
header: 'Status', <em>Tip: Hold shift when sorting to multi-sort!</em>
accessor: 'status', </div>
render: row => (
<span>
<span style={{
color: row.value === 'relationship' ? '#ff2e00'
: row.value === 'complicated' ? '#ffbf00'
: '#57d500',
transition: 'all .3s ease'
}}>
&#x25cf;
</span> {
row.value === 'relationship' ? 'In a relationship'
: row.value === 'complicated' ? `It's complicated`
: 'Single'
}
</span>
)
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
import ReactTable from 'react-table' const source = require('!raw-loader!./CellRenderers')
const columns = [{ export default () => (
header: 'Name', <div>
columns: [{ <Story />
header: 'First Name', <CodeHighlight>{() => source}</CodeHighlight>
accessor: 'firstName' </div>
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Profile Progress',
accessor: 'progress',
render: row => (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#dadada',
borderRadius: '2px'
}}
>
<div
style={{
width: \`$\{row.value}%\`,
height: '100%',
backgroundColor: row.value > 66 ? '#85cc00'
: row.value > 33 ? '#ffbf00'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}}
/>
</div>
)
}, {
header: 'Status',
accessor: 'status',
render: row => (
<span>
<span style={{
color: row.value === 'relationship' ? '#ff2e00'
: row.value === 'complicated' ? '#ffbf00'
: '#57d500',
transition: 'all .3s ease'
}}>
&#x25cf;
</span> {
row.value === 'relationship' ? 'In a relationship'
: row.value === 'complicated' ? \`It's complicated\`
: 'Single'
}
</span>
)
}]
}]
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
) )
`
}
+38 -103
View File
@@ -2,7 +2,6 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
const data = _.map(_.range(5553), d => { const data = _.map(_.range(5553), d => {
@@ -14,48 +13,36 @@ const data = _.map(_.range(5553), d => {
}) })
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, { }, {
header: 'Last Name', Header: 'Last Name',
id: 'lastName', id: 'lastName',
accessor: d => d.lastName accessor: d => d.lastName
}] }]
}, { }, {
header: 'Info', Header: 'Info',
columns: [{ columns: [{
header: 'Age', Header: 'Age',
accessor: 'age' accessor: 'age'
}] }]
}] }]
class ControlledTable extends React.Component { class Story extends React.Component {
constructor() { constructor () {
super() super()
this.sortChange = this.sortChange.bind(this)
this.state = { this.state = {
sorting: [], sorted: [],
page: 0, page: 0,
pageSize: 10 pageSize: 10,
expanded: {},
resized: [],
filtered: []
} }
} }
render () {
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 ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
@@ -63,91 +50,39 @@ class ControlledTable extends React.Component {
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
sorting={this.state.sorting} pivotBy={['lastName']}
onSortingChange={this.sortChange} filterable
// Controlled Props
sorted={this.state.sorted}
page={this.state.page} page={this.state.page}
onPageChange={page => this.setState({page})}
pageSize={this.state.pageSize} pageSize={this.state.pageSize}
expanded={this.state.expanded}
resized={this.state.resized}
filtered={this.state.filtered}
// Callbacks
onSortedChange={sorted => this.setState({sorted})}
onPageChange={page => this.setState({page})}
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})} onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
onExpandedChange={expanded => this.setState({expanded})}
onResizedChange={resized => this.setState({resized})}
onFilteredChange={filtered => this.setState({filtered})}
/> />
</div> </div>
<div style={{textAlign: 'center'}}> <br />
<br /> <pre><code><strong>this.state ===</strong> {JSON.stringify(this.state, null, 2)}</code></pre>
<em>Tip: For simplicity, multi-sort is not implemented in this demo</em> <br />
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div> </div>
) )
} }
} }
function getCode () { // Source Code
return `const data = _.map(_.range(5553), d => { const CodeHighlight = require('./components/codeHighlight').default
return { const source = require('!raw-loader!./ControlledTable')
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{ export default () => (
header: 'Name', <div>
columns: [{ <Story />
header: 'First Name', <CodeHighlight>{() => source}</CodeHighlight>
accessor: 'firstName' </div>
}, { )
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 />
+66 -97
View File
@@ -2,105 +2,74 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<strong>Hey!</strong> Open your console! :)
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
getTdProps={(state, rowInfo, column, instance) => {
return {
onMouseEnter: e => console.log('Cell - onMouseEnter', {
state,
rowInfo,
column,
instance,
event: e
})
}
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
}
function getCode () {
return `
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
getTdProps={(state, rowInfo, column, instance) => {
return { return {
onMouseEnter: e => console.log('Cell - onMouseEnter', { firstName: namor.generate({ words: 1, numLen: 0 }),
state, lastName: namor.generate({ words: 1, numLen: 0 }),
rowInfo, age: Math.floor(Math.random() * 30)
column,
instance,
event: e
})
} }
}} })
/>
) const columns = [{
` Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<strong>Hey!</strong> Open your console! :)
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
getTdProps={(state, rowInfo, column, instance) => {
return {
onMouseEnter: e => console.log('Cell - onMouseEnter', {
state,
rowInfo,
column,
instance,
event: e
})
}
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
} }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./CustomComponentProps')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+67 -107
View File
@@ -2,119 +2,79 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({words: 1, numLen: 0}), return {
lastName: namor.generate({words: 1, numLen: 0}), firstName: namor.generate({words: 1, numLen: 0}),
age: Math.floor(Math.random() * 30) lastName: namor.generate({words: 1, numLen: 0}),
} age: Math.floor(Math.random() * 30)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
footer: () => <div style={{textAlign: 'center'}}>First Name</div> Footer: () => <div style={{textAlign: 'center'}}>First Name</div>
}, {
Header: 'Last Name',
accessor: 'lastName',
Footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
}]
}, { }, {
header: 'Last Name', Header: 'Info',
accessor: 'lastName', columns: [{
footer: () => <div style={{textAlign: 'center'}}>Last Name</div> Header: 'Age',
accessor: 'age',
Footer: () => <div style={{textAlign: 'center'}}>Age</div>
}]
}, {
Header: 'Expand',
columns: [{
expander: true,
Header: () => (<strong>More</strong>),
width: 65,
Expander: ({isExpanded, ...rest}) => (
<div>
{isExpanded ? <span>&#x2299;</span> : <span>&#x2295;</span>}
</div>
),
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
Footer: () => <span>&hearts;</span>
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
footer: () => <div style={{textAlign: 'center'}}>Age</div>
}]
}, {
header: 'Expand',
columns: [{
expander: true,
header: () => (<strong>More</strong>),
width: 65,
render: ({isExpanded, ...rest}) => (
<div>
{isExpanded ? <span>&#x2299;</span> : <span>&#x2295;</span>}
</div>
),
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
footer: () => <span>&hearts;</span>
}]
}]
return ( return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
SubComponent={() => <span>Hello</span>}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
}
function getCode () {
return `
import ReactTable from 'react-table'
// Create some column definitions
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName',
footer: () => <div style={{textAlign: 'center'}}>First Name</div>
}, {
header: 'Last Name',
accessor: 'lastName',
footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
footer: () => <div style={{textAlign: 'center'}}>Age</div>
}]
}, {
header: 'Expand',
columns: [{
expander: true,
header: () => (<strong>More</strong>),
width: 65,
render: ({isExpanded, ...rest}) => (
<div> <div>
{isExpanded ? <span>&#x2299;</span> : <span>&#x2295;</span>} <div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
SubComponent={() => <span>Hello</span>}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
), )
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'}, }
footer: () => <span>&hearts;</span>
}]
}]
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
SubComponent={() => <span>Hello</span>}
/>
)
`
} }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./CustomExpanderPosition')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+77
View File
@@ -0,0 +1,77 @@
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../src/index'
class Story extends React.Component {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name (Sorted by Length, A-Z)',
accessor: 'firstName',
sortMethod: (a, b) => {
if (a.length === b.length) {
return a > b ? 1 : -1
}
return a.length > b.length ? 1 : -1
}
}, {
Header: 'Last Name (Sorted in reverse, A-Z)',
id: 'lastName',
accessor: d => d.lastName,
sortMethod: (a, b) => {
if (a === b) {
return 0
}
const aReverse = a.split('').reverse().join('')
const bReverse = b.split('').reverse().join('')
return aReverse > bReverse ? 1 : -1
}
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./CustomSorting')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+51 -76
View File
@@ -2,90 +2,65 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30) lastName: namor.generate({ words: 1, numLen: 0 }),
} age: Math.floor(Math.random() * 30)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
maxWidth: 200 maxWidth: 200
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
width: 300
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName, Header: 'Age',
width: 300 accessor: 'age',
minWidth: 400
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
minWidth: 400
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
import ReactTable from 'react-table' const source = require('!raw-loader!./CustomWidths')
const columns = [{ export default () => (
header: 'Name', <div>
columns: [{ <Story />
header: 'First Name', <CodeHighlight>{() => source}</CodeHighlight>
accessor: 'firstName', </div>
maxWidth: 200
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
width: 300
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
minWidth: 400
}]
}]
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
) )
`
}
+53 -77
View File
@@ -2,90 +2,66 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30) lastName: namor.generate({ words: 1, numLen: 0 }),
} age: Math.floor(Math.random() * 30)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName Header: 'Age',
accessor: 'age'
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
defaultSorting={[{ defaultSorted={[{
id: 'age', id: 'age',
desc: true desc: true
}]} }]}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
const columns = [{ const source = require('!raw-loader!./DefaultSorting')
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return ( export default () => (
<ReactTable <div>
className='-striped -highlight' <Story />
data={data} <CodeHighlight>{() => source}</CodeHighlight>
columns={columns} </div>
defaultPageSize={10} )
defaultSorting={[{
id: 'age',
desc: true
}]}
/>
)
`
}
+39 -94
View File
@@ -1,124 +1,69 @@
import React from 'react' import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
class MyTable extends React.Component { class Story extends React.Component {
constructor(props, context) { constructor (props, context) {
super(props, context); super(props, context)
this.renderEditable = this.renderEditable.bind(this); this.renderEditable = this.renderEditable.bind(this)
this.state = { this.state = {
data: [ data: [
{ firstName: 'Lucy', lastName: 'Marks' }, { firstName: 'Lucy', lastName: 'Marks' },
{ firstName: 'Bejamin', lastName: 'Pike' } { firstName: 'Bejamin', lastName: 'Pike' }
] ]
}; }
this.columns = [ this.columns = [
{ {
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
render: this.renderEditable Cell: this.renderEditable
}, },
{ {
header: 'Last Name', Header: 'Last Name',
accessor: 'lastName', accessor: 'lastName',
render: this.renderEditable Cell: this.renderEditable
}, },
{ {
header: 'Full Name', Header: 'Full Name',
id: 'full', id: 'full',
accessor: d => d.firstName + ' ' + d.lastName accessor: d => d.firstName + ' ' + d.lastName
} }
]; ]
} }
renderEditable(cellInfo) { renderEditable (cellInfo) {
return (<div style={{ backgroundColor: '#fafafa' }} contentEditable suppressContentEditableWarning onBlur={(e) => { return (<div style={{ backgroundColor: '#fafafa' }} contentEditable suppressContentEditableWarning onBlur={(e) => {
const data = [...this.state.data]; const data = [...this.state.data]
data[cellInfo.index][cellInfo.column.id] = e.target.textContent; data[cellInfo.index][cellInfo.column.id] = e.target.textContent
this.setState({data: data}); this.setState({data: data})
}}>{this.state.data[cellInfo.index][cellInfo.column.id]}</div>); }}>{this.state.data[cellInfo.index][cellInfo.column.id]}</div>)
} }
render() { render () {
return (<ReactTable return (
data={this.state.data}
columns={this.columns}
defaultPageSize={2}
showPageSizeOptions={false}
showPagination={false}
/>);
}
}
function getCode() {
return `
class MyTable extends React.Component {
constructor(props, context) {
super(props, context);
this.renderEditable = this.renderEditable.bind(this);
this.state = {
data: [
{ firstName: 'Lucy', lastName: 'Marks' },
{ firstName: 'Bejamin', lastName: 'Pike' }
]
};
this.columns = [
{
header: 'First Name',
accessor: 'firstName',
render: this.renderEditable
},
{
header: 'Last Name',
accessor: 'lastName',
render: this.renderEditable
},
{
header: 'Full Name',
id: 'full',
accessor: d => d.firstName + ' ' + d.lastName
}
];
}
renderEditable(cellInfo) {
return (<div style={{ backgroundColor: '#fafafa' }} contentEditable suppressContentEditableWarning onBlur={(e) => {
const data = [...this.state.data];
data[cellInfo.index][cellInfo.column.id] = e.target.textContent;
this.setState({data: data});
}}>{this.state.data[cellInfo.index][cellInfo.column.id]}</div>);
}
render() {
return (<ReactTable
data={this.state.data}
columns={this.columns}
defaultPageSize={2}
showPageSizeOptions={false}
showPagination={false}
/>);
}
}
`
}
export default () => {
return (
<div>
<p>First two columns are editable just by clicking into them using the <code>contentEditable</code> attribute. Last column (Full Name) is computed from the first two.</p>
<div className='table-wrap' style={{marginBottom: '20px'}}> <div className='table-wrap' style={{marginBottom: '20px'}}>
<MyTable /> <p>First two columns are editable just by clicking into them using the <code>contentEditable</code> attribute. Last column (Full Name) is computed from the first two.</p>
<ReactTable
data={this.state.data}
columns={this.columns}
defaultPageSize={2}
showPageSizeOptions={false}
showPagination={false}
/>
</div> </div>
)
}
}
<CodeHighlight>{() => getCode()}</CodeHighlight> // Source Code
</div> const CodeHighlight = require('./components/codeHighlight').default
) const source = require('!raw-loader!./EditableTable')
}
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+51 -122
View File
@@ -3,10 +3,10 @@ import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight' import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
class Filtering extends React.Component { class Story extends React.Component {
constructor (props) { constructor (props) {
super(props) super(props)
@@ -28,7 +28,9 @@ class Filtering extends React.Component {
collapseOnPageChange: true, collapseOnPageChange: true,
collapseOnDataChange: true, collapseOnDataChange: true,
freezeWhenExpanded: false, freezeWhenExpanded: false,
showFilters: true filterable: true,
sortable: true,
resizable: true
}, },
data: data data: data
} }
@@ -38,27 +40,27 @@ class Filtering extends React.Component {
render () { render () {
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
filterMethod: (filter, row) => (row[filter.id].startsWith(filter.value) && row[filter.id].endsWith(filter.value)) filterMethod: (filter, row) => (row[filter.id].startsWith(filter.value) && row[filter.id].endsWith(filter.value))
}, { }, {
header: 'Last Name', Header: 'Last Name',
id: 'lastName', id: 'lastName',
accessor: d => d.lastName, accessor: d => d.lastName,
filterMethod: (filter, row) => (row[filter.id].includes(filter.value)) filterMethod: (filter, row) => (row[filter.id].includes(filter.value))
}] }]
}, { }, {
header: 'Info', Header: 'Info',
columns: [{ columns: [{
header: 'Age', Header: 'Age',
accessor: 'age' accessor: 'age'
}, { }, {
header: 'Over 21', Header: 'Over 21',
accessor: 'age', accessor: 'age',
id: 'over', id: 'over',
render: ({value}) => (value >= 21 ? 'Yes' : 'No'), Cell: ({value}) => (value >= 21 ? 'Yes' : 'No'),
filterMethod: (filter, row) => { filterMethod: (filter, row) => {
if (filter.value === 'all') { if (filter.value === 'all') {
return true return true
@@ -68,14 +70,15 @@ class Filtering extends React.Component {
} }
return row[filter.id] < 21 return row[filter.id] < 21
}, },
filterRender: ({filter, onFilterChange}) => ( Filter: ({filter, onChange}) => (
<select <select
onChange={event => onFilterChange(event.target.value)} onChange={event => onChange(event.target.value)}
style={{width: '100%'}} style={{width: '100%'}}
value={filter ? filter.value : 'all'}> value={filter ? filter.value : 'all'}
<option value="all"></option> >
<option value="true">Can Drink</option> <option value='all' />
<option value="false">Can't Drink</option> <option value='true'>Can Drink</option>
<option value='false'>Can't Drink</option>
</select> </select>
) )
} }
@@ -88,23 +91,23 @@ class Filtering extends React.Component {
<h1>Table Options</h1> <h1>Table Options</h1>
<table> <table>
<tbody> <tbody>
{ {
Object.keys(this.state.tableOptions).map(optionKey => { Object.keys(this.state.tableOptions).map(optionKey => {
const optionValue = this.state.tableOptions[optionKey] const optionValue = this.state.tableOptions[optionKey]
return ( return (
<tr key={optionKey}> <tr key={optionKey}>
<td>{optionKey}</td> <td>{optionKey}</td>
<td style={{paddingLeft: 10, paddingTop: 5}}> <td style={{paddingLeft: 10, paddingTop: 5}}>
<input type="checkbox" <input type='checkbox'
name={optionKey} name={optionKey}
checked={optionValue} checked={optionValue}
onChange={this.setTableOption} onChange={this.setTableOption}
/> />
</td> </td>
</tr> </tr>
) )
}) })
} }
</tbody> </tbody>
</table> </table>
</div> </div>
@@ -148,21 +151,20 @@ class Filtering extends React.Component {
<div> <div>
<h1>Custom Filters In This Example</h1> <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 <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> on values that start with the filter text. Example: age.startsWith("2").</p>
<p>This example overrides the default filter behavior by setting <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 the <strong>defaultFilterMethod</strong> table option to match on values that are exactly equal to the
filter text. Example: age == "23")</p> filter text. Example: age == "23")</p>
<p>Each column can also be customized with the column <strong>filterMethod</strong> option:</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 <p>In this example the firstName column filters on the value starting with and ending with the filter
value.</p> value.</p>
<p>In this example the lastName column filters on the value including the filter value anywhere in its <p>In this example the lastName column filters on the value including the filter value anywhere in its
text.</p> text.</p>
<p>To completely override the filter that is shown, you can set the <strong>filterRender</strong> column <p>To completely override the filter that is shown, you can set the <strong>Filter</strong> column
option. Using this option you can specify the JSX that is shown. The option is passed 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 an <strong>onChange</strong> method that must be called with the value that you wan't to
pass to the <strong>filterMethod</strong> option whenever the filter has changed.</p> pass to the <strong>filterMethod</strong> option whenever the filter has changed.</p>
</div> </div>
<CodeHighlight>{() => this.getCode()}</CodeHighlight>
</div> </div>
) )
} }
@@ -178,87 +180,14 @@ class Filtering extends React.Component {
} }
}) })
} }
getCode () {
return `
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName',
filterMethod: (filter, row) => (row[filter.id].startsWith(filter.value) && row[filter.id].endsWith(filter.value))
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
filterMethod: (filter, row) => (row[filter.id].includes(filter.value))
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}, {
header: 'Over 21',
accessor: 'age',
id: 'over',
render: ({value}) => (value >= 21 ? 'Yes' : 'No'),
filterMethod: (filter, row) => {
if (filter.value === 'all') {
return true
}
if (filter.value === 'true') {
return row[filter.id] >= 21
}
return row[filter.id] < 21
},
filterRender: ({filter, onFilterChange}) => (
<select
onChange={event => onFilterChange(event.target.value)}
style={{width: '100%'}}
value={filter ? filter.value : 'all'}>
<option value="all"></option>
<option value="true">Can Drink</option>
<option value="false">Can't Drink</option>
</select>
)
}]
}]
export default (
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
defaultFilterMethod={(filter, row) => (String(row[filter.id]) === filter.value)}
{...otherOptions}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
)
`
}
} }
export default () => <Filtering /> // Source Code
const source = require('!raw-loader!./Filtering')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+71 -123
View File
@@ -2,142 +2,90 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30) lastName: namor.generate({ words: 1, numLen: 0 }),
} age: Math.floor(Math.random() * 30)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
footer: ( Footer: (
<span><strong>Popular:</strong> { <span><strong>Popular:</strong> {
_.first( _.first(
_.reduce(
_.map(
_.groupBy(
data, d => d.firstName
)
),
(a, b) => a.length > b.length ? a : b
)
).firstName}
</span>
)
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
Footer: (
<span><strong>Longest:</strong> {
_.reduce( _.reduce(
_.map( _.map(
_.groupBy( _.groupBy(
data, d => d.firstName data, d => d.lastName
) ),
(d, key) => key
), ),
(a, b) => a.length > b.length ? a : b (a, b) => a.length > b.length ? a : b
) )}
).firstName} </span>
</span> )
) }]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName, Header: 'Age',
footer: ( accessor: 'age',
<span><strong>Longest:</strong> { Footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
_.reduce( }]
_.map(
_.groupBy(
data, d => d.lastName
),
(d, key) => key
),
(a, b) => a.length > b.length ? a : b
)}
</span>
)
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
import ReactTable from 'react-table' const source = require('!raw-loader!./Footers')
// Create some column definitions export default () => (
const columns = [{ <div>
header: 'Name', <Story />
columns: [{ <CodeHighlight>{() => source}</CodeHighlight>
header: 'First Name', </div>
accessor: 'firstName',
footer: (
<span><strong>Popular:</strong> {
_.first(
_.reduce(
_.map(
_.groupBy(
data, d => d.firstName
)
),
(a, b) => a.length > b.length ? a : b
)
).firstName}
</span>
)
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
footer: (
<span><strong>Longest:</strong> {
_.reduce(
_.map(
_.groupBy(
data, d => d.lastName
),
(d, key) => key
),
(a, b) => a.length > b.length ? a : b
)}
</span>
)
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
}]
}]
// Display your table!
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
) )
`
}
+95 -132
View File
@@ -3,7 +3,6 @@ import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import JSONTree from 'react-json-tree' import JSONTree from 'react-json-tree'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
const JSONtheme = { const JSONtheme = {
@@ -27,147 +26,111 @@ const JSONtheme = {
base0F: '#cc6633' base0F: '#cc6633'
} }
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30) lastName: namor.generate({ words: 1, numLen: 0 }),
} age: Math.floor(Math.random() * 30)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName', accessor: 'firstName',
footer: 'Footer' Footer: 'Footer'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
Footer: 'Footer'
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName, Header: 'Age',
footer: 'Footer' accessor: 'age',
Footer: 'Footer'
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
footer: 'Footer'
}]
}]
return ( return (
<div> <div>
<strong>Functional rendering</strong> simply means that you have all of the building blocks to render your own React Table however you'd like. <strong>Functional rendering</strong> simply means that you have all of the building blocks to render your own React Table however you'd like.
<br /> <br />
<br /> <br />
<br /> <br />
<br /> <br />
<strong>Decorating the standard table output</strong> <strong>Decorating the standard table output</strong>
<br /> <br />
<br /> <br />
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
data={data} data={data}
columns={columns} columns={columns}
> >
{(state, makeTable, instance) => { {(state, makeTable, instance) => {
return ( return (
<div style={{ <div style={{
background: '#ffcf00', background: '#ffcf00',
borderRadius: '5px', borderRadius: '5px',
overflow: 'hidden', overflow: 'hidden',
padding: '5px' padding: '5px'
}}> }}>
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre> <pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
{makeTable()} {makeTable()}
</div> </div>
) )
}} }}
</ReactTable> </ReactTable>
</div>
<CodeHighlight>{() => `
import ReactTable from 'react-table'
return (
<ReactTable
data={data}
columns={columns}
>
{(state, Table, instance) => {
return (
<div style={{
background: '#ffcf00',
borderRadius: '5px',
overflow: 'hidden',
padding: '5px'
}}>
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
<Table />
</div> </div>
)
}}
</ReactTable>
)
`}</CodeHighlight>
<br /> <br />
<br /> <br />
<strong>Need more control? This is the entire table state and component instance at your disposal!</strong> <strong>Need more control? This is the entire table state and component instance at your disposal!</strong>
<br /> <br />
<br /> <br />
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
> >
{(state, StandardTable, instance) => { {(state, StandardTable, instance) => {
return ( return (
<div> <div>
<JSONTree <JSONTree
data={Object.assign({}, state, {children: 'function () {...}'})} data={Object.assign({}, state, {children: 'function () {...}'})}
theme={JSONtheme} theme={JSONtheme}
invertTheme invertTheme
/> />
</div> </div>
) )
}} }}
</ReactTable> </ReactTable>
</div>
<br />
<CodeHighlight>{() => `
import ReactTable from 'react-table'
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
>
{(state, StandardTable, instance) => {
return (
<div>
<JSONTree
data={Object.assign({}, state, {children: 'function () {...}'})}
theme={JSONtheme}
invertTheme
/>
</div> </div>
) <br />
}} </div>
</ReactTable> )
) }
`}</CodeHighlight>
</div>
)
} }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./FunctionalRendering')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+44 -80
View File
@@ -1,92 +1,56 @@
import React from 'react' import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const columns = [{
firstName: namor.generate({ words: 1, numLen: 0 }), Header: 'Name',
lastName: namor.generate({ words: 1, numLen: 0 }), columns: [{
age: Math.floor(Math.random() * 30) Header: 'First Name',
} accessor: 'firstName'
}) }, {
Header: 'Last Name',
const columns = [{ id: 'lastName',
header: 'Name', accessor: d => d.lastName
columns: [{ }]
header: 'First Name',
accessor: 'firstName'
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName Header: 'Age',
accessor: 'age'
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={[]} data={[]}
noDataText='Oh Noes!' noDataText='Oh Noes!'
// noDataText={() => 'Oh Noes!'} // Supports functions // noDataText={() => 'Oh Noes!'} // Supports functions
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components // noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
import ReactTable from 'react-table' const source = require('!raw-loader!./NoDataText')
// Create some column definitions export default () => (
const columns = [{ <div>
header: 'Name', <Story />
columns: [{ <CodeHighlight>{() => source}</CodeHighlight>
header: 'First Name', </div>
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
// Display your table!
return (
<ReactTable
data={[]}
noDataText='Oh Noes!'
// noDataText={() => 'Oh Noes!'} // Supports functions
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
columns={columns}
defaultPageSize={10}
/>
) )
`
}
+74 -126
View File
@@ -2,147 +2,95 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(100000), d => { render () {
return { const data = _.map(_.range(100000), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30), lastName: namor.generate({ words: 1, numLen: 0 }),
visits: Math.floor(Math.random() * 100) age: Math.floor(Math.random() * 30),
} visits: Math.floor(Math.random() * 100)
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
} }
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Visits', Header: 'Info',
accessor: 'visits', columns: [{
aggregate: vals => _.sum(vals) Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
}
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}] }]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
className='-striped -highlight'
defaultPageSize={10}
pivotBy={['firstName', 'lastName']}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
}
function getCode () {
return `
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
}
}, {
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}]
return (
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable <ReactTable
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={3} className='-striped -highlight'
showPagination={false} defaultPageSize={10}
pivotBy={['firstName', 'lastName']}
SubComponent={(row) => { SubComponent={(row) => {
return ( return (
<div style={{padding: '20px'}}> <div style={{padding: '20px'}}>
<em>It even has access to the row data: </em> <em>You can put any component you want here, even another React Table!</em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight> <br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div> </div>
) )
}} }}
/> />
</div> </div>
) <div style={{textAlign: 'center'}}>
}} <br />
/> <em>Tip: Hold shift when sorting to multi-sort!</em>
) </div>
` </div>
)
}
} }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./OneHundredKRows')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+58 -87
View File
@@ -2,101 +2,72 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(10000), d => { render () {
return { const data = _.map(_.range(1000), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30), lastName: namor.generate({ words: 1, numLen: 0 }),
visits: Math.floor(Math.random() * 100) age: Math.floor(Math.random() * 30),
} visits: Math.floor(Math.random() * 100)
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
} }
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Visits', Header: 'Info',
accessor: 'visits', columns: [{
aggregate: vals => _.sum(vals) Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
}
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}] }]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
data={data} data={data}
columns={columns} columns={columns}
className='-striped -highlight' className='-striped -highlight'
defaultPageSize={10} defaultPageSize={10}
pivotBy={['firstName', 'lastName']} pivotBy={['firstName', 'lastName']}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
const columns = [{ const source = require('!raw-loader!./Pivoting')
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
}
}, {
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}]
return ( export default () => (
<ReactTable <div>
data={data} <Story />
columns={columns} <CodeHighlight>{() => source}</CodeHighlight>
className='-striped -highlight' </div>
defaultPageSize={10}
pivotBy={['firstName', 'lastName']}
/>
) )
`
}
+119 -181
View File
@@ -2,192 +2,130 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(1000), d => { render () {
return { const data = _.map(_.range(1000), d => {
firstName: namor.generate({words: 1, numLen: 0}), return {
lastName: namor.generate({words: 1, numLen: 0}), firstName: namor.generate({words: 1, numLen: 0}),
age: Math.floor(Math.random() * 30), lastName: namor.generate({words: 1, numLen: 0}),
visits: Math.floor(Math.random() * 100) age: Math.floor(Math.random() * 30),
} visits: Math.floor(Math.random() * 100)
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => {
return _.round(_.mean(vals))
},
render: row => {
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
} }
}, { })
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
hideFilter: true
}]
}, {
header: () => <strong>Overriden Pivot Column Header Group</strong>,
expander: true,
minWidth: 200,
pivotRender: ({value}) => <span style={{color: 'darkred'}}>{value}</span>,
footer: () => <div style={{textAlign: 'center'}}><strong>Overriden Pivot Column Footer</strong></div>
}]
return ( const columns = [{
<div> Header: 'Name',
<div className='table-wrap'> columns: [{
<ReactTable Header: 'First Name',
data={data} accessor: 'firstName',
columns={columns} PivotValue: ({value}) => <span style={{color: 'darkred'}}>{value}</span>
defaultPageSize={10} }, {
className='-striped -highlight' Header: 'Last Name',
pivotBy={['firstName', 'lastName']} id: 'lastName',
defaultSorting={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]} accessor: d => d.lastName,
collapseOnSortingChange={false} PivotValue: ({value}) => <span style={{color: 'darkblue'}}>{value}</span>,
showFilters={true} Footer: () => <div style={{textAlign: 'center'}}><strong>Pivot Column Footer</strong></div>
ExpanderComponent={({isExpanded, ...rest}) => ( }]
isExpanded ? <span> &#10136; </span> : <span> &#10137; </span> }, {
)} Header: 'Info',
PivotValueComponent={ ({subRows, value}) => ( columns: [{
<span><span style={{color: 'darkred'}}>{value}</span> {subRows && `(${subRows.length} Last Names)`}</span> Header: 'Age',
)} accessor: 'age',
SubComponent={(row) => { aggregate: vals => {
return ( return _.round(_.mean(vals))
<div style={{padding: '20px'}}> },
<em>You can put any component you want here, even another React Table!</em> Aggregated: row => <span>{row.value} (avg)</span>
<br /> }, {
<br /> Header: 'Visits',
<ReactTable accessor: 'visits',
data={data} aggregate: vals => _.sum(vals),
columns={columns.filter(x => !x.expander)} filterable: false
defaultPageSize={3} }]
showPagination={false} }, {
SubComponent={(row) => { pivot: true,
return ( Header: () => <strong>Overridden Pivot Column Header Group</strong>
<div style={{padding: '20px'}}> }, {
<em>It even has access to the row data: </em> expander: true
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight> }]
</div>
) const subtableColumns = [{
}} Header: 'Name',
/> columns: [{
</div> Header: 'First Name',
) accessor: 'firstName'
}} }, {
/> Header: 'Last Name',
id: 'lastName'
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}, {
Header: 'Visits',
accessor: 'visits'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
defaultSorted={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]}
collapseOnSortingChange={false}
filterable
ExpanderComponent={({isExpanded, ...rest}) => (
isExpanded ? <span> &#10136; </span> : <span> &#10137; </span>
)}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={subtableColumns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { // Source Code
return ` const CodeHighlight = require('./components/codeHighlight').default
const columns = [{ const source = require('!raw-loader!./PivotingOptions')
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => {
return _.round(_.mean(vals))
},
render: row => {
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
}
}, {
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
hideFilter: true
}]
}, {
header: () => <strong>Overriden Pivot Column Header Group</strong>,
expander: true,
minWidth: 200,
pivotRender: ({value}) => <span style={{color: 'darkred'}}>{value}</span>,
footer: () => <div style={{textAlign: 'center'}}><strong>Overriden Pivot Column Footer</strong></div>
}]
return ( export default () => (
<div> <div>
<div className='table-wrap'> <Story />
<ReactTable <CodeHighlight>{() => source}</CodeHighlight>
data={data} </div>
columns={columns} )
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
defaultSorting={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]}
collapseOnSortingChange={false}
showFilters={true}
ExpanderComponent={({isExpanded, ...rest}) => (
isExpanded ? <span> &#10136; </span> : <span> &#10137; </span>
)}
PivotValueComponent={ ({subRows, value}) => (
<span><span style={{color: 'darkred'}}>{value}</span> {subRows && \`(\${subRows.length} Last Names)\`}</span>
)}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns.filter(x => !x.expander)}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
`
}
+77 -132
View File
@@ -2,153 +2,98 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(1000), d => { render () {
return { const data = _.map(_.range(1000), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30), lastName: namor.generate({ words: 1, numLen: 0 }),
visits: Math.floor(Math.random() * 100) age: Math.floor(Math.random() * 30),
} visits: Math.floor(Math.random() * 100)
}) }
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
},
filterMethod: (filter, row) => (filter.value === `${row[filter.id]} (avg)`)
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
filterable: false
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? `${row.value} (avg)` : row.value}</span>
},
filterMethod: (filter, row) => (filter.value == `${row[filter.id]} (avg)`)
}, {
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
hideFilter: true
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
showFilters={true}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
}
function getCode () {
return `
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
render: row => {
return <span>{row.aggregated ? \`\${row.value} (avg)\` : row.value}</span>
},
filterMethod: (filter, row) => (filter.value == \`\${row[filter.id]} (avg)\`)
}, {
header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
hideFilter: true
}]
}]
return (
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
showFilters={true}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable <ReactTable
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={3} defaultPageSize={10}
showPagination={false} className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
filterable
SubComponent={(row) => { SubComponent={(row) => {
return ( return (
<div style={{padding: '20px'}}> <div style={{padding: '20px'}}>
<em>It even has access to the row data: </em> <em>You can put any component you want here, even another React Table!</em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight> <br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div> </div>
) )
}} }}
/> />
</div> </div>
) <div style={{textAlign: 'center'}}>
}} <br />
/> <em>Tip: Hold shift when sorting to multi-sort!</em>
) </div>
` </div>
)
}
} }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./PivotingSubComponents')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+29 -85
View File
@@ -2,7 +2,6 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
const rawData = _.map(_.range(3424), d => { const rawData = _.map(_.range(3424), d => {
@@ -14,29 +13,29 @@ const rawData = _.map(_.range(3424), d => {
}) })
// Now let's mock the server. It's job is simple: use the table model to sort and return the page data // Now let's mock the server. It's job is simple: use the table model to sort and return the page data
const requestData = (pageSize, page, sorting, filtering) => { const requestData = (pageSize, page, sorted, filtered) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// On the server, you'll likely use SQL or noSQL or some other query language to do this. // On the server, you'll likely use SQL or noSQL or some other query language to do this.
// For this mock, we'll just use lodash // For this mock, we'll just use lodash
let filteredData = rawData; let filteredData = rawData
if (filtering.length) { if (filtered.length) {
filteredData = filtering.reduce( filteredData = filtered.reduce(
(filteredSoFar, nextFilter) => { (filteredSoFar, nextFilter) => {
return filteredSoFar.filter( return filteredSoFar.filter(
(row) => { (row) => {
return (row[nextFilter.id]+"").includes(nextFilter.value) return (row[nextFilter.id] + '').includes(nextFilter.value)
}) })
} }
, filteredData) , filteredData)
} }
const sortedData = _.orderBy(filteredData, sorting.map(sort => { const sortedData = _.orderBy(filteredData, sorted.map(sort => {
return row => { return row => {
if (row[sort.id] === null || row[sort.id] === undefined) { if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity return -Infinity
} }
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id] return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id]
} }
}), sorting.map(d => d.desc ? 'desc' : 'asc')) }), sorted.map(d => d.desc ? 'desc' : 'asc'))
// Be sure to send back the rows to be displayed and any other pertinent information, like how many pages there are total. // Be sure to send back the rows to be displayed and any other pertinent information, like how many pages there are total.
const res = { const res = {
@@ -49,23 +48,23 @@ const requestData = (pageSize, page, sorting, filtering) => {
}) })
} }
const ServerSide = React.createClass({ class Story extends React.Component {
getInitialState () { constructor () {
// To handle our data server-side, we need a few things in the state to help us out: super()
return { this.state = {
data: [], data: [],
pages: null, pages: null,
loading: true loading: true
} }
}, this.fetchData = this.fetchData.bind(this)
}
fetchData (state, instance) { fetchData (state, instance) {
// Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model. // Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model.
// You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want. // You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want.
this.setState({loading: true}) this.setState({loading: true})
// Request the data however you want. Here, we'll use our mocked service we created earlier // Request the data however you want. Here, we'll use our mocked service we created earlier
requestData(state.pageSize, state.page, state.sorting, state.filtering) requestData(state.pageSize, state.page, state.sorted, state.filtered)
.then((res) => { .then((res) => {
console.log(res.rows)
// Now just get the rows of data to your React Table (and update anything else like total pages or loading) // Now just get the rows of data to your React Table (and update anything else like total pages or loading)
this.setState({ this.setState({
data: res.rows, data: res.rows,
@@ -73,7 +72,7 @@ const ServerSide = React.createClass({
loading: false loading: false
}) })
}) })
}, }
render () { render () {
return ( return (
<div> <div>
@@ -81,96 +80,41 @@ const ServerSide = React.createClass({
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
columns={[{ columns={[{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, { }, {
header: 'Last Name', Header: 'Last Name',
id: 'lastName', id: 'lastName',
accessor: d => d.lastName accessor: d => d.lastName
}, { }, {
header: 'Age', Header: 'Age',
accessor: 'age' accessor: 'age'
}]} }]}
manual // Forces table not to paginate or sort automatically, so we can handle it server-side manual // Forces table not to paginate or sort automatically, so we can handle it server-side
defaultPageSize={10} defaultPageSize={10}
showFilters={true} filterable
data={this.state.data} // Set the rows to be displayed data={this.state.data} // Set the rows to be displayed
pages={this.state.pages} // Display the total number of pages pages={this.state.pages} // Display the total number of pages
loading={this.state.loading} // Display the loading overlay when we need it loading={this.state.loading} // Display the loading overlay when we need it
onChange={this.fetchData} // Request new data when things change onFetchData={this.fetchData} // Request new data when things change
/> />
</div> </div>
<div style={{textAlign: 'center'}}> <div style={{textAlign: 'center'}}>
<br /> <br />
<em>Tip: Hold shift when sorting to multi-sort!</em> <em>Tip: Hold shift when sorting to multi-sort!</em>
</div> </div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div> </div>
) )
} }
}) }
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./ServerSide')
export default () => ( export default () => (
<ServerSide /> <div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
) )
function getCode () {
return `
import ReactTable from 'react-table'
import Axios from 'axios'
export default React.createClass({
getInitialState () {
// To handle our data server-side, we need to keep track of our table state
return {
data: [],
pages: null,
loading: true
}
},
fetchData (state, instance) {
// Whenever the table model changes (sorting, pagination, etc), this method gets called and passed the current table model.
// You can set the 'loading' prop of the table to true to use the built-in loading notice, or show you're own loading bar if you want.
this.setState({loading: true})
// Request the data from a server however you want! Be sure to send the bits of the table model that it may neeed.
Axios.post('mysite.com/data', {
pageSize: state.pageSize,
page: state.page,
sorting: state.sorting,
filtering: state.filtering
})
.then((res) => {
// Now update your state!
this.setState({
data: res.rows,
pages: res.pages,
loading: false
})
})
},
render () {
return (
<ReactTable
columns={[{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}, {
header: 'Age',
accessor: 'age'
}]}
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
defaultPageSize={10}
showFilters={true}
data={this.state.data} // Set the rows to be displayed
pages={this.state.pages} // Display the total number of pages
loading={this.state.loading} // Display the loading overlay when we need it
onChange={this.fetchData} // Request new data when things change
/>
}
})
`
}
+54 -72
View File
@@ -2,86 +2,68 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
export default () => { class Story extends React.Component {
const data = _.map(_.range(5553), d => { render () {
return { const data = _.map(_.range(5553), d => {
firstName: namor.generate({ words: 1, numLen: 0 }), return {
lastName: namor.generate({ words: 1, numLen: 0 }), firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30) lastName: namor.generate({ words: 1, numLen: 0 }),
} age: Math.floor(Math.random() * 30),
}) children: _.map(_.range(10), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
}
})
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, { }, {
header: 'Last Name', Header: 'Info',
id: 'lastName', columns: [{
accessor: d => d.lastName Header: 'Age',
accessor: 'age'
}]
}] }]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return ( return (
<div> <div>
<div className='table-wrap'> <div className='table-wrap'>
<ReactTable <ReactTable
className='-striped -highlight' className='-striped -highlight'
data={data} data={data}
columns={columns} columns={columns}
defaultPageSize={10} defaultPageSize={10}
/> />
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div> </div>
<div style={{textAlign: 'center'}}> )
<br /> }
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{() => getCode()}</CodeHighlight>
</div>
)
} }
function getCode () { const CodeHighlight = require('./components/codeHighlight').default
return ` const source = require('!raw-loader!./Simple')
import ReactTable from 'react-table'
// Create some column definitions export default () => (
const columns = [{ <div>
header: 'Name', <Story />
columns: [{ <CodeHighlight>{() => source}</CodeHighlight>
header: 'First Name', </div>
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
// Display your table!
return (
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
) )
`
}
+44 -93
View File
@@ -2,12 +2,10 @@ import React from 'react'
import _ from 'lodash' import _ from 'lodash'
import namor from 'namor' import namor from 'namor'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../src/index' import ReactTable from '../src/index'
class SubComponents extends React.Component { class Story extends React.Component {
constructor (props) {
constructor(props) {
super(props) super(props)
const data = _.map(_.range(5553), d => { const data = _.map(_.range(5553), d => {
@@ -28,58 +26,57 @@ class SubComponents extends React.Component {
collapseOnPageChange: true, collapseOnPageChange: true,
collapseOnDataChange: true, collapseOnDataChange: true,
freezeWhenExpanded: false, freezeWhenExpanded: false,
showFilters: false filterable: false,
sortable: true,
resizable: true
}, },
data: data data: data
} }
this.setTableOption = this.setTableOption.bind(this); this.setTableOption = this.setTableOption.bind(this)
} }
render () {
render() {
const columns = [{ const columns = [{
header: 'Name', Header: 'Name',
columns: [{ columns: [{
header: 'First Name', Header: 'First Name',
accessor: 'firstName' accessor: 'firstName'
}, { }, {
header: 'Last Name', Header: 'Last Name',
id: 'lastName', id: 'lastName',
accessor: d => d.lastName accessor: d => d.lastName
}] }]
}, { }, {
header: 'Info', Header: 'Info',
columns: [{ columns: [{
header: 'Age', Header: 'Age',
accessor: 'age' accessor: 'age'
}] }]
}] }]
return ( return (
<div> <div>
<div style={{float: "left"}}> <div style={{float: 'left'}}>
<h1>Table Options</h1> <h1>Table Options</h1>
<table> <table>
<tbody> <tbody>
{ {
Object.keys(this.state.tableOptions).map(optionKey => { Object.keys(this.state.tableOptions).map(optionKey => {
const optionValue = this.state.tableOptions[optionKey]; const optionValue = this.state.tableOptions[optionKey]
return ( return (
<tr key={optionKey}> <tr key={optionKey}>
<td>{optionKey}</td> <td>{optionKey}</td>
<td style={{paddingLeft: 10, paddingTop: 5}}> <td style={{paddingLeft: 10, paddingTop: 5}}>
<input type="checkbox" <input type='checkbox'
name={optionKey} name={optionKey}
checked={optionValue} checked={optionValue}
onChange={this.setTableOption} onChange={this.setTableOption}
/> />
</td> </td>
</tr> </tr>
) )
}) })
} }
</tbody> </tbody>
</table> </table>
</div> </div>
@@ -119,15 +116,14 @@ class SubComponents extends React.Component {
<br /> <br />
<em>Tip: Hold shift when sorting to multi-sort!</em> <em>Tip: Hold shift when sorting to multi-sort!</em>
</div> </div>
<CodeHighlight>{() => this.getCode()}</CodeHighlight>
</div> </div>
) )
} }
setTableOption(event) { setTableOption (event) {
const target = event.target; const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value; const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name; const name = target.name
this.setState({ this.setState({
tableOptions: { tableOptions: {
...this.state.tableOptions, ...this.state.tableOptions,
@@ -135,60 +131,15 @@ class SubComponents extends React.Component {
} }
}) })
} }
getCode() {
return `
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
export default (
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
{...otherOptions}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
)
`
}
} }
export default () => <SubComponents/> // Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./SubComponents')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+77
View File
@@ -0,0 +1,77 @@
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../src/index'
class Story extends React.Component {
render () {
const data = _.map(_.range(5553), d => {
const children = _.map(_.range(10), d => {
const grandChildren = _.map(_.range(10), d => {
return {
age: Math.floor(Math.random() * 30)
}
})
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30),
children: grandChildren
}
})
return {
lastName: namor.generate({ words: 1, numLen: 0 }),
firstName: children.map(d => d.firstName),
age: Math.floor(Math.random() * 30),
children
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
expander: true
}, {
Header: 'Last Name',
accessor: 'lastName'
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
subRowsKey='children'
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw-loader!./SubRows')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+38 -327
View File
@@ -99,13 +99,6 @@
webpack-dev-middleware "^1.6.0" webpack-dev-middleware "^1.6.0"
webpack-hot-middleware "^2.13.2" webpack-hot-middleware "^2.13.2"
JSONStream@^1.0.3:
version "1.3.0"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.0.tgz#680ab9ac6572a8a1a207e0b38721db1c77b215e5"
dependencies:
jsonparse "^1.2.0"
through ">=2.2.7 <3"
abab@^1.0.0: abab@^1.0.0:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
@@ -139,15 +132,11 @@ acorn-jsx@^3.0.0, acorn-jsx@^3.0.1:
dependencies: dependencies:
acorn "^3.0.4" acorn "^3.0.4"
acorn@^1.0.3: acorn@^2.1.0, acorn@^2.4.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014"
acorn@^2.1.0, acorn@^2.4.0, acorn@^2.7.0:
version "2.7.0" version "2.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7"
acorn@^3.0.0, acorn@^3.0.4, acorn@^3.1.0: acorn@^3.0.0, acorn@^3.0.4:
version "3.3.0" version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
@@ -326,7 +315,7 @@ assert-plus@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
assert@^1.1.1, assert@~1.3.0: assert@^1.1.1:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.3.0.tgz#03939a622582a812cc202320a0b9a56c9b815849" resolved "https://registry.yarnpkg.com/assert/-/assert-1.3.0.tgz#03939a622582a812cc202320a0b9a56c9b815849"
dependencies: dependencies:
@@ -336,12 +325,6 @@ ast-types@0.9.4:
version "0.9.4" version "0.9.4"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.4.tgz#410d1f81890aeb8e0a38621558ba5869ae53c91b" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.4.tgz#410d1f81890aeb8e0a38621558ba5869ae53c91b"
astw@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astw/-/astw-2.0.0.tgz#08121ac8288d35611c0ceec663f6cd545604897d"
dependencies:
acorn "^1.0.3"
async-each@^1.0.0: async-each@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
@@ -421,7 +404,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2" esutils "^2.0.2"
js-tokens "^3.0.0" js-tokens "^3.0.0"
babel-core@^6.0.14, babel-core@^6.11.4, babel-core@^6.14.0, babel-core@^6.22.0: babel-core@^6.11.4, babel-core@^6.14.0, babel-core@^6.22.0:
version "6.22.1" version "6.22.1"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.22.1.tgz#9c5fd658ba1772d28d721f6d25d968fc7ae21648" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.22.1.tgz#9c5fd658ba1772d28d721f6d25d968fc7ae21648"
dependencies: dependencies:
@@ -1231,13 +1214,6 @@ babel-types@^6.0.19, babel-types@^6.16.0, babel-types@^6.19.0, babel-types@^6.22
lodash "^4.2.0" lodash "^4.2.0"
to-fast-properties "^1.0.1" to-fast-properties "^1.0.1"
babelify@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5"
dependencies:
babel-core "^6.0.14"
object-assign "^4.0.0"
babylon@^6.0.18, babylon@^6.11.0, babylon@^6.15.0: babylon@^6.0.18, babylon@^6.11.0, babylon@^6.15.0:
version "6.15.0" version "6.15.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e"
@@ -1322,22 +1298,6 @@ brorand@^1.0.1:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.0.6.tgz#4028706b915f91f7b349a2e0bf3c376039d216e5" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.0.6.tgz#4028706b915f91f7b349a2e0bf3c376039d216e5"
browser-pack@^6.0.1:
version "6.0.2"
resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.2.tgz#f86cd6cef4f5300c8e63e07a4d512f65fbff4531"
dependencies:
JSONStream "^1.0.3"
combine-source-map "~0.7.1"
defined "^1.0.0"
through2 "^2.0.0"
umd "^3.0.0"
browser-resolve@^1.11.0, browser-resolve@^1.7.0:
version "1.11.2"
resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce"
dependencies:
resolve "1.1.7"
browserify-aes@0.4.0: browserify-aes@0.4.0:
version "0.4.0" version "0.4.0"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c"
@@ -1389,63 +1349,12 @@ browserify-sign@^4.0.0:
inherits "^2.0.1" inherits "^2.0.1"
parse-asn1 "^5.0.0" parse-asn1 "^5.0.0"
browserify-zlib@^0.1.4, browserify-zlib@~0.1.2: browserify-zlib@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
dependencies: dependencies:
pako "~0.2.0" pako "~0.2.0"
browserify@13.1.0:
version "13.1.0"
resolved "https://registry.yarnpkg.com/browserify/-/browserify-13.1.0.tgz#d81a018e98dd7ca706ec04253d20f8a03b2af8ae"
dependencies:
JSONStream "^1.0.3"
assert "~1.3.0"
browser-pack "^6.0.1"
browser-resolve "^1.11.0"
browserify-zlib "~0.1.2"
buffer "^4.1.0"
concat-stream "~1.5.1"
console-browserify "^1.1.0"
constants-browserify "~1.0.0"
crypto-browserify "^3.0.0"
defined "^1.0.0"
deps-sort "^2.0.0"
domain-browser "~1.1.0"
duplexer2 "~0.1.2"
events "~1.1.0"
glob "^5.0.15"
has "^1.0.0"
htmlescape "^1.1.0"
https-browserify "~0.0.0"
inherits "~2.0.1"
insert-module-globals "^7.0.0"
labeled-stream-splicer "^2.0.0"
module-deps "^4.0.2"
os-browserify "~0.1.1"
parents "^1.0.1"
path-browserify "~0.0.0"
process "~0.11.0"
punycode "^1.3.2"
querystring-es3 "~0.2.0"
read-only-stream "^2.0.0"
readable-stream "^2.0.2"
resolve "^1.1.4"
shasum "^1.0.0"
shell-quote "^1.4.3"
stream-browserify "^2.0.0"
stream-http "^2.0.0"
string_decoder "~0.10.0"
subarg "^1.0.0"
syntax-error "^1.1.1"
through2 "^2.0.0"
timers-browserify "^1.0.1"
tty-browserify "~0.0.0"
url "~0.11.0"
util "~0.10.1"
vm-browserify "~0.0.1"
xtend "^4.0.0"
browserslist@^1.0.1, browserslist@^1.4.0, browserslist@^1.5.2, browserslist@~1.6.0: browserslist@^1.0.1, browserslist@^1.4.0, browserslist@^1.5.2, browserslist@~1.6.0:
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.6.0.tgz#85fb7c993540d3fda31c282baf7f5aee698ac9ee" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.6.0.tgz#85fb7c993540d3fda31c282baf7f5aee698ac9ee"
@@ -1461,7 +1370,7 @@ buffer-xor@^1.0.2:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
buffer@^4.1.0, buffer@^4.3.0, buffer@^4.9.0: buffer@^4.3.0, buffer@^4.9.0:
version "4.9.1" version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
dependencies: dependencies:
@@ -1477,10 +1386,6 @@ builtin-status-codes@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
cached-path-relative@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.0.tgz#d1094c577fbd9a8b8bd43c96af6188aa205d05f4"
caller-path@^0.1.0: caller-path@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
@@ -1694,15 +1599,6 @@ colors@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
combine-source-map@~0.7.1:
version "0.7.2"
resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e"
dependencies:
convert-source-map "~1.1.0"
inline-source-map "~0.6.0"
lodash.memoize "~3.0.3"
source-map "~0.5.3"
combined-stream@^1.0.5, combined-stream@~1.0.5: combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
@@ -1729,7 +1625,7 @@ concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
concat-stream@^1.4.6, concat-stream@~1.5.0, concat-stream@~1.5.1: concat-stream@^1.4.6:
version "1.5.2" version "1.5.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266"
dependencies: dependencies:
@@ -1761,7 +1657,7 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
constants-browserify@^1.0.0, constants-browserify@~1.0.0: constants-browserify@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -1781,10 +1677,6 @@ convert-source-map@^1.1.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67"
convert-source-map@~1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860"
cookie-signature@1.0.6: cookie-signature@1.0.6:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
@@ -1861,7 +1753,7 @@ crypto-browserify@3.3.0:
ripemd160 "0.2.0" ripemd160 "0.2.0"
sha.js "2.2.6" sha.js "2.2.6"
crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: crypto-browserify@^3.11.0:
version "3.11.0" version "3.11.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522"
dependencies: dependencies:
@@ -2075,15 +1967,6 @@ depd@~1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
deps-sort@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5"
dependencies:
JSONStream "^1.0.3"
shasum "^1.0.0"
subarg "^1.0.0"
through2 "^2.0.0"
des.js@^1.0.0: des.js@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
@@ -2101,13 +1984,6 @@ detect-indent@^4.0.0:
dependencies: dependencies:
repeating "^2.0.0" repeating "^2.0.0"
detective@^4.0.0:
version "4.3.2"
resolved "https://registry.yarnpkg.com/detective/-/detective-4.3.2.tgz#77697e2e7947ac3fe7c8e26a6d6f115235afa91c"
dependencies:
acorn "^3.1.0"
defined "^1.0.0"
diffie-hellman@^5.0.0: diffie-hellman@^5.0.0:
version "5.0.2" version "5.0.2"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
@@ -2130,7 +2006,7 @@ doctrine@^2.0.0:
esutils "^2.0.2" esutils "^2.0.2"
isarray "^1.0.0" isarray "^1.0.0"
domain-browser@^1.1.1, domain-browser@~1.1.0: domain-browser@^1.1.1:
version "1.1.7" version "1.1.7"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
@@ -2140,12 +2016,6 @@ dot-prop@^3.0.0:
dependencies: dependencies:
is-obj "^1.0.0" is-obj "^1.0.0"
duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
dependencies:
readable-stream "^2.0.2"
duplexer@~0.1.1: duplexer@~0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
@@ -2455,7 +2325,7 @@ event-stream@~3.3.0:
stream-combiner "~0.0.4" stream-combiner "~0.0.4"
through "~2.3.1" through "~2.3.1"
events@^1.0.0, events@^1.1.1, events@~1.1.0: events@^1.0.0, events@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
@@ -2516,10 +2386,6 @@ express@^4.13.3:
utils-merge "1.0.0" utils-merge "1.0.0"
vary "~1.1.0" vary "~1.1.0"
extend@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extend/-/extend-1.3.0.tgz#d1516fb0ff5624d2ebf9123ea1dac5a1994004f8"
extend@~3.0.0: extend@~3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
@@ -2795,7 +2661,7 @@ glob@7.0.x, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
glob@^5.0.15, glob@^5.0.5: glob@^5.0.5:
version "5.0.15" version "5.0.15"
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
dependencies: dependencies:
@@ -2872,7 +2738,7 @@ has-unicode@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
has@^1.0.0, has@^1.0.1: has@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
dependencies: dependencies:
@@ -2953,10 +2819,6 @@ html-minifier@^3.0.1:
relateurl "0.2.x" relateurl "0.2.x"
uglify-js "2.7.x" uglify-js "2.7.x"
htmlescape@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351"
http-errors@~1.5.0, http-errors@~1.5.1: http-errors@~1.5.0, http-errors@~1.5.1:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750"
@@ -2973,7 +2835,7 @@ http-signature@~1.1.0:
jsprim "^1.2.2" jsprim "^1.2.2"
sshpk "^1.7.0" sshpk "^1.7.0"
https-browserify@0.0.1, https-browserify@~0.0.0: https-browserify@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
@@ -3042,12 +2904,6 @@ ini@~1.3.0:
version "1.3.4" version "1.3.4"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
inline-source-map@~0.6.0:
version "0.6.2"
resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5"
dependencies:
source-map "~0.5.3"
inquirer@^0.12.0: inquirer@^0.12.0:
version "0.12.0" version "0.12.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
@@ -3066,19 +2922,6 @@ inquirer@^0.12.0:
strip-ansi "^3.0.0" strip-ansi "^3.0.0"
through "^2.3.6" through "^2.3.6"
insert-module-globals@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3"
dependencies:
JSONStream "^1.0.3"
combine-source-map "~0.7.1"
concat-stream "~1.5.1"
is-buffer "^1.1.0"
lexical-scope "^1.2.0"
process "~0.11.0"
through2 "^2.0.0"
xtend "^4.0.0"
interpret@^0.6.4: interpret@^0.6.4:
version "0.6.6" version "0.6.6"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b" resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b"
@@ -3115,7 +2958,7 @@ is-binary-path@^1.0.0:
dependencies: dependencies:
binary-extensions "^1.0.0" binary-extensions "^1.0.0"
is-buffer@^1.0.2, is-buffer@^1.1.0: is-buffer@^1.0.2:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b"
@@ -3266,10 +3109,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
isarray@~0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
isexe@^1.1.1: isexe@^1.1.1:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
@@ -3370,12 +3209,6 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
dependencies: dependencies:
jsonify "~0.0.0" jsonify "~0.0.0"
json-stable-stringify@~0.0.0:
version "0.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45"
dependencies:
jsonify "~0.0.0"
json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@@ -3388,10 +3221,6 @@ jsonify@~0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
jsonparse@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.0.tgz#85fc245b1d9259acc6941960b905adf64e7de0e8"
jsonpointer@^4.0.0: jsonpointer@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
@@ -3421,14 +3250,6 @@ kind-of@^3.0.2:
dependencies: dependencies:
is-buffer "^1.0.2" is-buffer "^1.0.2"
labeled-stream-splicer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59"
dependencies:
inherits "^2.0.1"
isarray "~0.0.1"
stream-splicer "^2.0.0"
lazy-cache@^1.0.3: lazy-cache@^1.0.3:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@@ -3446,12 +3267,6 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2" prelude-ls "~1.1.2"
type-check "~0.3.2" type-check "~0.3.2"
lexical-scope@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/lexical-scope/-/lexical-scope-1.2.0.tgz#fcea5edc704a4b3a8796cdca419c3a0afaf22df4"
dependencies:
astw "^2.0.0"
load-json-file@^1.0.0: load-json-file@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -3523,10 +3338,6 @@ lodash.memoize@^4.1.0:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
lodash.memoize@~3.0.3:
version "3.0.4"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f"
lodash.pick@^4.2.0, lodash.pick@^4.2.1, lodash.pick@^4.4.0: lodash.pick@^4.2.0, lodash.pick@^4.2.1, lodash.pick@^4.4.0:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
@@ -3735,26 +3546,6 @@ mobx@^2.3.4:
version "2.7.0" version "2.7.0"
resolved "https://registry.yarnpkg.com/mobx/-/mobx-2.7.0.tgz#cf3d82d18c0ca7f458d8f2a240817b3dc7e54a01" resolved "https://registry.yarnpkg.com/mobx/-/mobx-2.7.0.tgz#cf3d82d18c0ca7f458d8f2a240817b3dc7e54a01"
module-deps@^4.0.2:
version "4.0.8"
resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.0.8.tgz#55fd70623399706c3288bef7a609ff1e8c0ed2bb"
dependencies:
JSONStream "^1.0.3"
browser-resolve "^1.7.0"
cached-path-relative "^1.0.0"
concat-stream "~1.5.0"
defined "^1.0.0"
detective "^4.0.0"
duplexer2 "^0.1.2"
inherits "^2.0.1"
parents "^1.0.0"
readable-stream "^2.0.2"
resolve "^1.1.3"
stream-combiner2 "^1.1.1"
subarg "^1.0.0"
through2 "^2.0.0"
xtend "^4.0.0"
ms@0.7.1: ms@0.7.1:
version "0.7.1" version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
@@ -3964,7 +3755,7 @@ object-assign@^2.0.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa"
object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0: object-assign@^4.0.1, object-assign@^4.1.0:
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"
@@ -4058,10 +3849,6 @@ os-browserify@^0.2.0:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f"
os-browserify@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54"
os-homedir@^1.0.0, os-homedir@^1.0.1: os-homedir@^1.0.0, os-homedir@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
@@ -4101,12 +3888,6 @@ param-case@2.1.x:
dependencies: dependencies:
no-case "^2.2.0" no-case "^2.2.0"
parents@^1.0.0, parents@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751"
dependencies:
path-platform "~0.11.15"
parse-asn1@^5.0.0: parse-asn1@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.0.0.tgz#35060f6d5015d37628c770f4e091a0b5a278bc23" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.0.0.tgz#35060f6d5015d37628c770f4e091a0b5a278bc23"
@@ -4140,7 +3921,7 @@ parseurl@~1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.1.tgz#c8ab8c9223ba34888aa64a297b28853bec18da56"
path-browserify@0.0.0, path-browserify@~0.0.0: path-browserify@0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
@@ -4162,10 +3943,6 @@ path-is-inside@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
path-platform@~0.11.15:
version "0.11.15"
resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2"
path-to-regexp@0.1.7: path-to-regexp@0.1.7:
version "0.1.7" version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@@ -4537,7 +4314,7 @@ process-nextick-args@~1.0.6:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
process@^0.11.0, process@~0.11.0: process@^0.11.0:
version "0.11.9" version "0.11.9"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1" resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1"
@@ -4586,7 +4363,7 @@ punycode@1.3.2:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -4613,7 +4390,7 @@ query-string@^4.1.0:
object-assign "^4.1.0" object-assign "^4.1.0"
strict-uri-encode "^1.0.0" strict-uri-encode "^1.0.0"
querystring-es3@^0.2.0, querystring-es3@~0.2.0: querystring-es3@^0.2.0:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@@ -4636,6 +4413,10 @@ range-parser@^1.0.3, range-parser@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
rc@~1.1.6: rc@~1.1.6:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9" resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9"
@@ -4757,12 +4538,6 @@ read-file-stdin@^0.2.0:
dependencies: dependencies:
gather-stream "^1.0.0" gather-stream "^1.0.0"
read-only-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0"
dependencies:
readable-stream "^2.0.2"
read-pkg-up@^1.0.1: read-pkg-up@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
@@ -4778,7 +4553,7 @@ read-pkg@^1.0.0, read-pkg@^1.1.0:
normalize-package-data "^2.3.2" normalize-package-data "^2.3.2"
path-type "^1.0.0" path-type "^1.0.0"
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.5: "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0:
version "2.2.2" version "2.2.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
dependencies: dependencies:
@@ -4994,11 +4769,7 @@ resolve-from@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
resolve@1.1.7: resolve@^1.1.6:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.6:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c"
@@ -5149,7 +4920,7 @@ sha.js@2.2.6:
version "2.2.6" version "2.2.6"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba"
sha.js@^2.3.6, sha.js@~2.4.4: sha.js@^2.3.6:
version "2.4.8" version "2.4.8"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f"
dependencies: dependencies:
@@ -5161,14 +4932,7 @@ shallowequal@0.2.x, shallowequal@^0.2.2:
dependencies: dependencies:
lodash.keys "^3.1.2" lodash.keys "^3.1.2"
shasum@^1.0.0: shell-quote@^1.6.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f"
dependencies:
json-stable-stringify "~0.0.0"
sha.js "~2.4.4"
shell-quote@^1.4.3, shell-quote@^1.6.1:
version "1.6.1" version "1.6.1"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767"
dependencies: dependencies:
@@ -5319,27 +5083,20 @@ storybook@^0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/storybook/-/storybook-0.0.0.tgz#b3b9508fb99fd83615674917583cfe9e1532931d" resolved "https://registry.yarnpkg.com/storybook/-/storybook-0.0.0.tgz#b3b9508fb99fd83615674917583cfe9e1532931d"
stream-browserify@^2.0.0, stream-browserify@^2.0.1: stream-browserify@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
dependencies: dependencies:
inherits "~2.0.1" inherits "~2.0.1"
readable-stream "^2.0.2" readable-stream "^2.0.2"
stream-combiner2@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe"
dependencies:
duplexer2 "~0.1.0"
readable-stream "^2.0.2"
stream-combiner@~0.0.4: stream-combiner@~0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
dependencies: dependencies:
duplexer "~0.1.1" duplexer "~0.1.1"
stream-http@^2.0.0, stream-http@^2.3.1: stream-http@^2.3.1:
version "2.6.3" version "2.6.3"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.3.tgz#4c3ddbf9635968ea2cfd4e48d43de5def2625ac3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.3.tgz#4c3ddbf9635968ea2cfd4e48d43de5def2625ac3"
dependencies: dependencies:
@@ -5349,13 +5106,6 @@ stream-http@^2.0.0, stream-http@^2.3.1:
to-arraybuffer "^1.0.0" to-arraybuffer "^1.0.0"
xtend "^4.0.0" xtend "^4.0.0"
stream-splicer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83"
dependencies:
inherits "^2.0.1"
readable-stream "^2.0.2"
strict-uri-encode@^1.0.0: strict-uri-encode@^1.0.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
@@ -5391,7 +5141,7 @@ string.prototype.padstart@^3.0.0:
es-abstract "^1.4.3" es-abstract "^1.4.3"
function-bind "^1.0.2" function-bind "^1.0.2"
string_decoder@^0.10.25, string_decoder@~0.10.0, string_decoder@~0.10.x: string_decoder@^0.10.25, string_decoder@~0.10.x:
version "0.10.31" version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@@ -5442,12 +5192,6 @@ stylus@^0.54.5:
sax "0.5.x" sax "0.5.x"
source-map "0.1.x" source-map "0.1.x"
subarg@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2"
dependencies:
minimist "^1.1.0"
supports-color@^0.2.0: supports-color@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
@@ -5482,12 +5226,6 @@ symbol-observable@^1.0.2:
version "3.2.1" version "3.2.1"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb"
syntax-error@^1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.1.6.tgz#b4549706d386cc1c1dc7c2423f18579b6cade710"
dependencies:
acorn "^2.7.0"
table@^3.7.8: table@^3.7.8:
version "3.8.3" version "3.8.3"
resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
@@ -5532,23 +5270,10 @@ text-table@~0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
through2@^2.0.0: through@2, through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.6:
version "2.0.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
dependencies:
readable-stream "^2.1.5"
xtend "~4.0.1"
through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.6:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
timers-browserify@^1.0.1:
version "1.4.2"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
dependencies:
process "~0.11.0"
timers-browserify@^2.0.2: timers-browserify@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86"
@@ -5585,7 +5310,7 @@ tryit@^1.0.1:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
tty-browserify@0.0.0, tty-browserify@~0.0.0: tty-browserify@0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
@@ -5618,7 +5343,7 @@ ua-parser-js@^0.7.9:
version "0.7.12" version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
uglify-js@2.7.x, uglify-js@2.x.x, uglify-js@~2.7.3: uglify-js@2.7.x, uglify-js@~2.7.3:
version "2.7.5" version "2.7.5"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8"
dependencies: dependencies:
@@ -5640,24 +5365,10 @@ uglify-to-browserify@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
uglifyify@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/uglifyify/-/uglifyify-3.0.3.tgz#e53ba71977dbff773e340e5e35292825965d66d2"
dependencies:
convert-source-map "~1.1.0"
extend "^1.2.1"
minimatch "^3.0.2"
through "~2.3.4"
uglify-js "2.x.x"
uid-number@~0.0.6: uid-number@~0.0.6:
version "0.0.6" version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
umd@^3.0.0:
version "3.0.1"
resolved "http://registry.npmjs.org/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e"
uniq@^1.0.1: uniq@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
@@ -5687,7 +5398,7 @@ url-loader@^0.5.7:
loader-utils "0.2.x" loader-utils "0.2.x"
mime "1.2.x" mime "1.2.x"
url@^0.11.0, url@~0.11.0: url@^0.11.0:
version "0.11.0" version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
dependencies: dependencies:
@@ -5708,7 +5419,7 @@ util-deprecate@~1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
util@0.10.3, util@^0.10.3, util@~0.10.1: util@0.10.3, util@^0.10.3:
version "0.10.3" version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
dependencies: dependencies:
@@ -5753,7 +5464,7 @@ verror@1.3.6:
dependencies: dependencies:
extsprintf "1.0.2" extsprintf "1.0.2"
vm-browserify@0.0.4, vm-browserify@~0.0.1: vm-browserify@0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
dependencies: dependencies:
@@ -5953,7 +5664,7 @@ xml-char-classes@^1.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: xtend@^4.0.0, xtend@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"