├── .babelrc
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── README.md
├── circle.yml
├── package.json
├── src
    ├── action-reducer.js
    ├── index.js
    ├── ui.js
    └── utils.js
├── test
    ├── action-reducer
    │   └── reducer.js
    ├── setup.js
    ├── ui
    │   ├── context.js
    │   ├── defaults.js
    │   ├── key.js
    │   ├── opts.js
    │   ├── reducer.js
    │   ├── reset.js
    │   └── validation.js
    └── utils
    │   └── render.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 |     "presets": ["es2015", "react", "stage-0"],
3 |     "plugins": ["transform-decorators-legacy"]
4 | }
5 | 
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | transpiled
2 | node_modules
3 | 
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | 
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
 1 | # v0.1.0
 2 | - Update dependencies to work with React 15 (thanks @kurtfunai)
 3 | - Allow functions inside updateUI (`this.props.updateUI('username', v => v.toUpperCase());`)
 4 | 
 5 | # v0.0.15
 6 | - Add: Allow `options` and `mergeProps` to be passed to `@connect()`
 7 | - Add: Expose `uiPath` in `this.props.uiPath`
 8 | - Fix state evaluation when parents call resetUI
 9 | - Fix state evaluation when child call resetUI
10 | 
11 | # v0.0.14
12 | - Fix: update package.json for react 15
13 | 
14 | # v0.0.13
15 | - republish of 0.0.12 due to npm error
16 | 
17 | # v0.0.12
18 | - Add support for redux-immutable
19 | 
20 | # v0.0.11
21 | - Change: Upgrade to babel 6
22 | - Improve: Throw an error when custom reducers return no state
23 | 
24 | # v0.0.9
25 | - Fix: issue where componentWillReceiveProps could break derived state from
26 |   functions within opts.state
27 | 
28 | # v0.0.8
29 | - Add: allow default state to be set from an evaulated function with the
30 |   signature (props, state).
31 | 
32 | # v0.0.7
33 | - Add: Custom per-component reducers for local UI state modification
34 | - Fix: Fix react warnings from setting props in constructor
35 | 
36 | # v0.0.6
37 | - Fix: no longer deeply convert UI defalts to immutableJS
38 | - Change: Set default UI state in constructor
39 | - Change: Delay wiping UI state on unmount in `requestAnimationFrame`
40 | 
41 | # v0.0.5
42 | - Work around issue in `componentWillMount` in React. See commit
43 |   `5f9ab5c44fc7941e6f78fa9470ab8a04b7487997` for more info.
44 | 
45 | # v0.0.4
46 | - Fix invariant import in reducer
47 | 
48 | # v0.0.3
49 | - Add transpiled source to package
50 | 
51 | # v0.0.2
52 | - Fix dependencies
53 | 
54 | # v0.0.1
55 | - Initial version with scoping of contexts from parent to child
56 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | [](https://circleci.com/gh/tonyhb/redux-ui)
  2 | 
  3 | # redux-ui: ui state without profanity
  4 | 
  5 | Think of redux-ui as **block-level scoping** for UI state. In this example each block-scope represents a component, and each variable represents a UI state key:
  6 | 
  7 | ```js
  8 | {
  9 |   // Everything inside this scope has access to filter and tags. This is our root UI component.
 10 |   let filter = '';
 11 |   let tags = [];
 12 | 
 13 |   // Imagine the following scopes are a list of to-do tasks:
 14 |   {
 15 |     // Everything inside this scope has access to isSelected - plus all parent variables.
 16 |     let isSelected = true
 17 |   }
 18 |   {
 19 |     // This also has isSelected inside its scope and access to parent variables, but
 20 |     // isSelected is in a separate scope and can be manipulated independently from other
 21 |     // siblings.
 22 |     let isSelected = false
 23 |   }
 24 | }
 25 | ```
 26 | 
 27 | Wrap your root component with the redux-ui `@ui()` decorator.  It's given a new scope for temporary UI variables which:
 28 | 
 29 | - are automatically bound to `this.props.ui`
 30 | - are automatically passed any child component wrapped with the `@ui()` decorator
 31 | - will be automatically reset on componentWillUnmount (preventable via options)
 32 | - can be reset manually via a prop
 33 | - are updatable by any child component within the `@ui()` decorator
 34 | 
 35 | This is **powerful**. **Each component is reusable** and can still affect UI state for parent components.
 36 | 
 37 | ### Setup
 38 | 
 39 | **Step 1**: Add the redux-ui reducer to your reducers **under the `ui` key**:
 40 | ```js
 41 | import { reducer as uiReducer } from 'redux-ui'
 42 | // ...
 43 | combineReducers({ ...yourReducers, ui: uiReducer })
 44 | ```
 45 | 
 46 | **Step 2**: In each 'scene' or parent component add the UI decorator with the key in
 47 | which to save all state:
 48 | ```
 49 | import ui from 'redux-ui';
 50 | 
 51 | @ui({
 52 |   state: {
 53 |     yourVars: 'withDefaults',
 54 |     filters: []
 55 |   }
 56 | })
 57 | class YourComponent extends React.Component {
 58 | }
 59 | ```
 60 | 
 61 | **Step 3**: In each child component use the basic `@ui()` decorator; it will
 62 | automatically read and write UI state to the parent component's UI key.
 63 | 
 64 | You can also define variables in child components. If your child component has
 65 | variables named the same as a parent component think of block scoping:
 66 | everything within your child component down will read from the child's scope,
 67 | but the parent will use the parent's UI variable.
 68 | 
 69 | ### Usage
 70 | 
 71 | The `@ui` decorator injects four props into your components:
 72 | 
 73 | 1. `uiKey`: The key passed to the decorator from the decorator (eg.
 74 |    'some-decorator' with `@ui('some-decorator')`
 75 | 2. `ui`: The UI state for the component's `uiKey`
 76 | 3. `updateUI`: A function accepting either a name/value pair or object which
 77 |    updates state within `uiKey`
 78 | 4. `resetUI`: A function which resets the state within `uiKey` to its default
 79 | 
 80 | The decorator will set any default state specified (see below).
 81 | On `componentWillUnmount` the entire state in `uiKey` will be set to undefined.
 82 | You can also blow away state by calling	`resetUI` (for example, on router
 83 | changes).
 84 | 
 85 | ### Decorator API
 86 | 
 87 | The decorator takes an object of options:
 88 | 
 89 | ```js
 90 | @ui({
 91 |   // optional key which is used to determine the UI path in which state will
 92 |   // be stored. if omitted this is randomly generated.
 93 |   key: 'some-name',
 94 |   // optional persist, defaults to false. if set to true persist will keep UI
 95 |   // state for this component after it unmounts. if set to false the UI state will
 96 |   // be deleted and recreated when the component remounts
 97 |   persist: true,
 98 |   // **required**: UI state for the component
 99 |   state: {
100 |     uiVar1: '',
101 |     // You can set default UI state based on the component's props and the
102 |     // global store's state.
103 |     uiVar2: (props, state) => state.router.location.query.searchTerm
104 |   },
105 |   // customReducer: you can handle the UI state for this component's scope by dispatching actions
106 |   reducer: (state, action) => {
107 |     // state represents *only* the UI state for this component's scope - not any children
108 |     switch(action.type) {
109 |       case '@@reduxReactRouter/routerDidChange':
110 |         if (action.payload.location.query.extra_filters) {
111 |           return state.set('extraFilters', true);
112 |         }
113 |       }
114 |       return state;
115 |     }
116 |   },
117 |   // optional mergeProps passed to react-redux' @connect
118 |   mergeProps: () => ({}),
119 |   // optional `options` passed to react-redux @connect
120 |   options: {}
121 | })
122 | ```
123 | 
124 | ### Non-decorator API
125 | 
126 | You can use redux-ui without using an ES7 decorator like so:
127 | 
128 | ```
129 | import ui from 'redux-ui';
130 | // or ui = require('redux-ui').default;
131 | 
132 | class SomeComponent extends Component {
133 | }
134 | 
135 | SomeComponentWithUI = ui({ key: 'some-name', state: { ... }})(SomeComponent);
136 | ```
137 | 
138 | ##### `key`: string, defaults to random characters
139 | 
140 | The name of the key used in the UI reducer under which we store all state.  Allows you to create selectors in reselect with known paths, and allows setting `persist` below.
141 | 
142 | If this is not specified it will be autogenerated based on the component name suffixed with a random hex code.  Components using the same key will share the same UI context, so don't supply a name to a list of components (generated in a loop) if they need their own UI state.
143 | 
144 | 
145 | ##### `persist`: bool, defaults to `false`
146 | 
147 | Set to true if the UI state for this component should persist after `componentWillUnmount`.  You must also explicitly define a `key` for this component, otherwise the component will randomize the key and load new UI state on instantiation.
148 | 
149 | **Note**: All parent UI components also need to set this to true for this to take effect. Think of block-level scoping again — if a parent scope quits all child scopes are also out of context.
150 | 
151 | ##### `state`: object
152 | 
153 | All UI variables need to be explicitly defined in the state object.  This allows us to determine which scope a variable belongs to, as scope is inherited in the component tree.  Think of this as using `let` inside your block scopes.
154 | 
155 | ### Examples
156 | 
157 | ```js
158 | import ui from 'redux-ui';
159 | 
160 | // Component A gets its own context with the default UI state below.
161 | // `this.props.ui` will contain this state map.
162 | @ui({
163 |   state: {
164 |     // use the filter query parma via redux-router as the default
165 |     filter: (props, state) => state.router.location.query.filter,
166 |     isFormVisible: true,
167 |     isBackgroundRed: false
168 |   }
169 | })
170 | class A extends Component {
171 |   render() {
172 |     return (
173 |       
208 |         
I have my own UI state C and inherit UI state from B and A
209 |         
If I define variables which collide with B or A mine will
210 |         be used, as it is the most specific context.
211 |     );
212 |   }
213 | }
214 | ```
215 | 
216 | ### Aims
217 | 
218 | UI state:
219 | 
220 | 1. Should be global
221 | 2. Should be easily managed from each component via an action
222 | 3. Should be easy to reset (manually and when unmounting)
223 | 
224 | All of these goals should be easy to achieve.
225 | 
226 | ---
227 | 
228 | MIT license.
229 | 
230 | Written by [Franklin Ta](https://github.com/fta2012) and [Tony Holdstock-Brown](https://github.com/tonyhb).
231 | 
232 | 
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
 1 | machine:
 2 |         environment:
 3 |                 PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin"
 4 | 
 5 | dependencies:
 6 |         override:
 7 |                 - yarn
 8 | 
 9 | cache_directories:
10 |         - ~/.cache/yarn
11 | 
12 | test:
13 |         override:
14 |                 - yarn test
15 | 
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "redux-ui",
 3 |   "version": "0.1.1",
 4 |   "description": "UI state management for Redux and React",
 5 |   "main": "transpiled/index.js",
 6 |   "scripts": {
 7 |     "prepublish": "$(npm bin)/babel -d transpiled src",
 8 |     "test": "$(npm bin)/mocha  --compilers js:babel-register --recursive --require ./test/setup.js"
 9 |   },
10 |   "repository": {
11 |     "type": "git",
12 |     "url": "git+https://github.com/tonyhb/redux-ui.git"
13 |   },
14 |   "keywords": [
15 |     "react-component",
16 |     "redux",
17 |     "redux-ui",
18 |     "ui"
19 |   ],
20 |   "author": "Tony Holdstock-Brown",
21 |   "license": "MIT",
22 |   "bugs": {
23 |     "url": "https://github.com/tonyhb/redux-ui/issues"
24 |   },
25 |   "homepage": "https://github.com/tonyhb/redux-ui#readme",
26 |   "devDependencies": {
27 |     "babel-cli": "6.5.1",
28 |     "babel-plugin-transform-decorators-legacy": "^1.3.4",
29 |     "babel-preset-es2015": "^6.6.0",
30 |     "babel-preset-react": "^6.5.0",
31 |     "babel-preset-stage-0": "^6.5.0",
32 |     "chai": "^3.4.1",
33 |     "jsdom": "^7.2.1",
34 |     "mocha": "^2.3.4",
35 |     "react-dom": "15.5.0"
36 |   },
37 |   "dependencies": {
38 |     "babel-register": "^6.6.0",
39 |     "immutable": "^3.7.5",
40 |     "invariant": "^2.2.0",
41 |     "prop-types": "^15.5.7",
42 |     "react-redux": "^4.4.8 || ^5.0.4",
43 |     "redux": "^3.0.4"
44 |   },
45 |   "peerDependencies": {
46 |     "react": "^0.14.9 || ^15.3.0 || ^16.0.0"
47 |   }
48 | }
49 | 
--------------------------------------------------------------------------------
/src/action-reducer.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | import { Map } from 'immutable';
  4 | import invariant from 'invariant'
  5 | 
  6 | // For updating multiple UI variables at once.  Each variable might be part of
  7 | // a different context; this means that we need to either call updateUI on each
  8 | // key of the object to update or do transformations within one action in the
  9 | // reducer. The latter only triggers one store change event and is more
 10 | // performant.
 11 | export const MASS_UPDATE_UI_STATE = '@@redux-ui/MASS_UPDATE_UI_STATE';
 12 | export const UPDATE_UI_STATE = '@@redux-ui/UPDATE_UI_STATE';
 13 | export const SET_DEFAULT_UI_STATE = '@@redux-ui/SET_DEFAULT_UI_STATE';
 14 | 
 15 | // These are private consts used in actions only given to the UI decorator.
 16 | const MOUNT_UI_STATE = '@@redux-ui/MOUNT_UI_STATE';
 17 | const UNMOUNT_UI_STATE = '@@redux-ui/UNMOUNT_UI_STATE';
 18 | 
 19 | export const defaultState = new Map({
 20 |   __reducers: new Map({
 21 |     // This contains a map of component paths (joined by '.') to an object
 22 |     // containing the fully qualified path and the reducer function:
 23 |     // 'parent.child': {
 24 |     //   path: ['parent', 'child'],
 25 |     //   func: (state, action) => { ... }
 26 |     // }
 27 |   })
 28 | });
 29 | 
 30 | export default function reducer(state = defaultState, action) {
 31 |   let key = action.payload && (action.payload.key || []);
 32 | 
 33 |   if (!Array.isArray(key)) {
 34 |     key = [key];
 35 |   }
 36 | 
 37 |   switch (action.type) {
 38 |     case UPDATE_UI_STATE:
 39 |       const { name, value } = action.payload;
 40 |       if (typeof value === 'function') {
 41 |         state = state.updateIn(key.concat(name), value);
 42 |       } else {
 43 |         state = state.setIn(key.concat(name), value);
 44 |       }
 45 |       break;
 46 | 
 47 |     case MASS_UPDATE_UI_STATE:
 48 |       const { uiVars, transforms } = action.payload;
 49 |       state = state.withMutations( s => {
 50 |         Object.keys(transforms).forEach(k => {
 51 |           const path = uiVars[k];
 52 |           invariant(
 53 |             path,
 54 |             `Couldn't find variable ${k} within your component's UI state ` +
 55 |             `context. Define ${k} before using it in the @ui decorator`
 56 |           );
 57 | 
 58 |           s.setIn(path.concat(k), transforms[k]);
 59 |         });
 60 |       });
 61 |       break;
 62 | 
 63 |     case SET_DEFAULT_UI_STATE:
 64 |       // Replace all UI under a key with the given values
 65 |       state = state.setIn(key, new Map(action.payload.value));
 66 |       break;
 67 | 
 68 |     case MOUNT_UI_STATE:
 69 |       const { defaults, customReducer } = action.payload;
 70 |       state = state.withMutations( s => {
 71 |         // Set the defaults for the component
 72 |         s.setIn(key, new Map(defaults));
 73 | 
 74 |         // If this component has a custom reducer add it to the list.
 75 |         // We store the reducer func and UI path for the current component
 76 |         // inside the __reducers map.
 77 |         if (customReducer) {
 78 |           let path = key.join('.');
 79 |           s.setIn(['__reducers', path], {
 80 |             path: key,
 81 |             func: customReducer
 82 |           });
 83 |         }
 84 | 
 85 |         return s;
 86 |       });
 87 |       break;
 88 | 
 89 |     case UNMOUNT_UI_STATE:
 90 |       // We have to use deleteIn as react unmounts root components first;
 91 |       // this means that using setIn in child contexts will fail as the root
 92 |       // context will be stored as undefined in our state
 93 |       state= state.withMutations(s => {
 94 |         s.deleteIn(key);
 95 |         // Remove any custom reducers
 96 |         s.deleteIn(['__reducers', key.join('.')]);
 97 |       });
 98 |       break;
 99 |   }
100 | 
101 |   const customReducers = state.get('__reducers');
102 |   if (customReducers.size > 0) {
103 |     state = state.withMutations(mut => {
104 |       customReducers.forEach(r => {
105 |         // This calls each custom reducer with the UI state for each custom
106 |         // reducer with the component's UI state tree passed into it.
107 |         //
108 |         // NOTE: Each component's reducer gets its own UI state: not the entire
109 |         // UI reducer's state. Whatever is returned from this reducer is set
110 |         // within the **components** UI scope.
111 |         //
112 |         // This is because it's the only way to update UI state for components
113 |         // without keys - you need to know the path in advance to update state
114 |         // from a reducer.  If you have list of components with no UI keys in
115 |         // the component heirarchy, any children will not be able to use custom
116 |         // reducers as the path is random.
117 |         //
118 |         // TODO: Potentially add the possibility for a global UI state reducer?
119 |         //       Though why wouldn't you just add a custom reducer to the
120 |         //       top-level component?
121 |         const { path, func } = r;
122 |         const newState = func(mut.getIn(path), action);
123 |         if (newState === undefined) {
124 |           throw new Error(`Your custom UI reducer at path ${path.join('.')} must return some state`);
125 |         }
126 |         mut.setIn(path, newState);
127 |       });
128 |       return mut;
129 |     });
130 |   }
131 | 
132 |   return state;
133 | }
134 | 
135 | export const reducerEnhancer = (customReducer) => (state, action) => {
136 |   state = reducer(state, action);
137 |   if (typeof customReducer === 'function') {
138 |     state = customReducer(state, action);
139 |   }
140 |   return state;
141 | }
142 | 
143 | export function updateUI(key, name, value) {
144 |   return {
145 |     type: UPDATE_UI_STATE,
146 |     payload: {
147 |       key,
148 |       name,
149 |       value
150 |     }
151 |   };
152 | };
153 | 
154 | export function massUpdateUI(uiVars, transforms) {
155 |   return {
156 |     type: MASS_UPDATE_UI_STATE,
157 |     payload: {
158 |       uiVars,
159 |       transforms
160 |     }
161 |   };
162 | }
163 | 
164 | // Exposed to components, allowing them to reset their and all child scopes to
165 | // the default variables set up
166 | export function setDefaultUI(key, value) {
167 |   return {
168 |     type: SET_DEFAULT_UI_STATE,
169 |     payload: {
170 |       key,
171 |       value
172 |     }
173 |   };
174 | };
175 | 
176 | /** Private, decorator only actions **/
177 | 
178 | // This is not exposed to your components; it's only used in the decorator.
179 | export function unmountUI(key) {
180 |   return {
181 |     type: UNMOUNT_UI_STATE,
182 |     payload: {
183 |       key
184 |     }
185 |   };
186 | };
187 | 
188 | /**
189 |  * Given the key/path, set of defaults and custom reducer for a UI component
190 |  * during construction prepare the state of the UI reducer
191 |  *
192 |  */
193 | export function mountUI(key, defaults, customReducer) {
194 |   return {
195 |     type: MOUNT_UI_STATE,
196 |     payload: {
197 |       key,
198 |       defaults,
199 |       customReducer
200 |     }
201 |   }
202 | }
203 | 
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | 
3 | import ui from './ui';
4 | import reducer from './action-reducer';
5 | 
6 | export default ui;
7 | export { reducer };
8 | 
--------------------------------------------------------------------------------
/src/ui.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | import React, { Component } from 'react';
  4 | import { any, array, func, node, object, string } from 'prop-types';
  5 | import { bindActionCreators } from 'redux';
  6 | import { connect } from 'react-redux';
  7 | import invariant from 'invariant';
  8 | import { updateUI, massUpdateUI, setDefaultUI, mountUI, unmountUI } from './action-reducer';
  9 | 
 10 | import { getUIState } from './utils';
 11 | 
 12 | export default function ui(key, opts = {}) {
 13 |   if (typeof key === 'object') {
 14 |     opts = key;
 15 |     key = opts.key;
 16 |   }
 17 | 
 18 |   const connector = connect(
 19 |     (state) => { return { ui: getUIState(state) }; },
 20 |     (dispatch) => bindActionCreators({
 21 |       updateUI,
 22 |       massUpdateUI,
 23 |       setDefaultUI,
 24 |       mountUI,
 25 |       unmountUI
 26 |     }, dispatch),
 27 |     // These allow you to pass 'mergeProps' and 'options' keys into the
 28 |     // UI decorator's options which will be passed to @connect().
 29 |     // TODO: Document
 30 |     opts.mergeProps,
 31 |     opts.options,
 32 |   );
 33 | 
 34 |   return (WrappedComponent) => {
 35 | 
 36 |     // Return a parent UI class which scopes all UI state to the given key
 37 |     return connector(
 38 |       /**
 39 |        * UI is a wrapper component which:
 40 |        *   1. Inherits any parent scopes from parent components that are wrapped
 41 |        *      by @UI
 42 |        *   2. Sets up a new UI scope for the current component
 43 |        *   3. Merges the current UI scope into the parent UI scope (where the
 44 |        *      current scope takes precedence over parents)
 45 |        *
 46 |        * This allows normal block-scoping of UI state:
 47 |        *
 48 |        *   1. All UI components must define their local state keys
 49 |        *   2. Upon updating a state key, if it's not in the current scope
 50 |        *      walk up the tree until the variable is set
 51 |        *
 52 |        * This means that any child component can affect the current browser
 53 |        * chrome's UI state whilst maintaining their own local UI state.
 54 |        *
 55 |        * All state will be blown away on navigation by default.
 56 |        */
 57 |       class UI extends Component {
 58 | 
 59 |         constructor(props, ctx, queue) {
 60 |           super(props, ctx, queue);
 61 | 
 62 |           // If the key is undefined generate a new random hex key for the
 63 |           // current component's UI scope.
 64 |           //
 65 |           // We do this in construct() to guarantee a new key at component
 66 |           // instantiation time wihch is needed for iterating through a list of
 67 |           // components with no explicit key
 68 |           if (key === undefined) {
 69 |             this.key = (WrappedComponent.displayName ||
 70 |                    WrappedComponent.name) +
 71 |                    Math.floor(Math.random() * (1 << 30)).toString(16);
 72 |           } else {
 73 |             this.key = key;
 74 |           }
 75 | 
 76 |           // Immediately set this.uiPath and this.uiVars based on the incoming
 77 |           // context in class instantiation
 78 |           this.getMergedContextVars(ctx);
 79 |         }
 80 | 
 81 |         static propTypes = {
 82 |           // The entire global UI state via react-redux connector
 83 |           ui: object.isRequired,
 84 |           // These actions are passed via react-redux connector
 85 |           setDefaultUI: func.isRequired,
 86 |           updateUI: func.isRequired,
 87 |           massUpdateUI: func.isRequired
 88 |         }
 89 | 
 90 |         // Pass these down in the new context created for this component
 91 |         static childContextTypes = {
 92 |           // uiKey is the name of the parent context's key
 93 |           uiKey: string,
 94 |           // uiPath is the current path of the UI context
 95 |           uiPath: array,
 96 |           // uiVars is a map of UI variable names stored in state to the parent
 97 |           // context which controls them.
 98 |           uiVars: object,
 99 | 
100 |           // Actions to pass to children
101 |           updateUI: func,
102 |           resetUI: func
103 |         }
104 | 
105 |         // Get the existing context from a UI parent, if possible
106 |         static contextTypes = {
107 |           // This is used in mergeUIProps and construct() to immediately set
108 |           // props.
109 |           store: any,
110 | 
111 |           uiKey: string,
112 |           uiPath: array,
113 |           uiVars: object,
114 | 
115 |           updateUI: func,
116 |           resetUI: func
117 |         }
118 | 
119 |         componentWillMount() {
120 |           // If the component's UI subtree doesn't exist and we have state to
121 |           // set ensure we update our global store with the current state.
122 |           if (this.props.ui.getIn(this.uiPath) === undefined && opts.state) {
123 |             const state = this.getDefaultUIState(opts.state);
124 |             this.context.store.dispatch(mountUI(this.uiPath, state, opts.reducer));
125 |           }
126 |         }
127 | 
128 |         // When a parent context calls resetUI it blows away the entire subtree
129 |         // that any child contexts may store state in.
130 |         //
131 |         // We may need to restore default props for this component if a parent
132 |         // has blown away our state.
133 |         componentWillReceiveProps(nextProps) {
134 |           // We can only see if this component's state is blown away by
135 |           // accessing the current global UI state; the parent will not
136 |           // necessarily always pass down child state.
137 |           const ui = getUIState(this.context.store.getState());
138 |           if (ui.getIn(this.uiPath) === undefined && opts.state) {
139 |             const state = this.getDefaultUIState(opts.state, nextProps);
140 |             this.props.setDefaultUI(this.uiPath, state);
141 |           }
142 |         }
143 | 
144 |         // Get default state by evaluating any functions passed in to the state
145 |         // opts.
146 |         // This is also used within componentWilLReceiveProps and so props
147 |         // also needs to be passed in
148 |         getDefaultUIState(uiState, props = this.props) {
149 |           const globalState = this.context.store.getState();
150 |           let state = { ...uiState };
151 |           Object.keys(state).forEach(k => {
152 |             if (typeof(state[k]) === 'function') {
153 |               state[k] = state[k](this.props, globalState);
154 |             }
155 |           });
156 |           return state;
157 |         }
158 | 
159 |         // Blow away all UI state for this component key by setting the
160 |         // state for this key to undefined. This will get reset to the
161 |         // default state in componentWillMount in the future.
162 |         //
163 |         // We use requestAnimationFrame because `@ui()` can be combined with
164 |         // with `@connect()`; if the connect decorator uses selectors based on
165 |         // UI state (such as live filtering) the connect decorator will receive
166 |         // `undefined` as `this.props.ui` before unmounting.
167 |         //
168 |         // requestAnimationFrame avoids this.
169 |         componentWillUnmount() {
170 |           if (opts.persist !== true) {
171 |             if (window && window.requestAnimationFrame) {
172 |               window.requestAnimationFrame(() => this.props.unmountUI(this.uiPath));
173 |             } else {
174 |               this.props.unmountUI(this.uiPath);
175 |             }
176 |           }
177 |         }
178 | 
179 |         // Sets this.uiVars && this.uiPath.
180 |         //
181 |         // Merges this UI context's variables with any parent context's
182 |         // variables defined in uiVars.
183 |         getMergedContextVars(ctx = this.context) {
184 |           if (!this.uiVars || !this.uiPath) {
185 |             const uiPath = ctx.uiPath || [];
186 |             this.uiPath = uiPath.concat(this.key);
187 | 
188 |             // Keep trackof each UI variable and which path it should be set in
189 |             const state = opts.state || {};
190 |             this.uiVars = { ...ctx.uiVars } || {};
191 |             Object.keys(state).forEach(k => this.uiVars[k] = this.uiPath, this);
192 |           }
193 | 
194 |           return [this.uiVars, this.uiPath];
195 |         }
196 | 
197 |         // Construct a new context for all child UI components. We need to merge
198 |         // in the vars defined in opts.state to uiVars to explicitly state that
199 |         // this context is in charge of those variables.
200 |         //
201 |         // Pass the uiKey and partially applied updateUI function to all
202 |         // child components that are wrapped in a plain `@ui()` decorator
203 |         getChildContext() {
204 |           let [uiVars, uiPath] = this.getMergedContextVars();
205 | 
206 |           return {
207 |             uiKey: this.key,
208 |             uiVars,
209 |             uiPath,
210 | 
211 |             updateUI: ::this.updateUI,
212 |             resetUI: ::this.resetUI
213 |           };
214 |         }
215 | 
216 |         // Helper function to reset UI for the current context **and all child
217 |         // scopes**.
218 |         //
219 |         // This is the same as exiting scope in programming; all variables
220 |         // defined within the scope are reset.
221 |         resetUI() {
222 |           this.props.setDefaultUI(this.uiPath, this.getDefaultUIState(opts.state));
223 |           // TODO: Wipe all child contexts
224 |         }
225 | 
226 |         updateUI(name, value) {
227 |           // Get a list of all UI variables available to this context (which
228 |           // lists parent contexts) to see which key we need to set this in.
229 |           const [uiVars] = this.getMergedContextVars();
230 |           const uiVarPath = uiVars[name];
231 | 
232 |           if (typeof name === 'object' && value === undefined) {
233 |             // We're mass updating many UI variables. These may or may not be
234 |             // directly controlled by our context, so we delegate to the
235 |             // reducer which will deeply set each variable according to its
236 |             // uiPath (from uiVars).
237 |             //
238 |             // Doing this means we only trigger one store update.
239 |             this.props.massUpdateUI(this.uiVars, name);
240 |             return
241 |           }
242 | 
243 |           invariant(
244 |             uiVarPath,
245 |             `The '${name}' UI variable is not defined in the UI context in "` +
246 |             (WrappedComponent.displayName || WrappedComponent.name) + '" ' +
247 |             'or any parent UI context. Set this variable using the "state" ' +
248 |             'option in the @ui decorator before using it.'
249 |           );
250 | 
251 |           this.props.updateUI(uiVarPath, name, value);
252 |         }
253 | 
254 |         // Iterate through the list of contexts merging in UI variables from the
255 |         // UI store
256 |         mergeUIProps() {
257 |           // WARNING: React has a subtle componentWillMount bug which we're
258 |           // working around here!
259 |           //
260 |           // ## React bug
261 |           //
262 |           // On the first *ever* render of this component we set defaults in
263 |           // componentWillMount. This works; when `render()` is called the
264 |           // wrapped component has the default props within this.props.ui
265 |           //
266 |           // BUT.  Unmount, navigate away then return to this component.  When
267 |           // componentWillMount is called a *second* time, we call updateUI to
268 |           // set default props. **These aren't passed in to render() until the
269 |           // component is mounted a second time**. Even though it worked first
270 |           // time. And even though this is a new instance of the component.
271 |           //
272 |           // ## Workaround.
273 |           //
274 |           // Instead of relying on this.props.ui from our connector we call
275 |           // getState() in the store directly here. We guarantee that this will
276 |           // be the latest set of props, including default props set in
277 |           // componentWillMount.
278 |           //
279 |           // We still use @connect() to connect to the store and listen for
280 |           // changes in other cases.
281 |           const ui = getUIState(this.context.store.getState());
282 | 
283 |           return Object.keys(this.uiVars).reduce((props, k) => {
284 |             props[k] = ui.getIn(this.uiVars[k].concat(k));
285 |             return props;
286 |           }, {}) || {};
287 |         }
288 | 
289 |         render() {
290 |           return (
291 |             
298 |           );
299 |         }
300 |       }
301 |     );
302 |   }
303 | }
304 | 
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | /**
 4 |  * getUIState inspects redux' global state store and returns the UI state node.
 5 |  *
 6 |  * This checks to see whether state is an immutable map or a POJO.
 7 |  */
 8 | export const getUIState = (state) => {
 9 |   if (typeof state.get === 'function') {
10 |     return state.get('ui');
11 |   }
12 |   return state.ui;
13 | }
14 | 
--------------------------------------------------------------------------------
/test/action-reducer/reducer.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | import {
  4 |   reducer,
  5 |   reducerEnhancer,
  6 |   UPDATE_UI_STATE
  7 | } from '../../src/action-reducer.js';
  8 | 
  9 | import { assert } from 'chai';
 10 | import { is, Map } from 'immutable';
 11 | import { Provider } from 'react-redux';
 12 | import { createStore, combineReducers } from 'redux';
 13 | import { defaultState } from '../../src/action-reducer.js';
 14 | 
 15 | const customReducer = (state, action) => {
 16 |   if (action.type === 'CUSTOM_ACTION_TYPE') {
 17 |     return state.set('isHooked', true);
 18 |   }
 19 |   return state;
 20 | }
 21 | const enhancedReducer = reducerEnhancer(customReducer);
 22 | 
 23 | describe('reducerEnhancer', () => {
 24 |   let enhancedStore;
 25 | 
 26 |   beforeEach( () => {
 27 |     enhancedStore = createStore(combineReducers({ ui: enhancedReducer }));
 28 |   });
 29 | 
 30 |   it('delegates to the default reducer', () => {
 31 |     assert.isTrue(is(enhancedStore.getState().ui, defaultState));
 32 | 
 33 |     enhancedStore.dispatch({
 34 |       type: UPDATE_UI_STATE,
 35 |       payload: {
 36 |         key: 'a',
 37 |         name: 'foo',
 38 |         value: 'bar'
 39 |       }
 40 |     });
 41 | 
 42 |     assert.isTrue(
 43 |       is(
 44 |         enhancedStore.getState().ui,
 45 |         new Map({
 46 |           __reducers: new Map(),
 47 |           a: new Map({ foo: 'bar' })
 48 |         })
 49 |       )
 50 |     );
 51 |   });
 52 | 
 53 |   it('intercepts custom actions', () => {
 54 |     assert.isTrue(is(enhancedStore.getState().ui, defaultState));
 55 | 
 56 |     enhancedStore.dispatch({
 57 |       type: 'CUSTOM_ACTION_TYPE',
 58 |       payload: {
 59 |         foo: 'bar'
 60 |       }
 61 |     });
 62 |     assert.isTrue(
 63 |       is(
 64 |         enhancedStore.getState().ui,
 65 |         new Map({
 66 |           __reducers: new Map(),
 67 |           isHooked: true
 68 |         })
 69 |       )
 70 |     );
 71 |   });
 72 | 
 73 |   it('update ui state by updater', () => {
 74 |     assert.isTrue(is(enhancedStore.getState().ui, defaultState));
 75 | 
 76 |     enhancedStore.dispatch({
 77 |       type: UPDATE_UI_STATE,
 78 |       payload: {
 79 |         key: 'foo',
 80 |         name: 'bar',
 81 |         value: 'baz'
 82 |       }
 83 |     });
 84 | 
 85 |     enhancedStore.dispatch({
 86 |       type: UPDATE_UI_STATE,
 87 |       payload: {
 88 |         key: 'foo',
 89 |         name: 'bar',
 90 |         value: baz => baz.toUpperCase()
 91 |       }
 92 |     });
 93 | 
 94 |     assert.isTrue(
 95 |       is(
 96 |         enhancedStore.getState().ui,
 97 |         new Map({
 98 |           __reducers: new Map(),
 99 |           foo: new Map({ bar: 'BAZ' })
100 |         })
101 |       )
102 |     );
103 |   });
104 | });
105 | 
--------------------------------------------------------------------------------
/test/setup.js:
--------------------------------------------------------------------------------
1 | import { jsdom } from 'jsdom'
2 | 
3 | global.document = jsdom('')
4 | global.window = document.defaultView
5 | global.navigator = global.window.navigator
6 | 
--------------------------------------------------------------------------------
/test/ui/context.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | import { assert } from 'chai';
  4 | import React, { Component } from 'react';
  5 | import ReactTestUtils from 'react-dom/test-utils';
  6 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
  7 | 
  8 | import ui, { reducer } from '../../src';
  9 | import { render, renderAndFind } from '../utils/render.js';
 10 | 
 11 | describe('UI state context', () => {
 12 | 
 13 |   describe('single component tree', () => {
 14 |     class Test extends Component {
 15 |       updateName() { this.props.updateUI('name', 'test'); }
 16 |       massUpdate() {
 17 |         this.props.updateUI({
 18 |           name: 'test',
 19 |           isValid: false
 20 |         });
 21 |       }
 22 |       render() { return 
Hi
; }
 23 |     }
 24 |     const uiState = {
 25 |       name: 'parent',
 26 |       isValid: true
 27 |     };
 28 |     const UITest = ui({ state: uiState })(Test);
 29 | 
 30 |     it('component gets given expected props', () => {
 31 |       const c = renderAndFind(
, Test);
 32 |       assert(typeof c.props.updateUI === 'function', 'has updateUI');
 33 |       assert(typeof c.props.resetUI === 'function', 'has resetUI');
 34 |       assert(typeof c.props.uiKey === 'string', 'has uiKey');
 35 |       assert(shallowEqual(c.props.ui, uiState), 'has default state');
 36 |     });
 37 | 
 38 |     it('updates props using the single-update syntax', () => {
 39 |       const c = renderAndFind(
, Test);
 40 |       assert(c.props.ui.name === 'parent');
 41 |       c.updateName()
 42 |       assert(c.props.ui.name === 'test');
 43 |     });
 44 | 
 45 |     it('updates props using the mass-update syntax', () => {
 46 |       const c = renderAndFind(
, Test);
 47 |       assert(c.props.ui.name === 'parent');
 48 |       c.massUpdate()
 49 |       assert(c.props.ui.name === 'test');
 50 |       assert(c.props.ui.isValid === false);
 51 |     });
 52 |   });
 53 | 
 54 |   describe('single-level nested ui component tree', () => {
 55 |     const uiState = {
 56 |       name: 'parent'
 57 |     };
 58 |     class Parent extends Component {
 59 |       updateContext(to = 'parent') { this.props.updateUI('name', to); }
 60 |       render() { return 
{ this.props.children }
; }
 61 |     };
 62 |     const UIParent = ui({state: uiState})(Parent);
 63 | 
 64 |     class Child extends Component {
 65 |       updateParentContext(to = 'parent') { this.props.updateUI('name', to); }
 66 |       updateName() { this.props.updateUI('name', 'bar'); }
 67 |       updateOwnState() { this.props.updateUI('child', 'foo'); }
 68 |       render() { return 
Nested
; }
 69 |     };
 70 |     const UIChild = ui({})(Child);
 71 |     const UIChildWithOwnState = ui({ state: { child: true } })(Child);
 72 |     const UIChildWithOwnStateJSX = (
 73 |       
 74 |         
 75 |       
 76 |     );
 77 | 
 78 |     it('child component inherits parent context', () => {
 79 |       const c = renderAndFind(
, Child);
 80 |       assert(shallowEqual(c.props.ui, uiState), 'child inherits parent UI state context');
 81 |     });
 82 | 
 83 |     it('parent component only gets its own context', () => {
 84 |       const p = renderAndFind(UIChildWithOwnStateJSX, Parent);
 85 |       assert(shallowEqual(p.props.ui, uiState), 'parent only has its own context and not childrens');
 86 |     });
 87 | 
 88 |     it('child component updates parent variables', () => {
 89 |       const tree = render(
);
 90 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
 91 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
 92 | 
 93 |       assert(parent.props.ui.name === 'parent');
 94 |       assert(child.props.ui.name === 'parent');
 95 |       child.updateName();
 96 |       assert(parent.props.ui.name === 'bar');
 97 |       assert(child.props.ui.name === 'bar');
 98 |     });
 99 | 
100 |     it('child merges parent UI context with its own UI context', () => {
101 |       const child = renderAndFind(UIChildWithOwnStateJSX, Child);
102 |       const expectedState = {
103 |         name: 'parent',
104 |         child: true
105 |       };
106 |       assert(shallowEqual(child.props.ui, expectedState), 'child merges context');
107 |     });
108 | 
109 |     it('child updates own context separately from parent', () => {
110 |       const tree = render(UIChildWithOwnStateJSX);
111 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
112 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
113 |       child.updateOwnState();
114 |       assert(child.props.ui.child === 'foo', 'child updates own context');
115 |       assert(parent.props.ui.child === undefined, 'parent has no child state in its context');
116 |     });
117 | 
118 |     it('child updates parent context', () => {
119 |       const tree = render(UIChildWithOwnStateJSX);
120 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
121 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
122 | 
123 |       child.updateParentContext('foobar');
124 |       assert(parent.props.ui.name === 'foobar', 'parent updates context');
125 |       assert(child.props.ui.name === 'foobar', 'child updates context');
126 |     });
127 | 
128 |     it('parent updating context sends child new context and child receives updates', () => {
129 |       const tree = render(UIChildWithOwnStateJSX);
130 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
131 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
132 | 
133 |       parent.updateContext('what');
134 |       assert(parent.props.ui.name === 'what', 'parent updates context');
135 |       assert(child.props.ui.name === 'what', 'child updates context');
136 |     });
137 | 
138 |     describe('duplicating UI variable names across parent/child contexts', () => {
139 |       class Child extends Component {
140 |         updateChildContext(to = 'foo') { this.props.updateUI('name', to); }
141 |         render() { return 
 }
142 |       }
143 |       const UIChild = ui({ state: { name: 'child' } })(Child);
144 |       const UIChildJSX = (
);
145 | 
146 |       it('parent and child store state separately', () => {
147 |         const tree = render(UIChildJSX);
148 |         const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
149 |         const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
150 | 
151 |         assert(parent.props.ui.name === 'parent');
152 |         assert(child.props.ui.name === 'child');
153 |       });
154 | 
155 |       it('parent updates context separately from parent', () => {
156 |         const tree = render(UIChildJSX);
157 |         const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
158 |         const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
159 | 
160 |         parent.updateContext('foobar');
161 |         assert(parent.props.ui.name === 'foobar');
162 |         assert(child.props.ui.name === 'child');
163 |       });
164 | 
165 | 
166 |       it('child updates context separately from parent', () => {
167 |         const tree = render(UIChildJSX);
168 |         const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
169 |         const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
170 | 
171 |         child.updateChildContext('foobar');
172 |         assert(parent.props.ui.name === 'parent');
173 |         assert(child.props.ui.name === 'foobar');
174 |       });
175 |     });
176 | 
177 |   });
178 | 
179 |   describe('shared contexts', () => {
180 |     class Foo extends Component {
181 |       updateContext(to = 'misc') { this.props.updateUI('name', to); }
182 |       render = () => 
183 |     }
184 |     class Bar extends Component {
185 |       updateContext(to = 'misc') { this.props.updateUI('name', to); }
186 |       render = () => 
187 |     }
188 |     const adapter = ui({ key: 'a', state: { name: 'name' } });
189 |     const UIFoo = adapter(Foo);
190 |     const UIBar = adapter(Bar);
191 | 
192 |     it('components with the same key and nesting share the same context', () => {
193 |         const tree = render(
);
194 |         const a = ReactTestUtils.findRenderedComponentWithType(tree, Foo);
195 |         const b = ReactTestUtils.findRenderedComponentWithType(tree, Bar);
196 | 
197 |         assert(shallowEqual(a.props.ui, b.props.ui));
198 |         a.updateContext();
199 |         assert(a.props.ui.name === 'misc');
200 |         assert(shallowEqual(a.props.ui, b.props.ui));
201 |     });
202 | 
203 |   });
204 | 
205 | });
206 | 
--------------------------------------------------------------------------------
/test/ui/defaults.js:
--------------------------------------------------------------------------------
 1 | 
 2 | 'use strict';
 3 | 
 4 | import { assert } from 'chai';
 5 | import React, { Component } from 'react';
 6 | import ReactTestUtils from 'react-dom/test-utils';
 7 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
 8 | import { Map } from 'immutable';
 9 | 
10 | import ui, { reducer } from '../../src';
11 | import { render, renderAndFind } from '../utils/render.js';
12 | 
13 | describe('Default UI state variables', () => {
14 | 
15 |   describe('HOC is passed props and state to calculate defaults', () => {
16 |     // Set up closures which we can use to check that the uiState func is passed
17 |     // expected props.
18 |     let calcProps, calcState;
19 | 
20 |     class Test extends Component {
21 |       render() { return 
Hi
; }
22 |     }
23 |     const uiState = {
24 |       calculated: (props, state) => {
25 |         calcProps = props;
26 |         calcState = state;
27 |         return props.passedProp
28 |       },
29 |       isValid: true
30 |     };
31 |     const UITest = ui({ state: uiState })(Test);
32 | 
33 |     it('component gets given expected props', () => {
34 |       const c = renderAndFind(
, Test);
35 |       assert.equal(c.props.ui.calculated, 'foo');
36 |       assert.equal(calcProps.passedProp, 'foo');
37 |       assert.equal(typeof calcState.ui, typeof Map());
38 |     });
39 | 
40 |   });
41 | 
42 | });
43 | 
44 | 
--------------------------------------------------------------------------------
/test/ui/key.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import { assert } from 'chai';
 4 | import React, { Component } from 'react';
 5 | import ReactTestUtils from 'react-dom/test-utils';
 6 | 
 7 | import ui, { reducer } from '../../src';
 8 | import { render, renderAndFind } from '../utils/render.js';
 9 | 
10 | describe('key generation', () => {
11 | 
12 |   class Test extends Component {
13 |     render() { return 
Hi
; }
14 |   }
15 |   const testKey = 'testKey'
16 | 
17 |   const WrappedTestWithoutKey = ui({})(Test);
18 |   const WrappedTestWithKey = ui({key: testKey})(Test);
19 | 
20 |   describe('opts.key === undefined', () => {
21 |     it('assigns a random key to the component', () => {
22 |       const tree = render(
23 |         
24 |           
25 |           
26 |           
27 |         
28 |       );
29 |       const comps = ReactTestUtils
30 |         .scryRenderedComponentsWithType(tree, Test);
31 |       const { uiKey } = comps[0].props;
32 | 
33 |       // Check basic setup of the UI key within the first component
34 |       assert(uiKey !== '', 'uiKey is not empty');
35 |       assert(uiKey.substr(0, 'Test'.length) === 'Test', 'Key begins with component name');
36 |       assert(uiKey.length >= ('Test'.length + 5));
37 | 
38 |       // Ensure that all three components have unique IDs by creating a set
39 |       // of each key and checking the set's length
40 |       const uniqs = Array.from(new Set(comps.map(c => c.props.uiKey)));
41 |       assert(uniqs.length === 3, 'Two unique keys are specified');
42 |     });
43 |   });
44 | 
45 |   describe('opts.key !== undefined', () => {
46 |     it('uses the specified key', () => {
47 |       const tree = render(
);
48 |       const c = ReactTestUtils.findRenderedComponentWithType(tree, Test);
49 |       const { uiKey } = c.props;
50 | 
51 |       // Check basic setup of the UI key within the first component
52 |       assert(uiKey === testKey, 'uiKey matches opts.key');
53 |     });
54 |   });
55 | 
56 |   describe('props.uiPath', () => {
57 |     it('exposes uiPath', () => {
58 |       const c = renderAndFind(
, Test);
59 |       const { uiPath } = c.props;
60 | 
61 |       // Check basic setup of the UI key within the first component
62 |       assert.equal(uiPath, testKey);
63 |     });
64 |   });
65 | 
66 | });
67 | 
--------------------------------------------------------------------------------
/test/ui/opts.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import { assert } from 'chai';
 4 | import React, { Component } from 'react';
 5 | import ReactTestUtils from 'react-dom/test-utils';
 6 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
 7 | 
 8 | import ui, { reducer } from '../../src';
 9 | import { render, renderAndFind } from '../utils/render.js';
10 | 
11 | describe('@connect options', () => {
12 |   class Child extends Component {
13 |     render = () => 
Child
14 |   }
15 | 
16 |   it('allows you to pass mergeProps into connect', () => {
17 |     // Poor mans spying
18 |     let called = false;
19 |     const mergeProps = (stateProps, dispatchProps, ownProps) => {
20 |       called = true;
21 |       return Object.assign({}, ownProps, stateProps, dispatchProps);
22 |     }
23 | 
24 |     const UIChild = ui({
25 |       state: { name: 'child' },
26 |       mergeProps: mergeProps
27 |     })(Child);
28 | 
29 |     const c = renderAndFind(
, Child);
30 |     assert.isTrue(called);
31 |   });
32 | 
33 | 
34 |   it('allows you to pass options into connect', () => {
35 |     const WithRef = ui({
36 |       state: { name: 'child' },
37 |       options: { withRef: true }
38 |     })(Child);
39 |     let wrapped = renderAndFind(
, WithRef);
40 |     assert.isDefined(wrapped.getWrappedInstance());
41 | 
42 |     let WithoutRef = ui({
43 |       state: { name: 'child' },
44 |       options: { withRef: false }
45 |     })(Child);
46 |     wrapped = renderAndFind(
, WithoutRef);
47 |     assert.throws(() => wrapped.getWrappedInstance(), 'To access the wrapped instance, you need to specify { withRef: true } in the options argument of the connect() call.');
48 |   });
49 | });
50 | 
--------------------------------------------------------------------------------
/test/ui/reducer.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | import { assert } from 'chai';
  4 | 
  5 | import React, { Component } from 'react';
  6 | import ReactDOM from 'react-dom';
  7 | import { is, Map } from 'immutable';
  8 | import ReactTestUtils from 'react-dom/test-utils';
  9 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
 10 | 
 11 | import ui, { reducer } from '../../src';
 12 | import { store, render, renderAndFind } from '../utils/render.js';
 13 | 
 14 | describe('with a custom reducer', () => {
 15 | 
 16 |   class Parent extends Component {
 17 |     render = () => 
{ this.props.children }
 18 |   }
 19 | 
 20 |   // Create a UI component that listens to the 'CUSTOM' type and updates
 21 |   // UI variables
 22 |   let parentReducer = (state, action) => {
 23 |     if (action.type === 'CUSTOM') {
 24 |       return state.set('name', 'parentOverride');
 25 |     }
 26 |     return state;
 27 |   };
 28 |   const UIParent = ui({
 29 |     key: 'parent',
 30 |     state: {
 31 |       name: 'parent'
 32 |     },
 33 |     reducer: parentReducer
 34 |   })(Parent);
 35 | 
 36 |   it('adds a custom reducer on mount and removes at unmount', () => {
 37 |     const c = renderAndFind(
, Parent);
 38 | 
 39 |     let reducers = store.getState().ui.get('__reducers');
 40 |     assert.equal(reducers.size, 1);
 41 |     assert.equal(reducers.get('parent').func, parentReducer);
 42 | 
 43 |     // Unmount and this should be gone
 44 |     ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(c).parentNode);
 45 |     reducers = store.getState().ui.get('__reducers');
 46 |     assert.equal(reducers.size, 0);
 47 |   });
 48 | 
 49 |   it('updates props as expected', () => {
 50 |     const c = renderAndFind(
, Parent);
 51 |     assert.equal(c.props.ui.name, 'parent');
 52 |     c.props.updateUI('name', 'foo');
 53 |     assert.equal(c.props.ui.name, 'foo');
 54 | 
 55 |     ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(c).parentNode);
 56 |   });
 57 | 
 58 |   it('responds to actions using a custom reducer', () => {
 59 |     const c = renderAndFind(
, Parent);
 60 |     store.dispatch({ type: 'CUSTOM' });
 61 |     assert.equal(c.props.ui.name, 'parentOverride');
 62 | 
 63 |     ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(c).parentNode);
 64 |   });
 65 | 
 66 |   describe('with children', () => {
 67 |     // This will be set when the reducer is called, allowing us to test what
 68 |     // state the reducer is given.
 69 |     //
 70 |     // We should only be given state for our current component.
 71 |     let reducerState;
 72 | 
 73 |     // Create a UI component that listens to the 'CUSTOM' type and updates
 74 |     // UI variables
 75 |     let childReducer = (state = {}, action) => {
 76 |       reducerState = state;
 77 |       if (action.type === 'CUSTOM') {
 78 |         return state.set('foo', 'childOverride');
 79 |       }
 80 |       return state;
 81 |     };
 82 |     class Child extends Component {
 83 |       render = () => 
child
 84 |     }
 85 |     const UIChild = ui({
 86 |       key: 'child',
 87 |       state: { foo: 'bar' },
 88 |       reducer: childReducer
 89 |     })(Child);
 90 | 
 91 |     it('only gets given the UI state for the current component', () => {
 92 |       const tree = render(
, Parent);
 93 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
 94 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
 95 | 
 96 |       store.dispatch({ type: 'CUSTOM' });
 97 |       // The reducerState should equal the default reducer state for our child
 98 |       // component
 99 |       assert.isTrue(is(reducerState, new Map({ foo: 'bar' })));
100 |       assert.equal(parent.props.ui.name, 'parentOverride');
101 |       assert.equal(child.props.ui.foo, 'childOverride');
102 | 
103 |       ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(parent).parentNode);
104 |     });
105 |   });
106 | 
107 | });
108 | 
--------------------------------------------------------------------------------
/test/ui/reset.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import { assert } from 'chai';
 4 | import React, { Component } from 'react';
 5 | import ReactTestUtils from 'react-dom/test-utils';
 6 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
 7 | 
 8 | import ui, { reducer } from '../../src';
 9 | import { render, renderAndFind } from '../utils/render.js';
10 | 
11 | describe('resetting UI state', () => {
12 |   class Parent extends Component {
13 |     render = () => (
{ this.props.children }
)
14 |   }
15 | 
16 |   class Child extends Component {
17 |     render = () => 
Child
18 |   }
19 | 
20 |   const UIParent = ui({ state: { name: 'parent' } })(Parent);
21 |   const UIChild = ui({ state: { name: 'child' } })(Child);
22 | 
23 |   it('resetting a UI component with no children resets its own UI state', () => {
24 |     const child = renderAndFind(
, Child);
25 | 
26 |     child.props.updateUI({ name: 'foobar' });
27 |     assert(child.props.ui.name === 'foobar');
28 |     child.props.resetUI();
29 |     assert(child.props.ui.name === 'child');
30 |   });
31 | 
32 |   it('resetting a parent UI resets its own AND child contexts', () => {
33 |       const tree = render(
);
34 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
35 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
36 | 
37 |       child.props.updateUI({ name: 'b' });
38 |       parent.props.updateUI({ name: 'a' });
39 |       // Ensure state is updated
40 |       assert(child.props.ui.name === 'b');
41 |       // Resetting a parent should also reset all children
42 |       parent.props.resetUI();
43 |       assert(child.props.ui.name === 'child');
44 |       assert(parent.props.ui.name === 'parent');
45 |   });
46 | 
47 |   it('resetting a child UI resets only its own context', () => {
48 |       const tree = render(
);
49 |       const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
50 |       const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
51 | 
52 |       child.props.updateUI({ name: 'b' });
53 |       parent.props.updateUI({ name: 'a' });
54 |       // Ensure state is updated
55 |       assert(child.props.ui.name === 'b');
56 |       // Child should only reset itself to child; parent should stay changed
57 |       child.props.resetUI();
58 |       assert(child.props.ui.name === 'child');
59 |       assert(parent.props.ui.name === 'a');
60 |   });
61 | 
62 |   it('evaluates functions within default state correctly', () => {
63 |     const FunctionalUIChild = ui({
64 |       state: {
65 |         evaluated: (props) => props.value
66 |       }
67 |     })(Child);
68 | 
69 |     const child = renderAndFind(
, Child);
70 |     assert.equal(child.props.ui.evaluated, 'foo');
71 |     child.props.updateUI({ evaluated: 'next' });
72 |     assert.equal(child.props.ui.evaluated, 'next');
73 |     child.props.resetUI();
74 |     assert.equal(child.props.ui.evaluated, 'foo');
75 |   });
76 | 
77 |   it('calling resetUI from a parent component with a child that has evaluated state works', () => {
78 |     const FunctionalUIChild = ui({
79 |       state: {
80 |         evaluated: (props) => props.value
81 |       }
82 |     })(Child);
83 | 
84 |     const tree = render(
);
85 |     const parent = ReactTestUtils.findRenderedComponentWithType(tree, Parent);
86 |     const child = ReactTestUtils.findRenderedComponentWithType(tree, Child);
87 | 
88 |     assert.equal(child.props.ui.evaluated, 'foo');
89 |     child.props.updateUI({ evaluated: 'next' });
90 |     assert.equal(child.props.ui.evaluated, 'next');
91 |     parent.props.resetUI();
92 |     assert.equal(child.props.ui.evaluated, 'foo');
93 |   });
94 | 
95 | });
96 | 
--------------------------------------------------------------------------------
/test/ui/validation.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import { assert } from 'chai';
 4 | import React, { Component } from 'react';
 5 | import ReactTestUtils from 'react-dom/test-utils';
 6 | import shallowEqual from 'react-redux/lib/utils/shallowEqual';
 7 | 
 8 | import ui, { reducer } from '../../src';
 9 | import { render, renderAndFind } from '../utils/render.js';
10 | 
11 | describe('Prop validation', () => {
12 |   class Child extends Component {
13 |     render = () => 
Child
14 |   }
15 |   const UIChild = ui({ state: { name: 'child' } })(Child);
16 | 
17 |   it('only allows you to set defined variables in a single-level tree', () => {
18 |     const child = renderAndFind(
, Child);
19 |     assert.throws(() => child.props.updateUI({ foo: 1 }));
20 |   });
21 | });
22 | 
23 | 
--------------------------------------------------------------------------------
/test/utils/render.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import React from 'react';
 4 | import { Provider } from 'react-redux';
 5 | import { createStore, combineReducers } from 'redux';
 6 | import ui, { reducer } from '../../src';
 7 | import ReactTestUtils from 'react-dom/test-utils';
 8 | 
 9 | const store = createStore(combineReducers({ ui: reducer }));
10 | 
11 | /**
12 |  * Wrap given JSX with a provider contianing a store with the UI reducer
13 |  */
14 | const wrapWithProvider = (jsx) => (
15 |   
16 |     { jsx }
17 |   
18 | );
19 | 
20 | const render = (jsx) => {
21 |   return ReactTestUtils.renderIntoDocument(
22 |     wrapWithProvider(jsx)
23 |   );
24 | }
25 | 
26 | const renderAndFind = (jsx, type = null) => {
27 |   if (type === undefined) {
28 |     type = jsx;
29 |     jsx = 
30 |   }
31 |   const tree = render(jsx);
32 |   return ReactTestUtils.findRenderedComponentWithType(tree, type);
33 | }
34 | 
35 | export {
36 |   store,
37 |   wrapWithProvider,
38 |   render,
39 |   renderAndFind
40 | }
41 | 
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
   1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
   2 | # yarn lockfile v1
   3 | 
   4 | 
   5 | abab@^1.0.0:
   6 |   version "1.0.3"
   7 |   resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
   8 | 
   9 | abbrev@1:
  10 |   version "1.1.0"
  11 |   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
  12 | 
  13 | acorn-globals@^1.0.4:
  14 |   version "1.0.9"
  15 |   resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf"
  16 |   dependencies:
  17 |     acorn "^2.1.0"
  18 | 
  19 | acorn@^2.1.0, acorn@^2.4.0:
  20 |   version "2.7.0"
  21 |   resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7"
  22 | 
  23 | ajv@^4.9.1:
  24 |   version "4.11.8"
  25 |   resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
  26 |   dependencies:
  27 |     co "^4.6.0"
  28 |     json-stable-stringify "^1.0.1"
  29 | 
  30 | amdefine@>=0.0.4:
  31 |   version "1.0.1"
  32 |   resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
  33 | 
  34 | ansi-regex@^2.0.0:
  35 |   version "2.1.1"
  36 |   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
  37 | 
  38 | ansi-styles@^2.1.0:
  39 |   version "2.2.1"
  40 |   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
  41 | 
  42 | anymatch@^1.3.0:
  43 |   version "1.3.0"
  44 |   resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
  45 |   dependencies:
  46 |     arrify "^1.0.0"
  47 |     micromatch "^2.1.5"
  48 | 
  49 | aproba@^1.0.3:
  50 |   version "1.1.1"
  51 |   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab"
  52 | 
  53 | are-we-there-yet@~1.1.2:
  54 |   version "1.1.4"
  55 |   resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
  56 |   dependencies:
  57 |     delegates "^1.0.0"
  58 |     readable-stream "^2.0.6"
  59 | 
  60 | arr-diff@^2.0.0:
  61 |   version "2.0.0"
  62 |   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
  63 |   dependencies:
  64 |     arr-flatten "^1.0.1"
  65 | 
  66 | arr-flatten@^1.0.1:
  67 |   version "1.0.3"
  68 |   resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1"
  69 | 
  70 | array-find-index@^1.0.1:
  71 |   version "1.0.2"
  72 |   resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
  73 | 
  74 | array-uniq@^1.0.0:
  75 |   version "1.0.3"
  76 |   resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
  77 | 
  78 | array-unique@^0.2.1:
  79 |   version "0.2.1"
  80 |   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
  81 | 
  82 | arrify@^1.0.0:
  83 |   version "1.0.1"
  84 |   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
  85 | 
  86 | asap@~2.0.3:
  87 |   version "2.0.5"
  88 |   resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
  89 | 
  90 | asn1@~0.2.3:
  91 |   version "0.2.3"
  92 |   resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
  93 | 
  94 | assert-plus@1.0.0, assert-plus@^1.0.0:
  95 |   version "1.0.0"
  96 |   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
  97 | 
  98 | assert-plus@^0.2.0:
  99 |   version "0.2.0"
 100 |   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
 101 | 
 102 | assertion-error@^1.0.1:
 103 |   version "1.0.2"
 104 |   resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c"
 105 | 
 106 | async-each@^1.0.0:
 107 |   version "1.0.1"
 108 |   resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
 109 | 
 110 | asynckit@^0.4.0:
 111 |   version "0.4.0"
 112 |   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 113 | 
 114 | aws-sign2@~0.6.0:
 115 |   version "0.6.0"
 116 |   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
 117 | 
 118 | aws4@^1.2.1:
 119 |   version "1.6.0"
 120 |   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
 121 | 
 122 | babel-cli@6.5.1:
 123 |   version "6.5.1"
 124 |   resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.5.1.tgz#446195f282320bc8b570d5d94757eead42533b4f"
 125 |   dependencies:
 126 |     babel-core "^6.5.1"
 127 |     babel-polyfill "^6.3.13"
 128 |     babel-register "^6.5.1"
 129 |     babel-runtime "^5.0.0"
 130 |     bin-version-check "^2.1.0"
 131 |     chalk "1.1.1"
 132 |     commander "^2.8.1"
 133 |     convert-source-map "^1.1.0"
 134 |     fs-readdir-recursive "^0.1.0"
 135 |     glob "^5.0.5"
 136 |     lodash "^3.2.0"
 137 |     log-symbols "^1.0.2"
 138 |     output-file-sync "^1.1.0"
 139 |     path-exists "^1.0.0"
 140 |     path-is-absolute "^1.0.0"
 141 |     request "^2.65.0"
 142 |     slash "^1.0.0"
 143 |     source-map "^0.5.0"
 144 |     v8flags "^2.0.10"
 145 |   optionalDependencies:
 146 |     chokidar "^1.0.0"
 147 | 
 148 | babel-code-frame@^6.22.0:
 149 |   version "6.22.0"
 150 |   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
 151 |   dependencies:
 152 |     chalk "^1.1.0"
 153 |     esutils "^2.0.2"
 154 |     js-tokens "^3.0.0"
 155 | 
 156 | babel-core@^6.24.1, babel-core@^6.5.1:
 157 |   version "6.24.1"
 158 |   resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83"
 159 |   dependencies:
 160 |     babel-code-frame "^6.22.0"
 161 |     babel-generator "^6.24.1"
 162 |     babel-helpers "^6.24.1"
 163 |     babel-messages "^6.23.0"
 164 |     babel-register "^6.24.1"
 165 |     babel-runtime "^6.22.0"
 166 |     babel-template "^6.24.1"
 167 |     babel-traverse "^6.24.1"
 168 |     babel-types "^6.24.1"
 169 |     babylon "^6.11.0"
 170 |     convert-source-map "^1.1.0"
 171 |     debug "^2.1.1"
 172 |     json5 "^0.5.0"
 173 |     lodash "^4.2.0"
 174 |     minimatch "^3.0.2"
 175 |     path-is-absolute "^1.0.0"
 176 |     private "^0.1.6"
 177 |     slash "^1.0.0"
 178 |     source-map "^0.5.0"
 179 | 
 180 | babel-generator@^6.24.1:
 181 |   version "6.24.1"
 182 |   resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
 183 |   dependencies:
 184 |     babel-messages "^6.23.0"
 185 |     babel-runtime "^6.22.0"
 186 |     babel-types "^6.24.1"
 187 |     detect-indent "^4.0.0"
 188 |     jsesc "^1.3.0"
 189 |     lodash "^4.2.0"
 190 |     source-map "^0.5.0"
 191 |     trim-right "^1.0.1"
 192 | 
 193 | babel-helper-bindify-decorators@^6.24.1:
 194 |   version "6.24.1"
 195 |   resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
 196 |   dependencies:
 197 |     babel-runtime "^6.22.0"
 198 |     babel-traverse "^6.24.1"
 199 |     babel-types "^6.24.1"
 200 | 
 201 | babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
 202 |   version "6.24.1"
 203 |   resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
 204 |   dependencies:
 205 |     babel-helper-explode-assignable-expression "^6.24.1"
 206 |     babel-runtime "^6.22.0"
 207 |     babel-types "^6.24.1"
 208 | 
 209 | babel-helper-builder-react-jsx@^6.24.1:
 210 |   version "6.24.1"
 211 |   resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz#0ad7917e33c8d751e646daca4e77cc19377d2cbc"
 212 |   dependencies:
 213 |     babel-runtime "^6.22.0"
 214 |     babel-types "^6.24.1"
 215 |     esutils "^2.0.0"
 216 | 
 217 | babel-helper-call-delegate@^6.24.1:
 218 |   version "6.24.1"
 219 |   resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
 220 |   dependencies:
 221 |     babel-helper-hoist-variables "^6.24.1"
 222 |     babel-runtime "^6.22.0"
 223 |     babel-traverse "^6.24.1"
 224 |     babel-types "^6.24.1"
 225 | 
 226 | babel-helper-define-map@^6.24.1:
 227 |   version "6.24.1"
 228 |   resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080"
 229 |   dependencies:
 230 |     babel-helper-function-name "^6.24.1"
 231 |     babel-runtime "^6.22.0"
 232 |     babel-types "^6.24.1"
 233 |     lodash "^4.2.0"
 234 | 
 235 | babel-helper-explode-assignable-expression@^6.24.1:
 236 |   version "6.24.1"
 237 |   resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
 238 |   dependencies:
 239 |     babel-runtime "^6.22.0"
 240 |     babel-traverse "^6.24.1"
 241 |     babel-types "^6.24.1"
 242 | 
 243 | babel-helper-explode-class@^6.24.1:
 244 |   version "6.24.1"
 245 |   resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
 246 |   dependencies:
 247 |     babel-helper-bindify-decorators "^6.24.1"
 248 |     babel-runtime "^6.22.0"
 249 |     babel-traverse "^6.24.1"
 250 |     babel-types "^6.24.1"
 251 | 
 252 | babel-helper-function-name@^6.24.1:
 253 |   version "6.24.1"
 254 |   resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
 255 |   dependencies:
 256 |     babel-helper-get-function-arity "^6.24.1"
 257 |     babel-runtime "^6.22.0"
 258 |     babel-template "^6.24.1"
 259 |     babel-traverse "^6.24.1"
 260 |     babel-types "^6.24.1"
 261 | 
 262 | babel-helper-get-function-arity@^6.24.1:
 263 |   version "6.24.1"
 264 |   resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
 265 |   dependencies:
 266 |     babel-runtime "^6.22.0"
 267 |     babel-types "^6.24.1"
 268 | 
 269 | babel-helper-hoist-variables@^6.24.1:
 270 |   version "6.24.1"
 271 |   resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
 272 |   dependencies:
 273 |     babel-runtime "^6.22.0"
 274 |     babel-types "^6.24.1"
 275 | 
 276 | babel-helper-optimise-call-expression@^6.24.1:
 277 |   version "6.24.1"
 278 |   resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
 279 |   dependencies:
 280 |     babel-runtime "^6.22.0"
 281 |     babel-types "^6.24.1"
 282 | 
 283 | babel-helper-regex@^6.24.1:
 284 |   version "6.24.1"
 285 |   resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8"
 286 |   dependencies:
 287 |     babel-runtime "^6.22.0"
 288 |     babel-types "^6.24.1"
 289 |     lodash "^4.2.0"
 290 | 
 291 | babel-helper-remap-async-to-generator@^6.24.1:
 292 |   version "6.24.1"
 293 |   resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
 294 |   dependencies:
 295 |     babel-helper-function-name "^6.24.1"
 296 |     babel-runtime "^6.22.0"
 297 |     babel-template "^6.24.1"
 298 |     babel-traverse "^6.24.1"
 299 |     babel-types "^6.24.1"
 300 | 
 301 | babel-helper-replace-supers@^6.24.1:
 302 |   version "6.24.1"
 303 |   resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
 304 |   dependencies:
 305 |     babel-helper-optimise-call-expression "^6.24.1"
 306 |     babel-messages "^6.23.0"
 307 |     babel-runtime "^6.22.0"
 308 |     babel-template "^6.24.1"
 309 |     babel-traverse "^6.24.1"
 310 |     babel-types "^6.24.1"
 311 | 
 312 | babel-helpers@^6.24.1:
 313 |   version "6.24.1"
 314 |   resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
 315 |   dependencies:
 316 |     babel-runtime "^6.22.0"
 317 |     babel-template "^6.24.1"
 318 | 
 319 | babel-messages@^6.23.0:
 320 |   version "6.23.0"
 321 |   resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
 322 |   dependencies:
 323 |     babel-runtime "^6.22.0"
 324 | 
 325 | babel-plugin-check-es2015-constants@^6.22.0:
 326 |   version "6.22.0"
 327 |   resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
 328 |   dependencies:
 329 |     babel-runtime "^6.22.0"
 330 | 
 331 | babel-plugin-syntax-async-functions@^6.8.0:
 332 |   version "6.13.0"
 333 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
 334 | 
 335 | babel-plugin-syntax-async-generators@^6.5.0:
 336 |   version "6.13.0"
 337 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
 338 | 
 339 | babel-plugin-syntax-class-constructor-call@^6.18.0:
 340 |   version "6.18.0"
 341 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416"
 342 | 
 343 | babel-plugin-syntax-class-properties@^6.8.0:
 344 |   version "6.13.0"
 345 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
 346 | 
 347 | babel-plugin-syntax-decorators@^6.1.18, babel-plugin-syntax-decorators@^6.13.0:
 348 |   version "6.13.0"
 349 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
 350 | 
 351 | babel-plugin-syntax-do-expressions@^6.8.0:
 352 |   version "6.13.0"
 353 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d"
 354 | 
 355 | babel-plugin-syntax-dynamic-import@^6.18.0:
 356 |   version "6.18.0"
 357 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
 358 | 
 359 | babel-plugin-syntax-exponentiation-operator@^6.8.0:
 360 |   version "6.13.0"
 361 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
 362 | 
 363 | babel-plugin-syntax-export-extensions@^6.8.0:
 364 |   version "6.13.0"
 365 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721"
 366 | 
 367 | babel-plugin-syntax-flow@^6.18.0:
 368 |   version "6.18.0"
 369 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
 370 | 
 371 | babel-plugin-syntax-function-bind@^6.8.0:
 372 |   version "6.13.0"
 373 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46"
 374 | 
 375 | babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
 376 |   version "6.18.0"
 377 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
 378 | 
 379 | babel-plugin-syntax-object-rest-spread@^6.8.0:
 380 |   version "6.13.0"
 381 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
 382 | 
 383 | babel-plugin-syntax-trailing-function-commas@^6.22.0:
 384 |   version "6.22.0"
 385 |   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
 386 | 
 387 | babel-plugin-transform-async-generator-functions@^6.24.1:
 388 |   version "6.24.1"
 389 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
 390 |   dependencies:
 391 |     babel-helper-remap-async-to-generator "^6.24.1"
 392 |     babel-plugin-syntax-async-generators "^6.5.0"
 393 |     babel-runtime "^6.22.0"
 394 | 
 395 | babel-plugin-transform-async-to-generator@^6.24.1:
 396 |   version "6.24.1"
 397 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
 398 |   dependencies:
 399 |     babel-helper-remap-async-to-generator "^6.24.1"
 400 |     babel-plugin-syntax-async-functions "^6.8.0"
 401 |     babel-runtime "^6.22.0"
 402 | 
 403 | babel-plugin-transform-class-constructor-call@^6.24.1:
 404 |   version "6.24.1"
 405 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9"
 406 |   dependencies:
 407 |     babel-plugin-syntax-class-constructor-call "^6.18.0"
 408 |     babel-runtime "^6.22.0"
 409 |     babel-template "^6.24.1"
 410 | 
 411 | babel-plugin-transform-class-properties@^6.24.1:
 412 |   version "6.24.1"
 413 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
 414 |   dependencies:
 415 |     babel-helper-function-name "^6.24.1"
 416 |     babel-plugin-syntax-class-properties "^6.8.0"
 417 |     babel-runtime "^6.22.0"
 418 |     babel-template "^6.24.1"
 419 | 
 420 | babel-plugin-transform-decorators-legacy@^1.3.4:
 421 |   version "1.3.4"
 422 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz#741b58f6c5bce9e6027e0882d9c994f04f366925"
 423 |   dependencies:
 424 |     babel-plugin-syntax-decorators "^6.1.18"
 425 |     babel-runtime "^6.2.0"
 426 |     babel-template "^6.3.0"
 427 | 
 428 | babel-plugin-transform-decorators@^6.24.1:
 429 |   version "6.24.1"
 430 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
 431 |   dependencies:
 432 |     babel-helper-explode-class "^6.24.1"
 433 |     babel-plugin-syntax-decorators "^6.13.0"
 434 |     babel-runtime "^6.22.0"
 435 |     babel-template "^6.24.1"
 436 |     babel-types "^6.24.1"
 437 | 
 438 | babel-plugin-transform-do-expressions@^6.22.0:
 439 |   version "6.22.0"
 440 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb"
 441 |   dependencies:
 442 |     babel-plugin-syntax-do-expressions "^6.8.0"
 443 |     babel-runtime "^6.22.0"
 444 | 
 445 | babel-plugin-transform-es2015-arrow-functions@^6.22.0:
 446 |   version "6.22.0"
 447 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
 448 |   dependencies:
 449 |     babel-runtime "^6.22.0"
 450 | 
 451 | babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
 452 |   version "6.22.0"
 453 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
 454 |   dependencies:
 455 |     babel-runtime "^6.22.0"
 456 | 
 457 | babel-plugin-transform-es2015-block-scoping@^6.24.1:
 458 |   version "6.24.1"
 459 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576"
 460 |   dependencies:
 461 |     babel-runtime "^6.22.0"
 462 |     babel-template "^6.24.1"
 463 |     babel-traverse "^6.24.1"
 464 |     babel-types "^6.24.1"
 465 |     lodash "^4.2.0"
 466 | 
 467 | babel-plugin-transform-es2015-classes@^6.24.1:
 468 |   version "6.24.1"
 469 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
 470 |   dependencies:
 471 |     babel-helper-define-map "^6.24.1"
 472 |     babel-helper-function-name "^6.24.1"
 473 |     babel-helper-optimise-call-expression "^6.24.1"
 474 |     babel-helper-replace-supers "^6.24.1"
 475 |     babel-messages "^6.23.0"
 476 |     babel-runtime "^6.22.0"
 477 |     babel-template "^6.24.1"
 478 |     babel-traverse "^6.24.1"
 479 |     babel-types "^6.24.1"
 480 | 
 481 | babel-plugin-transform-es2015-computed-properties@^6.24.1:
 482 |   version "6.24.1"
 483 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
 484 |   dependencies:
 485 |     babel-runtime "^6.22.0"
 486 |     babel-template "^6.24.1"
 487 | 
 488 | babel-plugin-transform-es2015-destructuring@^6.22.0:
 489 |   version "6.23.0"
 490 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
 491 |   dependencies:
 492 |     babel-runtime "^6.22.0"
 493 | 
 494 | babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
 495 |   version "6.24.1"
 496 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
 497 |   dependencies:
 498 |     babel-runtime "^6.22.0"
 499 |     babel-types "^6.24.1"
 500 | 
 501 | babel-plugin-transform-es2015-for-of@^6.22.0:
 502 |   version "6.23.0"
 503 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
 504 |   dependencies:
 505 |     babel-runtime "^6.22.0"
 506 | 
 507 | babel-plugin-transform-es2015-function-name@^6.24.1:
 508 |   version "6.24.1"
 509 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
 510 |   dependencies:
 511 |     babel-helper-function-name "^6.24.1"
 512 |     babel-runtime "^6.22.0"
 513 |     babel-types "^6.24.1"
 514 | 
 515 | babel-plugin-transform-es2015-literals@^6.22.0:
 516 |   version "6.22.0"
 517 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
 518 |   dependencies:
 519 |     babel-runtime "^6.22.0"
 520 | 
 521 | babel-plugin-transform-es2015-modules-amd@^6.24.1:
 522 |   version "6.24.1"
 523 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
 524 |   dependencies:
 525 |     babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
 526 |     babel-runtime "^6.22.0"
 527 |     babel-template "^6.24.1"
 528 | 
 529 | babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
 530 |   version "6.24.1"
 531 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe"
 532 |   dependencies:
 533 |     babel-plugin-transform-strict-mode "^6.24.1"
 534 |     babel-runtime "^6.22.0"
 535 |     babel-template "^6.24.1"
 536 |     babel-types "^6.24.1"
 537 | 
 538 | babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
 539 |   version "6.24.1"
 540 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
 541 |   dependencies:
 542 |     babel-helper-hoist-variables "^6.24.1"
 543 |     babel-runtime "^6.22.0"
 544 |     babel-template "^6.24.1"
 545 | 
 546 | babel-plugin-transform-es2015-modules-umd@^6.24.1:
 547 |   version "6.24.1"
 548 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
 549 |   dependencies:
 550 |     babel-plugin-transform-es2015-modules-amd "^6.24.1"
 551 |     babel-runtime "^6.22.0"
 552 |     babel-template "^6.24.1"
 553 | 
 554 | babel-plugin-transform-es2015-object-super@^6.24.1:
 555 |   version "6.24.1"
 556 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
 557 |   dependencies:
 558 |     babel-helper-replace-supers "^6.24.1"
 559 |     babel-runtime "^6.22.0"
 560 | 
 561 | babel-plugin-transform-es2015-parameters@^6.24.1:
 562 |   version "6.24.1"
 563 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
 564 |   dependencies:
 565 |     babel-helper-call-delegate "^6.24.1"
 566 |     babel-helper-get-function-arity "^6.24.1"
 567 |     babel-runtime "^6.22.0"
 568 |     babel-template "^6.24.1"
 569 |     babel-traverse "^6.24.1"
 570 |     babel-types "^6.24.1"
 571 | 
 572 | babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
 573 |   version "6.24.1"
 574 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
 575 |   dependencies:
 576 |     babel-runtime "^6.22.0"
 577 |     babel-types "^6.24.1"
 578 | 
 579 | babel-plugin-transform-es2015-spread@^6.22.0:
 580 |   version "6.22.0"
 581 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
 582 |   dependencies:
 583 |     babel-runtime "^6.22.0"
 584 | 
 585 | babel-plugin-transform-es2015-sticky-regex@^6.24.1:
 586 |   version "6.24.1"
 587 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
 588 |   dependencies:
 589 |     babel-helper-regex "^6.24.1"
 590 |     babel-runtime "^6.22.0"
 591 |     babel-types "^6.24.1"
 592 | 
 593 | babel-plugin-transform-es2015-template-literals@^6.22.0:
 594 |   version "6.22.0"
 595 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
 596 |   dependencies:
 597 |     babel-runtime "^6.22.0"
 598 | 
 599 | babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
 600 |   version "6.23.0"
 601 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
 602 |   dependencies:
 603 |     babel-runtime "^6.22.0"
 604 | 
 605 | babel-plugin-transform-es2015-unicode-regex@^6.24.1:
 606 |   version "6.24.1"
 607 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
 608 |   dependencies:
 609 |     babel-helper-regex "^6.24.1"
 610 |     babel-runtime "^6.22.0"
 611 |     regexpu-core "^2.0.0"
 612 | 
 613 | babel-plugin-transform-exponentiation-operator@^6.24.1:
 614 |   version "6.24.1"
 615 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
 616 |   dependencies:
 617 |     babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
 618 |     babel-plugin-syntax-exponentiation-operator "^6.8.0"
 619 |     babel-runtime "^6.22.0"
 620 | 
 621 | babel-plugin-transform-export-extensions@^6.22.0:
 622 |   version "6.22.0"
 623 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653"
 624 |   dependencies:
 625 |     babel-plugin-syntax-export-extensions "^6.8.0"
 626 |     babel-runtime "^6.22.0"
 627 | 
 628 | babel-plugin-transform-flow-strip-types@^6.22.0:
 629 |   version "6.22.0"
 630 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf"
 631 |   dependencies:
 632 |     babel-plugin-syntax-flow "^6.18.0"
 633 |     babel-runtime "^6.22.0"
 634 | 
 635 | babel-plugin-transform-function-bind@^6.22.0:
 636 |   version "6.22.0"
 637 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97"
 638 |   dependencies:
 639 |     babel-plugin-syntax-function-bind "^6.8.0"
 640 |     babel-runtime "^6.22.0"
 641 | 
 642 | babel-plugin-transform-object-rest-spread@^6.22.0:
 643 |   version "6.23.0"
 644 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
 645 |   dependencies:
 646 |     babel-plugin-syntax-object-rest-spread "^6.8.0"
 647 |     babel-runtime "^6.22.0"
 648 | 
 649 | babel-plugin-transform-react-display-name@^6.23.0:
 650 |   version "6.23.0"
 651 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37"
 652 |   dependencies:
 653 |     babel-runtime "^6.22.0"
 654 | 
 655 | babel-plugin-transform-react-jsx-self@^6.22.0:
 656 |   version "6.22.0"
 657 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e"
 658 |   dependencies:
 659 |     babel-plugin-syntax-jsx "^6.8.0"
 660 |     babel-runtime "^6.22.0"
 661 | 
 662 | babel-plugin-transform-react-jsx-source@^6.22.0:
 663 |   version "6.22.0"
 664 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6"
 665 |   dependencies:
 666 |     babel-plugin-syntax-jsx "^6.8.0"
 667 |     babel-runtime "^6.22.0"
 668 | 
 669 | babel-plugin-transform-react-jsx@^6.24.1:
 670 |   version "6.24.1"
 671 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3"
 672 |   dependencies:
 673 |     babel-helper-builder-react-jsx "^6.24.1"
 674 |     babel-plugin-syntax-jsx "^6.8.0"
 675 |     babel-runtime "^6.22.0"
 676 | 
 677 | babel-plugin-transform-regenerator@^6.24.1:
 678 |   version "6.24.1"
 679 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418"
 680 |   dependencies:
 681 |     regenerator-transform "0.9.11"
 682 | 
 683 | babel-plugin-transform-strict-mode@^6.24.1:
 684 |   version "6.24.1"
 685 |   resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
 686 |   dependencies:
 687 |     babel-runtime "^6.22.0"
 688 |     babel-types "^6.24.1"
 689 | 
 690 | babel-polyfill@^6.3.13:
 691 |   version "6.23.0"
 692 |   resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d"
 693 |   dependencies:
 694 |     babel-runtime "^6.22.0"
 695 |     core-js "^2.4.0"
 696 |     regenerator-runtime "^0.10.0"
 697 | 
 698 | babel-preset-es2015@^6.6.0:
 699 |   version "6.24.1"
 700 |   resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
 701 |   dependencies:
 702 |     babel-plugin-check-es2015-constants "^6.22.0"
 703 |     babel-plugin-transform-es2015-arrow-functions "^6.22.0"
 704 |     babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
 705 |     babel-plugin-transform-es2015-block-scoping "^6.24.1"
 706 |     babel-plugin-transform-es2015-classes "^6.24.1"
 707 |     babel-plugin-transform-es2015-computed-properties "^6.24.1"
 708 |     babel-plugin-transform-es2015-destructuring "^6.22.0"
 709 |     babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
 710 |     babel-plugin-transform-es2015-for-of "^6.22.0"
 711 |     babel-plugin-transform-es2015-function-name "^6.24.1"
 712 |     babel-plugin-transform-es2015-literals "^6.22.0"
 713 |     babel-plugin-transform-es2015-modules-amd "^6.24.1"
 714 |     babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
 715 |     babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
 716 |     babel-plugin-transform-es2015-modules-umd "^6.24.1"
 717 |     babel-plugin-transform-es2015-object-super "^6.24.1"
 718 |     babel-plugin-transform-es2015-parameters "^6.24.1"
 719 |     babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
 720 |     babel-plugin-transform-es2015-spread "^6.22.0"
 721 |     babel-plugin-transform-es2015-sticky-regex "^6.24.1"
 722 |     babel-plugin-transform-es2015-template-literals "^6.22.0"
 723 |     babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
 724 |     babel-plugin-transform-es2015-unicode-regex "^6.24.1"
 725 |     babel-plugin-transform-regenerator "^6.24.1"
 726 | 
 727 | babel-preset-flow@^6.23.0:
 728 |   version "6.23.0"
 729 |   resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d"
 730 |   dependencies:
 731 |     babel-plugin-transform-flow-strip-types "^6.22.0"
 732 | 
 733 | babel-preset-react@^6.5.0:
 734 |   version "6.24.1"
 735 |   resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380"
 736 |   dependencies:
 737 |     babel-plugin-syntax-jsx "^6.3.13"
 738 |     babel-plugin-transform-react-display-name "^6.23.0"
 739 |     babel-plugin-transform-react-jsx "^6.24.1"
 740 |     babel-plugin-transform-react-jsx-self "^6.22.0"
 741 |     babel-plugin-transform-react-jsx-source "^6.22.0"
 742 |     babel-preset-flow "^6.23.0"
 743 | 
 744 | babel-preset-stage-0@^6.5.0:
 745 |   version "6.24.1"
 746 |   resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz#5642d15042f91384d7e5af8bc88b1db95b039e6a"
 747 |   dependencies:
 748 |     babel-plugin-transform-do-expressions "^6.22.0"
 749 |     babel-plugin-transform-function-bind "^6.22.0"
 750 |     babel-preset-stage-1 "^6.24.1"
 751 | 
 752 | babel-preset-stage-1@^6.24.1:
 753 |   version "6.24.1"
 754 |   resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0"
 755 |   dependencies:
 756 |     babel-plugin-transform-class-constructor-call "^6.24.1"
 757 |     babel-plugin-transform-export-extensions "^6.22.0"
 758 |     babel-preset-stage-2 "^6.24.1"
 759 | 
 760 | babel-preset-stage-2@^6.24.1:
 761 |   version "6.24.1"
 762 |   resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
 763 |   dependencies:
 764 |     babel-plugin-syntax-dynamic-import "^6.18.0"
 765 |     babel-plugin-transform-class-properties "^6.24.1"
 766 |     babel-plugin-transform-decorators "^6.24.1"
 767 |     babel-preset-stage-3 "^6.24.1"
 768 | 
 769 | babel-preset-stage-3@^6.24.1:
 770 |   version "6.24.1"
 771 |   resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
 772 |   dependencies:
 773 |     babel-plugin-syntax-trailing-function-commas "^6.22.0"
 774 |     babel-plugin-transform-async-generator-functions "^6.24.1"
 775 |     babel-plugin-transform-async-to-generator "^6.24.1"
 776 |     babel-plugin-transform-exponentiation-operator "^6.24.1"
 777 |     babel-plugin-transform-object-rest-spread "^6.22.0"
 778 | 
 779 | babel-register@^6.24.1, babel-register@^6.5.1, babel-register@^6.6.0:
 780 |   version "6.24.1"
 781 |   resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f"
 782 |   dependencies:
 783 |     babel-core "^6.24.1"
 784 |     babel-runtime "^6.22.0"
 785 |     core-js "^2.4.0"
 786 |     home-or-tmp "^2.0.0"
 787 |     lodash "^4.2.0"
 788 |     mkdirp "^0.5.1"
 789 |     source-map-support "^0.4.2"
 790 | 
 791 | babel-runtime@^5.0.0:
 792 |   version "5.8.38"
 793 |   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-5.8.38.tgz#1c0b02eb63312f5f087ff20450827b425c9d4c19"
 794 |   dependencies:
 795 |     core-js "^1.0.0"
 796 | 
 797 | babel-runtime@^6.18.0, babel-runtime@^6.2.0, babel-runtime@^6.22.0:
 798 |   version "6.23.0"
 799 |   resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b"
 800 |   dependencies:
 801 |     core-js "^2.4.0"
 802 |     regenerator-runtime "^0.10.0"
 803 | 
 804 | babel-template@^6.24.1, babel-template@^6.3.0:
 805 |   version "6.24.1"
 806 |   resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
 807 |   dependencies:
 808 |     babel-runtime "^6.22.0"
 809 |     babel-traverse "^6.24.1"
 810 |     babel-types "^6.24.1"
 811 |     babylon "^6.11.0"
 812 |     lodash "^4.2.0"
 813 | 
 814 | babel-traverse@^6.24.1:
 815 |   version "6.24.1"
 816 |   resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
 817 |   dependencies:
 818 |     babel-code-frame "^6.22.0"
 819 |     babel-messages "^6.23.0"
 820 |     babel-runtime "^6.22.0"
 821 |     babel-types "^6.24.1"
 822 |     babylon "^6.15.0"
 823 |     debug "^2.2.0"
 824 |     globals "^9.0.0"
 825 |     invariant "^2.2.0"
 826 |     lodash "^4.2.0"
 827 | 
 828 | babel-types@^6.19.0, babel-types@^6.24.1:
 829 |   version "6.24.1"
 830 |   resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
 831 |   dependencies:
 832 |     babel-runtime "^6.22.0"
 833 |     esutils "^2.0.2"
 834 |     lodash "^4.2.0"
 835 |     to-fast-properties "^1.0.1"
 836 | 
 837 | babylon@^6.11.0, babylon@^6.15.0:
 838 |   version "6.17.1"
 839 |   resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f"
 840 | 
 841 | balanced-match@^0.4.1:
 842 |   version "0.4.2"
 843 |   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
 844 | 
 845 | bcrypt-pbkdf@^1.0.0:
 846 |   version "1.0.1"
 847 |   resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
 848 |   dependencies:
 849 |     tweetnacl "^0.14.3"
 850 | 
 851 | bin-version-check@^2.1.0:
 852 |   version "2.1.0"
 853 |   resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-2.1.0.tgz#e4e5df290b9069f7d111324031efc13fdd11a5b0"
 854 |   dependencies:
 855 |     bin-version "^1.0.0"
 856 |     minimist "^1.1.0"
 857 |     semver "^4.0.3"
 858 |     semver-truncate "^1.0.0"
 859 | 
 860 | bin-version@^1.0.0:
 861 |   version "1.0.4"
 862 |   resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-1.0.4.tgz#9eb498ee6fd76f7ab9a7c160436f89579435d78e"
 863 |   dependencies:
 864 |     find-versions "^1.0.0"
 865 | 
 866 | binary-extensions@^1.0.0:
 867 |   version "1.8.0"
 868 |   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
 869 | 
 870 | block-stream@*:
 871 |   version "0.0.9"
 872 |   resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
 873 |   dependencies:
 874 |     inherits "~2.0.0"
 875 | 
 876 | boom@2.x.x:
 877 |   version "2.10.1"
 878 |   resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
 879 |   dependencies:
 880 |     hoek "2.x.x"
 881 | 
 882 | brace-expansion@^1.1.7:
 883 |   version "1.1.7"
 884 |   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
 885 |   dependencies:
 886 |     balanced-match "^0.4.1"
 887 |     concat-map "0.0.1"
 888 | 
 889 | braces@^1.8.2:
 890 |   version "1.8.5"
 891 |   resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
 892 |   dependencies:
 893 |     expand-range "^1.8.1"
 894 |     preserve "^0.2.0"
 895 |     repeat-element "^1.1.2"
 896 | 
 897 | buffer-shims@~1.0.0:
 898 |   version "1.0.0"
 899 |   resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
 900 | 
 901 | builtin-modules@^1.0.0:
 902 |   version "1.1.1"
 903 |   resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
 904 | 
 905 | camelcase-keys@^2.0.0:
 906 |   version "2.1.0"
 907 |   resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
 908 |   dependencies:
 909 |     camelcase "^2.0.0"
 910 |     map-obj "^1.0.0"
 911 | 
 912 | camelcase@^2.0.0:
 913 |   version "2.1.1"
 914 |   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
 915 | 
 916 | caseless@~0.12.0:
 917 |   version "0.12.0"
 918 |   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
 919 | 
 920 | chai@^3.4.1:
 921 |   version "3.5.0"
 922 |   resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
 923 |   dependencies:
 924 |     assertion-error "^1.0.1"
 925 |     deep-eql "^0.1.3"
 926 |     type-detect "^1.0.0"
 927 | 
 928 | chalk@1.1.1, chalk@^1.0.0, chalk@^1.1.0:
 929 |   version "1.1.1"
 930 |   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.1.tgz#509afb67066e7499f7eb3535c77445772ae2d019"
 931 |   dependencies:
 932 |     ansi-styles "^2.1.0"
 933 |     escape-string-regexp "^1.0.2"
 934 |     has-ansi "^2.0.0"
 935 |     strip-ansi "^3.0.0"
 936 |     supports-color "^2.0.0"
 937 | 
 938 | chokidar@^1.0.0:
 939 |   version "1.7.0"
 940 |   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
 941 |   dependencies:
 942 |     anymatch "^1.3.0"
 943 |     async-each "^1.0.0"
 944 |     glob-parent "^2.0.0"
 945 |     inherits "^2.0.1"
 946 |     is-binary-path "^1.0.0"
 947 |     is-glob "^2.0.0"
 948 |     path-is-absolute "^1.0.0"
 949 |     readdirp "^2.0.0"
 950 |   optionalDependencies:
 951 |     fsevents "^1.0.0"
 952 | 
 953 | co@^4.6.0:
 954 |   version "4.6.0"
 955 |   resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
 956 | 
 957 | code-point-at@^1.0.0:
 958 |   version "1.1.0"
 959 |   resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
 960 | 
 961 | combined-stream@^1.0.5, combined-stream@~1.0.5:
 962 |   version "1.0.5"
 963 |   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
 964 |   dependencies:
 965 |     delayed-stream "~1.0.0"
 966 | 
 967 | commander@0.6.1:
 968 |   version "0.6.1"
 969 |   resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06"
 970 | 
 971 | commander@2.3.0:
 972 |   version "2.3.0"
 973 |   resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873"
 974 | 
 975 | commander@^2.8.1:
 976 |   version "2.9.0"
 977 |   resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
 978 |   dependencies:
 979 |     graceful-readlink ">= 1.0.0"
 980 | 
 981 | concat-map@0.0.1:
 982 |   version "0.0.1"
 983 |   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
 984 | 
 985 | console-control-strings@^1.0.0, console-control-strings@~1.1.0:
 986 |   version "1.1.0"
 987 |   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
 988 | 
 989 | convert-source-map@^1.1.0:
 990 |   version "1.5.0"
 991 |   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
 992 | 
 993 | core-js@^1.0.0:
 994 |   version "1.2.7"
 995 |   resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
 996 | 
 997 | core-js@^2.4.0:
 998 |   version "2.4.1"
 999 |   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
1000 | 
1001 | core-util-is@~1.0.0:
1002 |   version "1.0.2"
1003 |   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
1004 | 
1005 | create-react-class@^15.5.3:
1006 |   version "15.5.3"
1007 |   resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.3.tgz#fb0f7cae79339e9a179e194ef466efa3923820fe"
1008 |   dependencies:
1009 |     fbjs "^0.8.9"
1010 |     loose-envify "^1.3.1"
1011 |     object-assign "^4.1.1"
1012 | 
1013 | cryptiles@2.x.x:
1014 |   version "2.0.5"
1015 |   resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
1016 |   dependencies:
1017 |     boom "2.x.x"
1018 | 
1019 | cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0":
1020 |   version "0.3.2"
1021 |   resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b"
1022 | 
1023 | "cssstyle@>= 0.2.29 < 0.3.0":
1024 |   version "0.2.37"
1025 |   resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54"
1026 |   dependencies:
1027 |     cssom "0.3.x"
1028 | 
1029 | currently-unhandled@^0.4.1:
1030 |   version "0.4.1"
1031 |   resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
1032 |   dependencies:
1033 |     array-find-index "^1.0.1"
1034 | 
1035 | dashdash@^1.12.0:
1036 |   version "1.14.1"
1037 |   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
1038 |   dependencies:
1039 |     assert-plus "^1.0.0"
1040 | 
1041 | debug@2.2.0, debug@^2.1.1, debug@^2.2.0:
1042 |   version "2.2.0"
1043 |   resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
1044 |   dependencies:
1045 |     ms "0.7.1"
1046 | 
1047 | decamelize@^1.1.2:
1048 |   version "1.2.0"
1049 |   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
1050 | 
1051 | deep-eql@^0.1.3:
1052 |   version "0.1.3"
1053 |   resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
1054 |   dependencies:
1055 |     type-detect "0.1.1"
1056 | 
1057 | deep-extend@~0.4.0:
1058 |   version "0.4.2"
1059 |   resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
1060 | 
1061 | deep-is@~0.1.3:
1062 |   version "0.1.3"
1063 |   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
1064 | 
1065 | delayed-stream@~1.0.0:
1066 |   version "1.0.0"
1067 |   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
1068 | 
1069 | delegates@^1.0.0:
1070 |   version "1.0.0"
1071 |   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
1072 | 
1073 | detect-indent@^4.0.0:
1074 |   version "4.0.0"
1075 |   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
1076 |   dependencies:
1077 |     repeating "^2.0.0"
1078 | 
1079 | diff@1.4.0:
1080 |   version "1.4.0"
1081 |   resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
1082 | 
1083 | ecc-jsbn@~0.1.1:
1084 |   version "0.1.1"
1085 |   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
1086 |   dependencies:
1087 |     jsbn "~0.1.0"
1088 | 
1089 | encoding@^0.1.11:
1090 |   version "0.1.12"
1091 |   resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
1092 |   dependencies:
1093 |     iconv-lite "~0.4.13"
1094 | 
1095 | error-ex@^1.2.0:
1096 |   version "1.3.1"
1097 |   resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
1098 |   dependencies:
1099 |     is-arrayish "^0.2.1"
1100 | 
1101 | escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2:
1102 |   version "1.0.2"
1103 |   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"
1104 | 
1105 | escodegen@^1.6.1:
1106 |   version "1.8.1"
1107 |   resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018"
1108 |   dependencies:
1109 |     esprima "^2.7.1"
1110 |     estraverse "^1.9.1"
1111 |     esutils "^2.0.2"
1112 |     optionator "^0.8.1"
1113 |   optionalDependencies:
1114 |     source-map "~0.2.0"
1115 | 
1116 | esprima@^2.7.1:
1117 |   version "2.7.3"
1118 |   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
1119 | 
1120 | estraverse@^1.9.1:
1121 |   version "1.9.3"
1122 |   resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
1123 | 
1124 | esutils@^2.0.0, esutils@^2.0.2:
1125 |   version "2.0.2"
1126 |   resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
1127 | 
1128 | expand-brackets@^0.1.4:
1129 |   version "0.1.5"
1130 |   resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
1131 |   dependencies:
1132 |     is-posix-bracket "^0.1.0"
1133 | 
1134 | expand-range@^1.8.1:
1135 |   version "1.8.2"
1136 |   resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
1137 |   dependencies:
1138 |     fill-range "^2.1.0"
1139 | 
1140 | extend@~3.0.0:
1141 |   version "3.0.1"
1142 |   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
1143 | 
1144 | extglob@^0.3.1:
1145 |   version "0.3.2"
1146 |   resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
1147 |   dependencies:
1148 |     is-extglob "^1.0.0"
1149 | 
1150 | extsprintf@1.0.2:
1151 |   version "1.0.2"
1152 |   resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
1153 | 
1154 | fast-levenshtein@~2.0.4:
1155 |   version "2.0.6"
1156 |   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
1157 | 
1158 | fbjs@^0.8.9:
1159 |   version "0.8.12"
1160 |   resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
1161 |   dependencies:
1162 |     core-js "^1.0.0"
1163 |     isomorphic-fetch "^2.1.1"
1164 |     loose-envify "^1.0.0"
1165 |     object-assign "^4.1.0"
1166 |     promise "^7.1.1"
1167 |     setimmediate "^1.0.5"
1168 |     ua-parser-js "^0.7.9"
1169 | 
1170 | filename-regex@^2.0.0:
1171 |   version "2.0.1"
1172 |   resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
1173 | 
1174 | fill-range@^2.1.0:
1175 |   version "2.2.3"
1176 |   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
1177 |   dependencies:
1178 |     is-number "^2.1.0"
1179 |     isobject "^2.0.0"
1180 |     randomatic "^1.1.3"
1181 |     repeat-element "^1.1.2"
1182 |     repeat-string "^1.5.2"
1183 | 
1184 | find-up@^1.0.0:
1185 |   version "1.1.2"
1186 |   resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
1187 |   dependencies:
1188 |     path-exists "^2.0.0"
1189 |     pinkie-promise "^2.0.0"
1190 | 
1191 | find-versions@^1.0.0:
1192 |   version "1.2.1"
1193 |   resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-1.2.1.tgz#cbde9f12e38575a0af1be1b9a2c5d5fd8f186b62"
1194 |   dependencies:
1195 |     array-uniq "^1.0.0"
1196 |     get-stdin "^4.0.1"
1197 |     meow "^3.5.0"
1198 |     semver-regex "^1.0.0"
1199 | 
1200 | for-in@^1.0.1:
1201 |   version "1.0.2"
1202 |   resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
1203 | 
1204 | for-own@^0.1.4:
1205 |   version "0.1.5"
1206 |   resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
1207 |   dependencies:
1208 |     for-in "^1.0.1"
1209 | 
1210 | forever-agent@~0.6.1:
1211 |   version "0.6.1"
1212 |   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
1213 | 
1214 | form-data@~2.1.1:
1215 |   version "2.1.4"
1216 |   resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
1217 |   dependencies:
1218 |     asynckit "^0.4.0"
1219 |     combined-stream "^1.0.5"
1220 |     mime-types "^2.1.12"
1221 | 
1222 | fs-readdir-recursive@^0.1.0:
1223 |   version "0.1.2"
1224 |   resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-0.1.2.tgz#315b4fb8c1ca5b8c47defef319d073dad3568059"
1225 | 
1226 | fs.realpath@^1.0.0:
1227 |   version "1.0.0"
1228 |   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
1229 | 
1230 | fsevents@^1.0.0:
1231 |   version "1.1.1"
1232 |   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.1.tgz#f19fd28f43eeaf761680e519a203c4d0b3d31aff"
1233 |   dependencies:
1234 |     nan "^2.3.0"
1235 |     node-pre-gyp "^0.6.29"
1236 | 
1237 | fstream-ignore@^1.0.5:
1238 |   version "1.0.5"
1239 |   resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
1240 |   dependencies:
1241 |     fstream "^1.0.0"
1242 |     inherits "2"
1243 |     minimatch "^3.0.0"
1244 | 
1245 | fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
1246 |   version "1.0.11"
1247 |   resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
1248 |   dependencies:
1249 |     graceful-fs "^4.1.2"
1250 |     inherits "~2.0.0"
1251 |     mkdirp ">=0.5 0"
1252 |     rimraf "2"
1253 | 
1254 | gauge@~2.7.3:
1255 |   version "2.7.4"
1256 |   resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
1257 |   dependencies:
1258 |     aproba "^1.0.3"
1259 |     console-control-strings "^1.0.0"
1260 |     has-unicode "^2.0.0"
1261 |     object-assign "^4.1.0"
1262 |     signal-exit "^3.0.0"
1263 |     string-width "^1.0.1"
1264 |     strip-ansi "^3.0.1"
1265 |     wide-align "^1.1.0"
1266 | 
1267 | get-stdin@^4.0.1:
1268 |   version "4.0.1"
1269 |   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
1270 | 
1271 | getpass@^0.1.1:
1272 |   version "0.1.7"
1273 |   resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
1274 |   dependencies:
1275 |     assert-plus "^1.0.0"
1276 | 
1277 | glob-base@^0.3.0:
1278 |   version "0.3.0"
1279 |   resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
1280 |   dependencies:
1281 |     glob-parent "^2.0.0"
1282 |     is-glob "^2.0.0"
1283 | 
1284 | glob-parent@^2.0.0:
1285 |   version "2.0.0"
1286 |   resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
1287 |   dependencies:
1288 |     is-glob "^2.0.0"
1289 | 
1290 | glob@3.2.11:
1291 |   version "3.2.11"
1292 |   resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d"
1293 |   dependencies:
1294 |     inherits "2"
1295 |     minimatch "0.3"
1296 | 
1297 | glob@^5.0.5:
1298 |   version "5.0.15"
1299 |   resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
1300 |   dependencies:
1301 |     inflight "^1.0.4"
1302 |     inherits "2"
1303 |     minimatch "2 || 3"
1304 |     once "^1.3.0"
1305 |     path-is-absolute "^1.0.0"
1306 | 
1307 | glob@^7.0.5:
1308 |   version "7.1.1"
1309 |   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
1310 |   dependencies:
1311 |     fs.realpath "^1.0.0"
1312 |     inflight "^1.0.4"
1313 |     inherits "2"
1314 |     minimatch "^3.0.2"
1315 |     once "^1.3.0"
1316 |     path-is-absolute "^1.0.0"
1317 | 
1318 | globals@^9.0.0:
1319 |   version "9.17.0"
1320 |   resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286"
1321 | 
1322 | graceful-fs@^4.1.2, graceful-fs@^4.1.4:
1323 |   version "4.1.11"
1324 |   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
1325 | 
1326 | "graceful-readlink@>= 1.0.0":
1327 |   version "1.0.1"
1328 |   resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
1329 | 
1330 | growl@1.9.2:
1331 |   version "1.9.2"
1332 |   resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
1333 | 
1334 | har-schema@^1.0.5:
1335 |   version "1.0.5"
1336 |   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
1337 | 
1338 | har-validator@~4.2.1:
1339 |   version "4.2.1"
1340 |   resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
1341 |   dependencies:
1342 |     ajv "^4.9.1"
1343 |     har-schema "^1.0.5"
1344 | 
1345 | has-ansi@^2.0.0:
1346 |   version "2.0.0"
1347 |   resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
1348 |   dependencies:
1349 |     ansi-regex "^2.0.0"
1350 | 
1351 | has-unicode@^2.0.0:
1352 |   version "2.0.1"
1353 |   resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
1354 | 
1355 | hawk@~3.1.3:
1356 |   version "3.1.3"
1357 |   resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
1358 |   dependencies:
1359 |     boom "2.x.x"
1360 |     cryptiles "2.x.x"
1361 |     hoek "2.x.x"
1362 |     sntp "1.x.x"
1363 | 
1364 | hoek@2.x.x:
1365 |   version "2.16.3"
1366 |   resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
1367 | 
1368 | hoist-non-react-statics@^1.0.3:
1369 |   version "1.2.0"
1370 |   resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
1371 | 
1372 | home-or-tmp@^2.0.0:
1373 |   version "2.0.0"
1374 |   resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
1375 |   dependencies:
1376 |     os-homedir "^1.0.0"
1377 |     os-tmpdir "^1.0.1"
1378 | 
1379 | hosted-git-info@^2.1.4:
1380 |   version "2.4.2"
1381 |   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
1382 | 
1383 | http-signature@~1.1.0:
1384 |   version "1.1.1"
1385 |   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
1386 |   dependencies:
1387 |     assert-plus "^0.2.0"
1388 |     jsprim "^1.2.2"
1389 |     sshpk "^1.7.0"
1390 | 
1391 | iconv-lite@~0.4.13:
1392 |   version "0.4.17"
1393 |   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d"
1394 | 
1395 | immutable@^3.7.5:
1396 |   version "3.8.1"
1397 |   resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2"
1398 | 
1399 | indent-string@^2.1.0:
1400 |   version "2.1.0"
1401 |   resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
1402 |   dependencies:
1403 |     repeating "^2.0.0"
1404 | 
1405 | inflight@^1.0.4:
1406 |   version "1.0.6"
1407 |   resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
1408 |   dependencies:
1409 |     once "^1.3.0"
1410 |     wrappy "1"
1411 | 
1412 | inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1:
1413 |   version "2.0.3"
1414 |   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
1415 | 
1416 | ini@~1.3.0:
1417 |   version "1.3.4"
1418 |   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
1419 | 
1420 | invariant@^2.0.0, invariant@^2.2.0:
1421 |   version "2.2.2"
1422 |   resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
1423 |   dependencies:
1424 |     loose-envify "^1.0.0"
1425 | 
1426 | is-arrayish@^0.2.1:
1427 |   version "0.2.1"
1428 |   resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
1429 | 
1430 | is-binary-path@^1.0.0:
1431 |   version "1.0.1"
1432 |   resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
1433 |   dependencies:
1434 |     binary-extensions "^1.0.0"
1435 | 
1436 | is-buffer@^1.1.5:
1437 |   version "1.1.5"
1438 |   resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
1439 | 
1440 | is-builtin-module@^1.0.0:
1441 |   version "1.0.0"
1442 |   resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
1443 |   dependencies:
1444 |     builtin-modules "^1.0.0"
1445 | 
1446 | is-dotfile@^1.0.0:
1447 |   version "1.0.2"
1448 |   resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d"
1449 | 
1450 | is-equal-shallow@^0.1.3:
1451 |   version "0.1.3"
1452 |   resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
1453 |   dependencies:
1454 |     is-primitive "^2.0.0"
1455 | 
1456 | is-extendable@^0.1.1:
1457 |   version "0.1.1"
1458 |   resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
1459 | 
1460 | is-extglob@^1.0.0:
1461 |   version "1.0.0"
1462 |   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
1463 | 
1464 | is-finite@^1.0.0:
1465 |   version "1.0.2"
1466 |   resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
1467 |   dependencies:
1468 |     number-is-nan "^1.0.0"
1469 | 
1470 | is-fullwidth-code-point@^1.0.0:
1471 |   version "1.0.0"
1472 |   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
1473 |   dependencies:
1474 |     number-is-nan "^1.0.0"
1475 | 
1476 | is-glob@^2.0.0, is-glob@^2.0.1:
1477 |   version "2.0.1"
1478 |   resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
1479 |   dependencies:
1480 |     is-extglob "^1.0.0"
1481 | 
1482 | is-number@^2.0.2, is-number@^2.1.0:
1483 |   version "2.1.0"
1484 |   resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
1485 |   dependencies:
1486 |     kind-of "^3.0.2"
1487 | 
1488 | is-posix-bracket@^0.1.0:
1489 |   version "0.1.1"
1490 |   resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
1491 | 
1492 | is-primitive@^2.0.0:
1493 |   version "2.0.0"
1494 |   resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
1495 | 
1496 | is-stream@^1.0.1:
1497 |   version "1.1.0"
1498 |   resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
1499 | 
1500 | is-typedarray@~1.0.0:
1501 |   version "1.0.0"
1502 |   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
1503 | 
1504 | is-utf8@^0.2.0:
1505 |   version "0.2.1"
1506 |   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
1507 | 
1508 | isarray@1.0.0, isarray@~1.0.0:
1509 |   version "1.0.0"
1510 |   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
1511 | 
1512 | isobject@^2.0.0:
1513 |   version "2.1.0"
1514 |   resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
1515 |   dependencies:
1516 |     isarray "1.0.0"
1517 | 
1518 | isomorphic-fetch@^2.1.1:
1519 |   version "2.2.1"
1520 |   resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
1521 |   dependencies:
1522 |     node-fetch "^1.0.1"
1523 |     whatwg-fetch ">=0.10.0"
1524 | 
1525 | isstream@~0.1.2:
1526 |   version "0.1.2"
1527 |   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
1528 | 
1529 | jade@0.26.3:
1530 |   version "0.26.3"
1531 |   resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c"
1532 |   dependencies:
1533 |     commander "0.6.1"
1534 |     mkdirp "0.3.0"
1535 | 
1536 | jodid25519@^1.0.0:
1537 |   version "1.0.2"
1538 |   resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
1539 |   dependencies:
1540 |     jsbn "~0.1.0"
1541 | 
1542 | js-tokens@^3.0.0:
1543 |   version "3.0.1"
1544 |   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
1545 | 
1546 | jsbn@~0.1.0:
1547 |   version "0.1.1"
1548 |   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
1549 | 
1550 | jsdom@^7.2.1:
1551 |   version "7.2.2"
1552 |   resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e"
1553 |   dependencies:
1554 |     abab "^1.0.0"
1555 |     acorn "^2.4.0"
1556 |     acorn-globals "^1.0.4"
1557 |     cssom ">= 0.3.0 < 0.4.0"
1558 |     cssstyle ">= 0.2.29 < 0.3.0"
1559 |     escodegen "^1.6.1"
1560 |     nwmatcher ">= 1.3.7 < 2.0.0"
1561 |     parse5 "^1.5.1"
1562 |     request "^2.55.0"
1563 |     sax "^1.1.4"
1564 |     symbol-tree ">= 3.1.0 < 4.0.0"
1565 |     tough-cookie "^2.2.0"
1566 |     webidl-conversions "^2.0.0"
1567 |     whatwg-url-compat "~0.6.5"
1568 |     xml-name-validator ">= 2.0.1 < 3.0.0"
1569 | 
1570 | jsesc@^1.3.0:
1571 |   version "1.3.0"
1572 |   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
1573 | 
1574 | jsesc@~0.5.0:
1575 |   version "0.5.0"
1576 |   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
1577 | 
1578 | json-schema@0.2.3:
1579 |   version "0.2.3"
1580 |   resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
1581 | 
1582 | json-stable-stringify@^1.0.1:
1583 |   version "1.0.1"
1584 |   resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
1585 |   dependencies:
1586 |     jsonify "~0.0.0"
1587 | 
1588 | json-stringify-safe@~5.0.1:
1589 |   version "5.0.1"
1590 |   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
1591 | 
1592 | json5@^0.5.0:
1593 |   version "0.5.1"
1594 |   resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
1595 | 
1596 | jsonify@~0.0.0:
1597 |   version "0.0.0"
1598 |   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
1599 | 
1600 | jsprim@^1.2.2:
1601 |   version "1.4.0"
1602 |   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918"
1603 |   dependencies:
1604 |     assert-plus "1.0.0"
1605 |     extsprintf "1.0.2"
1606 |     json-schema "0.2.3"
1607 |     verror "1.3.6"
1608 | 
1609 | kind-of@^3.0.2:
1610 |   version "3.2.0"
1611 |   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07"
1612 |   dependencies:
1613 |     is-buffer "^1.1.5"
1614 | 
1615 | levn@~0.3.0:
1616 |   version "0.3.0"
1617 |   resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
1618 |   dependencies:
1619 |     prelude-ls "~1.1.2"
1620 |     type-check "~0.3.2"
1621 | 
1622 | load-json-file@^1.0.0:
1623 |   version "1.1.0"
1624 |   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
1625 |   dependencies:
1626 |     graceful-fs "^4.1.2"
1627 |     parse-json "^2.2.0"
1628 |     pify "^2.0.0"
1629 |     pinkie-promise "^2.0.0"
1630 |     strip-bom "^2.0.0"
1631 | 
1632 | lodash-es@^4.2.0, lodash-es@^4.2.1:
1633 |   version "4.17.4"
1634 |   resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7"
1635 | 
1636 | lodash@^3.2.0:
1637 |   version "3.10.1"
1638 |   resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
1639 | 
1640 | lodash@^4.2.0, lodash@^4.2.1:
1641 |   version "4.17.4"
1642 |   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
1643 | 
1644 | log-symbols@^1.0.2:
1645 |   version "1.0.2"
1646 |   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
1647 |   dependencies:
1648 |     chalk "^1.0.0"
1649 | 
1650 | loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
1651 |   version "1.3.1"
1652 |   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
1653 |   dependencies:
1654 |     js-tokens "^3.0.0"
1655 | 
1656 | loud-rejection@^1.0.0:
1657 |   version "1.6.0"
1658 |   resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
1659 |   dependencies:
1660 |     currently-unhandled "^0.4.1"
1661 |     signal-exit "^3.0.0"
1662 | 
1663 | lru-cache@2:
1664 |   version "2.7.3"
1665 |   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
1666 | 
1667 | map-obj@^1.0.0, map-obj@^1.0.1:
1668 |   version "1.0.1"
1669 |   resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
1670 | 
1671 | meow@^3.5.0:
1672 |   version "3.7.0"
1673 |   resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
1674 |   dependencies:
1675 |     camelcase-keys "^2.0.0"
1676 |     decamelize "^1.1.2"
1677 |     loud-rejection "^1.0.0"
1678 |     map-obj "^1.0.1"
1679 |     minimist "^1.1.3"
1680 |     normalize-package-data "^2.3.4"
1681 |     object-assign "^4.0.1"
1682 |     read-pkg-up "^1.0.1"
1683 |     redent "^1.0.0"
1684 |     trim-newlines "^1.0.0"
1685 | 
1686 | micromatch@^2.1.5:
1687 |   version "2.3.11"
1688 |   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
1689 |   dependencies:
1690 |     arr-diff "^2.0.0"
1691 |     array-unique "^0.2.1"
1692 |     braces "^1.8.2"
1693 |     expand-brackets "^0.1.4"
1694 |     extglob "^0.3.1"
1695 |     filename-regex "^2.0.0"
1696 |     is-extglob "^1.0.0"
1697 |     is-glob "^2.0.1"
1698 |     kind-of "^3.0.2"
1699 |     normalize-path "^2.0.1"
1700 |     object.omit "^2.0.0"
1701 |     parse-glob "^3.0.4"
1702 |     regex-cache "^0.4.2"
1703 | 
1704 | mime-db@~1.27.0:
1705 |   version "1.27.0"
1706 |   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
1707 | 
1708 | mime-types@^2.1.12, mime-types@~2.1.7:
1709 |   version "2.1.15"
1710 |   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
1711 |   dependencies:
1712 |     mime-db "~1.27.0"
1713 | 
1714 | minimatch@0.3:
1715 |   version "0.3.0"
1716 |   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd"
1717 |   dependencies:
1718 |     lru-cache "2"
1719 |     sigmund "~1.0.0"
1720 | 
1721 | "minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2:
1722 |   version "3.0.4"
1723 |   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
1724 |   dependencies:
1725 |     brace-expansion "^1.1.7"
1726 | 
1727 | minimist@0.0.8:
1728 |   version "0.0.8"
1729 |   resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
1730 | 
1731 | minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
1732 |   version "1.2.0"
1733 |   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
1734 | 
1735 | mkdirp@0.3.0:
1736 |   version "0.3.0"
1737 |   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e"
1738 | 
1739 | mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.1:
1740 |   version "0.5.1"
1741 |   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
1742 |   dependencies:
1743 |     minimist "0.0.8"
1744 | 
1745 | mocha@^2.3.4:
1746 |   version "2.5.3"
1747 |   resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58"
1748 |   dependencies:
1749 |     commander "2.3.0"
1750 |     debug "2.2.0"
1751 |     diff "1.4.0"
1752 |     escape-string-regexp "1.0.2"
1753 |     glob "3.2.11"
1754 |     growl "1.9.2"
1755 |     jade "0.26.3"
1756 |     mkdirp "0.5.1"
1757 |     supports-color "1.2.0"
1758 |     to-iso-string "0.0.2"
1759 | 
1760 | ms@0.7.1:
1761 |   version "0.7.1"
1762 |   resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
1763 | 
1764 | nan@^2.3.0:
1765 |   version "2.6.2"
1766 |   resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
1767 | 
1768 | node-fetch@^1.0.1:
1769 |   version "1.6.3"
1770 |   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
1771 |   dependencies:
1772 |     encoding "^0.1.11"
1773 |     is-stream "^1.0.1"
1774 | 
1775 | node-pre-gyp@^0.6.29:
1776 |   version "0.6.34"
1777 |   resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7"
1778 |   dependencies:
1779 |     mkdirp "^0.5.1"
1780 |     nopt "^4.0.1"
1781 |     npmlog "^4.0.2"
1782 |     rc "^1.1.7"
1783 |     request "^2.81.0"
1784 |     rimraf "^2.6.1"
1785 |     semver "^5.3.0"
1786 |     tar "^2.2.1"
1787 |     tar-pack "^3.4.0"
1788 | 
1789 | nopt@^4.0.1:
1790 |   version "4.0.1"
1791 |   resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
1792 |   dependencies:
1793 |     abbrev "1"
1794 |     osenv "^0.1.4"
1795 | 
1796 | normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
1797 |   version "2.3.8"
1798 |   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
1799 |   dependencies:
1800 |     hosted-git-info "^2.1.4"
1801 |     is-builtin-module "^1.0.0"
1802 |     semver "2 || 3 || 4 || 5"
1803 |     validate-npm-package-license "^3.0.1"
1804 | 
1805 | normalize-path@^2.0.1:
1806 |   version "2.1.1"
1807 |   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
1808 |   dependencies:
1809 |     remove-trailing-separator "^1.0.1"
1810 | 
1811 | npmlog@^4.0.2:
1812 |   version "4.1.0"
1813 |   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
1814 |   dependencies:
1815 |     are-we-there-yet "~1.1.2"
1816 |     console-control-strings "~1.1.0"
1817 |     gauge "~2.7.3"
1818 |     set-blocking "~2.0.0"
1819 | 
1820 | number-is-nan@^1.0.0:
1821 |   version "1.0.1"
1822 |   resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
1823 | 
1824 | "nwmatcher@>= 1.3.7 < 2.0.0":
1825 |   version "1.3.9"
1826 |   resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a"
1827 | 
1828 | oauth-sign@~0.8.1:
1829 |   version "0.8.2"
1830 |   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
1831 | 
1832 | object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
1833 |   version "4.1.1"
1834 |   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
1835 | 
1836 | object.omit@^2.0.0:
1837 |   version "2.0.1"
1838 |   resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
1839 |   dependencies:
1840 |     for-own "^0.1.4"
1841 |     is-extendable "^0.1.1"
1842 | 
1843 | once@^1.3.0, once@^1.3.3:
1844 |   version "1.4.0"
1845 |   resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
1846 |   dependencies:
1847 |     wrappy "1"
1848 | 
1849 | optionator@^0.8.1:
1850 |   version "0.8.2"
1851 |   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
1852 |   dependencies:
1853 |     deep-is "~0.1.3"
1854 |     fast-levenshtein "~2.0.4"
1855 |     levn "~0.3.0"
1856 |     prelude-ls "~1.1.2"
1857 |     type-check "~0.3.2"
1858 |     wordwrap "~1.0.0"
1859 | 
1860 | os-homedir@^1.0.0:
1861 |   version "1.0.2"
1862 |   resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
1863 | 
1864 | os-tmpdir@^1.0.0, os-tmpdir@^1.0.1:
1865 |   version "1.0.2"
1866 |   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
1867 | 
1868 | osenv@^0.1.4:
1869 |   version "0.1.4"
1870 |   resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
1871 |   dependencies:
1872 |     os-homedir "^1.0.0"
1873 |     os-tmpdir "^1.0.0"
1874 | 
1875 | output-file-sync@^1.1.0:
1876 |   version "1.1.2"
1877 |   resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76"
1878 |   dependencies:
1879 |     graceful-fs "^4.1.4"
1880 |     mkdirp "^0.5.1"
1881 |     object-assign "^4.1.0"
1882 | 
1883 | parse-glob@^3.0.4:
1884 |   version "3.0.4"
1885 |   resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
1886 |   dependencies:
1887 |     glob-base "^0.3.0"
1888 |     is-dotfile "^1.0.0"
1889 |     is-extglob "^1.0.0"
1890 |     is-glob "^2.0.0"
1891 | 
1892 | parse-json@^2.2.0:
1893 |   version "2.2.0"
1894 |   resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
1895 |   dependencies:
1896 |     error-ex "^1.2.0"
1897 | 
1898 | parse5@^1.5.1:
1899 |   version "1.5.1"
1900 |   resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94"
1901 | 
1902 | path-exists@^1.0.0:
1903 |   version "1.0.0"
1904 |   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-1.0.0.tgz#d5a8998eb71ef37a74c34eb0d9eba6e878eea081"
1905 | 
1906 | path-exists@^2.0.0:
1907 |   version "2.1.0"
1908 |   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
1909 |   dependencies:
1910 |     pinkie-promise "^2.0.0"
1911 | 
1912 | path-is-absolute@^1.0.0:
1913 |   version "1.0.1"
1914 |   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
1915 | 
1916 | path-type@^1.0.0:
1917 |   version "1.1.0"
1918 |   resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
1919 |   dependencies:
1920 |     graceful-fs "^4.1.2"
1921 |     pify "^2.0.0"
1922 |     pinkie-promise "^2.0.0"
1923 | 
1924 | performance-now@^0.2.0:
1925 |   version "0.2.0"
1926 |   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
1927 | 
1928 | pify@^2.0.0:
1929 |   version "2.3.0"
1930 |   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
1931 | 
1932 | pinkie-promise@^2.0.0:
1933 |   version "2.0.1"
1934 |   resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
1935 |   dependencies:
1936 |     pinkie "^2.0.0"
1937 | 
1938 | pinkie@^2.0.0:
1939 |   version "2.0.4"
1940 |   resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
1941 | 
1942 | prelude-ls@~1.1.2:
1943 |   version "1.1.2"
1944 |   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
1945 | 
1946 | preserve@^0.2.0:
1947 |   version "0.2.0"
1948 |   resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
1949 | 
1950 | private@^0.1.6:
1951 |   version "0.1.7"
1952 |   resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
1953 | 
1954 | process-nextick-args@~1.0.6:
1955 |   version "1.0.7"
1956 |   resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
1957 | 
1958 | promise@^7.1.1:
1959 |   version "7.1.1"
1960 |   resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
1961 |   dependencies:
1962 |     asap "~2.0.3"
1963 | 
1964 | prop-types@^15.5.10, prop-types@^15.5.7, prop-types@~15.5.0:
1965 |   version "15.5.10"
1966 |   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
1967 |   dependencies:
1968 |     fbjs "^0.8.9"
1969 |     loose-envify "^1.3.1"
1970 | 
1971 | punycode@^1.4.1:
1972 |   version "1.4.1"
1973 |   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
1974 | 
1975 | qs@~6.4.0:
1976 |   version "6.4.0"
1977 |   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
1978 | 
1979 | randomatic@^1.1.3:
1980 |   version "1.1.6"
1981 |   resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb"
1982 |   dependencies:
1983 |     is-number "^2.0.2"
1984 |     kind-of "^3.0.2"
1985 | 
1986 | rc@^1.1.7:
1987 |   version "1.2.1"
1988 |   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
1989 |   dependencies:
1990 |     deep-extend "~0.4.0"
1991 |     ini "~1.3.0"
1992 |     minimist "^1.2.0"
1993 |     strip-json-comments "~2.0.1"
1994 | 
1995 | react-dom@15.5.0:
1996 |   version "15.5.0"
1997 |   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.5.0.tgz#86a8d6dcde388473815039de3840706e1f28f697"
1998 |   dependencies:
1999 |     fbjs "^0.8.9"
2000 |     loose-envify "^1.1.0"
2001 |     object-assign "^4.1.0"
2002 |     prop-types "~15.5.0"
2003 | 
2004 | "react-redux@^4.4.8 || ^5.0.4":
2005 |   version "5.0.5"
2006 |   resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.5.tgz#f8e8c7b239422576e52d6b7db06439469be9846a"
2007 |   dependencies:
2008 |     create-react-class "^15.5.3"
2009 |     hoist-non-react-statics "^1.0.3"
2010 |     invariant "^2.0.0"
2011 |     lodash "^4.2.0"
2012 |     lodash-es "^4.2.0"
2013 |     loose-envify "^1.1.0"
2014 |     prop-types "^15.5.10"
2015 | 
2016 | "react@^0.14.9 || ^15.3.0":
2017 |   version "15.5.4"
2018 |   resolved "https://registry.yarnpkg.com/react/-/react-15.5.4.tgz#fa83eb01506ab237cdc1c8c3b1cea8de012bf047"
2019 |   dependencies:
2020 |     fbjs "^0.8.9"
2021 |     loose-envify "^1.1.0"
2022 |     object-assign "^4.1.0"
2023 |     prop-types "^15.5.7"
2024 | 
2025 | read-pkg-up@^1.0.1:
2026 |   version "1.0.1"
2027 |   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
2028 |   dependencies:
2029 |     find-up "^1.0.0"
2030 |     read-pkg "^1.0.0"
2031 | 
2032 | read-pkg@^1.0.0:
2033 |   version "1.1.0"
2034 |   resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
2035 |   dependencies:
2036 |     load-json-file "^1.0.0"
2037 |     normalize-package-data "^2.3.2"
2038 |     path-type "^1.0.0"
2039 | 
2040 | readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4:
2041 |   version "2.2.9"
2042 |   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
2043 |   dependencies:
2044 |     buffer-shims "~1.0.0"
2045 |     core-util-is "~1.0.0"
2046 |     inherits "~2.0.1"
2047 |     isarray "~1.0.0"
2048 |     process-nextick-args "~1.0.6"
2049 |     string_decoder "~1.0.0"
2050 |     util-deprecate "~1.0.1"
2051 | 
2052 | readdirp@^2.0.0:
2053 |   version "2.1.0"
2054 |   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
2055 |   dependencies:
2056 |     graceful-fs "^4.1.2"
2057 |     minimatch "^3.0.2"
2058 |     readable-stream "^2.0.2"
2059 |     set-immediate-shim "^1.0.1"
2060 | 
2061 | redent@^1.0.0:
2062 |   version "1.0.0"
2063 |   resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
2064 |   dependencies:
2065 |     indent-string "^2.1.0"
2066 |     strip-indent "^1.0.1"
2067 | 
2068 | redux@^3.0.4:
2069 |   version "3.6.0"
2070 |   resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d"
2071 |   dependencies:
2072 |     lodash "^4.2.1"
2073 |     lodash-es "^4.2.1"
2074 |     loose-envify "^1.1.0"
2075 |     symbol-observable "^1.0.2"
2076 | 
2077 | regenerate@^1.2.1:
2078 |   version "1.3.2"
2079 |   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
2080 | 
2081 | regenerator-runtime@^0.10.0:
2082 |   version "0.10.5"
2083 |   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
2084 | 
2085 | regenerator-transform@0.9.11:
2086 |   version "0.9.11"
2087 |   resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283"
2088 |   dependencies:
2089 |     babel-runtime "^6.18.0"
2090 |     babel-types "^6.19.0"
2091 |     private "^0.1.6"
2092 | 
2093 | regex-cache@^0.4.2:
2094 |   version "0.4.3"
2095 |   resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
2096 |   dependencies:
2097 |     is-equal-shallow "^0.1.3"
2098 |     is-primitive "^2.0.0"
2099 | 
2100 | regexpu-core@^2.0.0:
2101 |   version "2.0.0"
2102 |   resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
2103 |   dependencies:
2104 |     regenerate "^1.2.1"
2105 |     regjsgen "^0.2.0"
2106 |     regjsparser "^0.1.4"
2107 | 
2108 | regjsgen@^0.2.0:
2109 |   version "0.2.0"
2110 |   resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
2111 | 
2112 | regjsparser@^0.1.4:
2113 |   version "0.1.5"
2114 |   resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
2115 |   dependencies:
2116 |     jsesc "~0.5.0"
2117 | 
2118 | remove-trailing-separator@^1.0.1:
2119 |   version "1.0.1"
2120 |   resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4"
2121 | 
2122 | repeat-element@^1.1.2:
2123 |   version "1.1.2"
2124 |   resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
2125 | 
2126 | repeat-string@^1.5.2:
2127 |   version "1.6.1"
2128 |   resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
2129 | 
2130 | repeating@^2.0.0:
2131 |   version "2.0.1"
2132 |   resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
2133 |   dependencies:
2134 |     is-finite "^1.0.0"
2135 | 
2136 | request@^2.55.0, request@^2.65.0, request@^2.81.0:
2137 |   version "2.81.0"
2138 |   resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
2139 |   dependencies:
2140 |     aws-sign2 "~0.6.0"
2141 |     aws4 "^1.2.1"
2142 |     caseless "~0.12.0"
2143 |     combined-stream "~1.0.5"
2144 |     extend "~3.0.0"
2145 |     forever-agent "~0.6.1"
2146 |     form-data "~2.1.1"
2147 |     har-validator "~4.2.1"
2148 |     hawk "~3.1.3"
2149 |     http-signature "~1.1.0"
2150 |     is-typedarray "~1.0.0"
2151 |     isstream "~0.1.2"
2152 |     json-stringify-safe "~5.0.1"
2153 |     mime-types "~2.1.7"
2154 |     oauth-sign "~0.8.1"
2155 |     performance-now "^0.2.0"
2156 |     qs "~6.4.0"
2157 |     safe-buffer "^5.0.1"
2158 |     stringstream "~0.0.4"
2159 |     tough-cookie "~2.3.0"
2160 |     tunnel-agent "^0.6.0"
2161 |     uuid "^3.0.0"
2162 | 
2163 | rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1:
2164 |   version "2.6.1"
2165 |   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
2166 |   dependencies:
2167 |     glob "^7.0.5"
2168 | 
2169 | safe-buffer@^5.0.1:
2170 |   version "5.0.1"
2171 |   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
2172 | 
2173 | sax@^1.1.4:
2174 |   version "1.2.2"
2175 |   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828"
2176 | 
2177 | semver-regex@^1.0.0:
2178 |   version "1.0.0"
2179 |   resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-1.0.0.tgz#92a4969065f9c70c694753d55248fc68f8f652c9"
2180 | 
2181 | semver-truncate@^1.0.0:
2182 |   version "1.1.2"
2183 |   resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8"
2184 |   dependencies:
2185 |     semver "^5.3.0"
2186 | 
2187 | "semver@2 || 3 || 4 || 5", semver@^5.3.0:
2188 |   version "5.3.0"
2189 |   resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
2190 | 
2191 | semver@^4.0.3:
2192 |   version "4.3.6"
2193 |   resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
2194 | 
2195 | set-blocking@~2.0.0:
2196 |   version "2.0.0"
2197 |   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
2198 | 
2199 | set-immediate-shim@^1.0.1:
2200 |   version "1.0.1"
2201 |   resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
2202 | 
2203 | setimmediate@^1.0.5:
2204 |   version "1.0.5"
2205 |   resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
2206 | 
2207 | sigmund@~1.0.0:
2208 |   version "1.0.1"
2209 |   resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
2210 | 
2211 | signal-exit@^3.0.0:
2212 |   version "3.0.2"
2213 |   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
2214 | 
2215 | slash@^1.0.0:
2216 |   version "1.0.0"
2217 |   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
2218 | 
2219 | sntp@1.x.x:
2220 |   version "1.0.9"
2221 |   resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
2222 |   dependencies:
2223 |     hoek "2.x.x"
2224 | 
2225 | source-map-support@^0.4.2:
2226 |   version "0.4.15"
2227 |   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
2228 |   dependencies:
2229 |     source-map "^0.5.6"
2230 | 
2231 | source-map@^0.5.0, source-map@^0.5.6:
2232 |   version "0.5.6"
2233 |   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
2234 | 
2235 | source-map@~0.2.0:
2236 |   version "0.2.0"
2237 |   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
2238 |   dependencies:
2239 |     amdefine ">=0.0.4"
2240 | 
2241 | spdx-correct@~1.0.0:
2242 |   version "1.0.2"
2243 |   resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
2244 |   dependencies:
2245 |     spdx-license-ids "^1.0.2"
2246 | 
2247 | spdx-expression-parse@~1.0.0:
2248 |   version "1.0.4"
2249 |   resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
2250 | 
2251 | spdx-license-ids@^1.0.2:
2252 |   version "1.2.2"
2253 |   resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
2254 | 
2255 | sshpk@^1.7.0:
2256 |   version "1.13.0"
2257 |   resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
2258 |   dependencies:
2259 |     asn1 "~0.2.3"
2260 |     assert-plus "^1.0.0"
2261 |     dashdash "^1.12.0"
2262 |     getpass "^0.1.1"
2263 |   optionalDependencies:
2264 |     bcrypt-pbkdf "^1.0.0"
2265 |     ecc-jsbn "~0.1.1"
2266 |     jodid25519 "^1.0.0"
2267 |     jsbn "~0.1.0"
2268 |     tweetnacl "~0.14.0"
2269 | 
2270 | string-width@^1.0.1, string-width@^1.0.2:
2271 |   version "1.0.2"
2272 |   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
2273 |   dependencies:
2274 |     code-point-at "^1.0.0"
2275 |     is-fullwidth-code-point "^1.0.0"
2276 |     strip-ansi "^3.0.0"
2277 | 
2278 | string_decoder@~1.0.0:
2279 |   version "1.0.0"
2280 |   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
2281 |   dependencies:
2282 |     buffer-shims "~1.0.0"
2283 | 
2284 | stringstream@~0.0.4:
2285 |   version "0.0.5"
2286 |   resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
2287 | 
2288 | strip-ansi@^3.0.0, strip-ansi@^3.0.1:
2289 |   version "3.0.1"
2290 |   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
2291 |   dependencies:
2292 |     ansi-regex "^2.0.0"
2293 | 
2294 | strip-bom@^2.0.0:
2295 |   version "2.0.0"
2296 |   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
2297 |   dependencies:
2298 |     is-utf8 "^0.2.0"
2299 | 
2300 | strip-indent@^1.0.1:
2301 |   version "1.0.1"
2302 |   resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
2303 |   dependencies:
2304 |     get-stdin "^4.0.1"
2305 | 
2306 | strip-json-comments@~2.0.1:
2307 |   version "2.0.1"
2308 |   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
2309 | 
2310 | supports-color@1.2.0:
2311 |   version "1.2.0"
2312 |   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e"
2313 | 
2314 | supports-color@^2.0.0:
2315 |   version "2.0.0"
2316 |   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
2317 | 
2318 | symbol-observable@^1.0.2:
2319 |   version "1.0.4"
2320 |   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
2321 | 
2322 | "symbol-tree@>= 3.1.0 < 4.0.0":
2323 |   version "3.2.2"
2324 |   resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
2325 | 
2326 | tar-pack@^3.4.0:
2327 |   version "3.4.0"
2328 |   resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
2329 |   dependencies:
2330 |     debug "^2.2.0"
2331 |     fstream "^1.0.10"
2332 |     fstream-ignore "^1.0.5"
2333 |     once "^1.3.3"
2334 |     readable-stream "^2.1.4"
2335 |     rimraf "^2.5.1"
2336 |     tar "^2.2.1"
2337 |     uid-number "^0.0.6"
2338 | 
2339 | tar@^2.2.1:
2340 |   version "2.2.1"
2341 |   resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
2342 |   dependencies:
2343 |     block-stream "*"
2344 |     fstream "^1.0.2"
2345 |     inherits "2"
2346 | 
2347 | to-fast-properties@^1.0.1:
2348 |   version "1.0.3"
2349 |   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
2350 | 
2351 | to-iso-string@0.0.2:
2352 |   version "0.0.2"
2353 |   resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1"
2354 | 
2355 | tough-cookie@^2.2.0, tough-cookie@~2.3.0:
2356 |   version "2.3.2"
2357 |   resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
2358 |   dependencies:
2359 |     punycode "^1.4.1"
2360 | 
2361 | tr46@~0.0.1:
2362 |   version "0.0.3"
2363 |   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
2364 | 
2365 | trim-newlines@^1.0.0:
2366 |   version "1.0.0"
2367 |   resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
2368 | 
2369 | trim-right@^1.0.1:
2370 |   version "1.0.1"
2371 |   resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
2372 | 
2373 | tunnel-agent@^0.6.0:
2374 |   version "0.6.0"
2375 |   resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
2376 |   dependencies:
2377 |     safe-buffer "^5.0.1"
2378 | 
2379 | tweetnacl@^0.14.3, tweetnacl@~0.14.0:
2380 |   version "0.14.5"
2381 |   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
2382 | 
2383 | type-check@~0.3.2:
2384 |   version "0.3.2"
2385 |   resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
2386 |   dependencies:
2387 |     prelude-ls "~1.1.2"
2388 | 
2389 | type-detect@0.1.1:
2390 |   version "0.1.1"
2391 |   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
2392 | 
2393 | type-detect@^1.0.0:
2394 |   version "1.0.0"
2395 |   resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
2396 | 
2397 | ua-parser-js@^0.7.9:
2398 |   version "0.7.12"
2399 |   resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
2400 | 
2401 | uid-number@^0.0.6:
2402 |   version "0.0.6"
2403 |   resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
2404 | 
2405 | user-home@^1.1.1:
2406 |   version "1.1.1"
2407 |   resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190"
2408 | 
2409 | util-deprecate@~1.0.1:
2410 |   version "1.0.2"
2411 |   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
2412 | 
2413 | uuid@^3.0.0:
2414 |   version "3.0.1"
2415 |   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
2416 | 
2417 | v8flags@^2.0.10:
2418 |   version "2.1.1"
2419 |   resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4"
2420 |   dependencies:
2421 |     user-home "^1.1.1"
2422 | 
2423 | validate-npm-package-license@^3.0.1:
2424 |   version "3.0.1"
2425 |   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
2426 |   dependencies:
2427 |     spdx-correct "~1.0.0"
2428 |     spdx-expression-parse "~1.0.0"
2429 | 
2430 | verror@1.3.6:
2431 |   version "1.3.6"
2432 |   resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
2433 |   dependencies:
2434 |     extsprintf "1.0.2"
2435 | 
2436 | webidl-conversions@^2.0.0:
2437 |   version "2.0.1"
2438 |   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-2.0.1.tgz#3bf8258f7d318c7443c36f2e169402a1a6703506"
2439 | 
2440 | whatwg-fetch@>=0.10.0:
2441 |   version "2.0.3"
2442 |   resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
2443 | 
2444 | whatwg-url-compat@~0.6.5:
2445 |   version "0.6.5"
2446 |   resolved "https://registry.yarnpkg.com/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz#00898111af689bb097541cd5a45ca6c8798445bf"
2447 |   dependencies:
2448 |     tr46 "~0.0.1"
2449 | 
2450 | wide-align@^1.1.0:
2451 |   version "1.1.2"
2452 |   resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
2453 |   dependencies:
2454 |     string-width "^1.0.2"
2455 | 
2456 | wordwrap@~1.0.0:
2457 |   version "1.0.0"
2458 |   resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
2459 | 
2460 | wrappy@1:
2461 |   version "1.0.2"
2462 |   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
2463 | 
2464 | "xml-name-validator@>= 2.0.1 < 3.0.0":
2465 |   version "2.0.1"
2466 |   resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635"
2467 | 
--------------------------------------------------------------------------------