From cee98c94cbb0d70b432ae40435a38888dbef2e7f Mon Sep 17 00:00:00 2001 From: cburbank Date: Sun, 15 Jan 2017 16:30:27 -0500 Subject: [PATCH 001/165] feat(props): Add onError callback prop Users can provide a custom callback function to be executed when PlacesServiceStatus is not OK. --- README.md | 7 +++++++ src/PlacesAutocomplete.js | 7 ++++++- src/tests/index.spec.js | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 93a66877..736034cd 100644 --- a/README.md +++ b/README.md @@ -235,6 +235,13 @@ Default: `false` You can set `hideLabel` to `true` to not render the label element +#### onError +Type: `function` +Required: `false` +Default: `() => console.error('place autocomplete failed')` + +You can pass `onError` prop to customize the behavior when `google.maps.places.PlacesServiceStatus` is not `OK` (e.g., no predictions are found) + #### onSelect Type: `function` Required: `false`, diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 99d7e3db..9c466d9e 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -49,7 +49,10 @@ class PlacesAutocomplete extends React.Component { } autocompleteCallback(predictions, status) { - if (status != this.autocompleteOK) { console.error('place autocomplete failed'); return; } + if (status != this.autocompleteOK) { + this.props.onError() + return + } this.setState({ autocompleteItems: predictions.map((p, idx) => ({ suggestion: p.description, @@ -249,6 +252,7 @@ PlacesAutocomplete.propTypes = { children: React.PropTypes.element, value: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired, + onError: React.PropTypes.func, onSelect: React.PropTypes.func, placeholder: React.PropTypes.string, hideLabel: React.PropTypes.bool, @@ -285,6 +289,7 @@ PlacesAutocomplete.propTypes = { }; PlacesAutocomplete.defaultProps = { + onError: () => console.error('place autocomplete failed'), placeholder: 'Address', hideLabel: false, autoFocus: false, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index bbb7eec0..6d1f3f4e 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -27,6 +27,21 @@ describe('PlacesAutocomplete callbacks', () => { const wrapper = mount( {}} />) expect(PlacesAutocomplete.prototype.componentDidMount.calledOnce).to.equal(true) }) + + it('executes onError callback passed in as prop when status is not OK', () => { + const spy = sinon.spy() + const wrapper = mount( {}} />) + wrapper.instance().autocompleteCallback([], 'error') + expect(spy.calledOnce).to.equal(true) + }) + + it('executes default onError function when there is no custom prop and status is not OK', () => { + sinon.stub(console, 'error') + const wrapper = mount( {}} />) + wrapper.instance().autocompleteCallback([], 'error') + expect(console.error.calledOnce).to.equal(true) + expect(console.error.calledWith('place autocomplete failed')).to.equal(true) + }) }); describe('PlacesAutocomplete props', () => { From c7b320afc0bb2be9d7c6e64386fedda68875e4d3 Mon Sep 17 00:00:00 2001 From: cburbank Date: Sun, 15 Jan 2017 17:40:21 -0500 Subject: [PATCH 002/165] feat(props): Add clearItemsOnError prop If true, autocomplete items will be cleared when PlacesServiceStatus is not OK. Defaults to false. --- README.md | 15 +++++++++++++-- src/PlacesAutocomplete.js | 7 +++++-- src/tests/index.spec.js | 31 ++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 736034cd..7a42ee42 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,8 @@ export default SimpleForm * styles * placeholder * hideLabel +* onError +* clearItemsOnError * onSelect * options * autoFocus @@ -238,9 +240,18 @@ You can set `hideLabel` to `true` to not render the label element #### onError Type: `function` Required: `false` -Default: `() => console.error('place autocomplete failed')` +Default: `(status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://github.com/kenny-hibino/react-places-autocomplete)\nStatus: ', status)` -You can pass `onError` prop to customize the behavior when `google.maps.places.PlacesServiceStatus` is not `OK` (e.g., no predictions are found) +You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) + +Receives `status` as a parameter + +#### clearItemsOnError +Type: `boolean` +Required: `false` +Default: `false` + +You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK #### onSelect Type: `function` diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 9c466d9e..8a0d2828 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -50,7 +50,8 @@ class PlacesAutocomplete extends React.Component { autocompleteCallback(predictions, status) { if (status != this.autocompleteOK) { - this.props.onError() + this.props.onError(status) + if (this.props.clearItemsOnError) { this.clearAutocomplete() } return } this.setState({ @@ -253,6 +254,7 @@ PlacesAutocomplete.propTypes = { value: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired, onError: React.PropTypes.func, + clearItemsOnError: React.PropTypes.bool, onSelect: React.PropTypes.func, placeholder: React.PropTypes.string, hideLabel: React.PropTypes.bool, @@ -289,7 +291,8 @@ PlacesAutocomplete.propTypes = { }; PlacesAutocomplete.defaultProps = { - onError: () => console.error('place autocomplete failed'), + clearItemsOnError: false, + onError: (status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), placeholder: 'Address', hideLabel: false, autoFocus: false, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 6d1f3f4e..a4bd0f5b 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -31,16 +31,16 @@ describe('PlacesAutocomplete callbacks', () => { it('executes onError callback passed in as prop when status is not OK', () => { const spy = sinon.spy() const wrapper = mount( {}} />) - wrapper.instance().autocompleteCallback([], 'error') + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(spy.calledOnce).to.equal(true) + expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) }) it('executes default onError function when there is no custom prop and status is not OK', () => { sinon.stub(console, 'error') const wrapper = mount( {}} />) - wrapper.instance().autocompleteCallback([], 'error') + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(console.error.calledOnce).to.equal(true) - expect(console.error.calledWith('place autocomplete failed')).to.equal(true) }) }); @@ -87,6 +87,31 @@ describe('autocomplete dropdown', () => { expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) expect(wrapper.find('.autocomplete-item')).to.have.length(3) }) + + it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { + const initialItems = [{ + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0 + }] + const wrapper = shallow( {}} clearItemsOnError={true}/>) + wrapper.setState({ autocompleteItems: initialItems }) + wrapper.instance().autocompleteCallback([], 'error') + expect(wrapper.find('.autocomplete-item')).to.have.length(0) + }) + + it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { + const initialItems = [{ + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0 + }] + wrapper.setState({ autocompleteItems: initialItems }) + wrapper.instance().autocompleteCallback([], 'error') + expect(wrapper.find('.autocomplete-item')).to.have.length(1) + }) }) describe('custom classNames, placeholder', () => { From 60bb5e70cd1c7a1de233986df6cca3502336a184 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Dec 2016 16:44:43 +0900 Subject: [PATCH 003/165] Add npm scripts postpublish and deploy for publishing Github Page --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5db3d6bc..7b2dea25 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "demo": "webpack-dev-server --config demo/webpack.config.js --debug --content-base demo --inline --hot --colors", "demo:test": "mocha demo/tests/index.spec.js --compilers js:babel-register", "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", - "demo:deploy": "gh-pages -d demo/dist" + "demo:deploy": "gh-pages -d demo/dist", + "deploy": "gh-pages -d demo:build", + "postpublish": "npm run deploy" }, "repository": { "type": "git", From b20c199af87315efd6327606ea1b4eb4f4a9d7fe Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 3 Feb 2017 20:56:08 -0800 Subject: [PATCH 004/165] chore(demo): Change input styles in Demo --- demo/Demo.js | 8 +++++--- demo/app.css | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index 64b86cdb..f3e1bfdb 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -65,11 +65,11 @@ class Demo extends React.Component { const cssClasses = { root: 'form-group', label: 'form-label', - input: 'form-control', - autocompleteContainer: 'autocomplete-container' + input: 'Demo__search-input', + autocompleteContainer: 'Demo__autocomplete-container' } - const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) + const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) return (
@@ -91,6 +91,8 @@ class Demo extends React.Component { classNames={cssClasses} autocompleteItem={AutocompleteItem} autoFocus={true} + placeholder="Search Places" + hideLabel={true} /> {this.state.loading ?
Loading...
: null} {!this.state.loading && this.state.geocodeResults ? diff --git a/demo/app.css b/demo/app.css index ff20bfd8..0353711e 100644 --- a/demo/app.css +++ b/demo/app.css @@ -17,14 +17,42 @@ body, #root, .page-wrapper { border-color: #e53935; } -.fa.fa-map-marker.suggestion { - margin-right: 5px; +.Demo__suggestion-icon { + margin-right: 8px; } .fa.fa-map-marker.header { color: #e53935; } +.Demo__search-input, +.Demo__search-input:focus, +.Demo__search-input:active { + box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16), 0 0 0 1px rgba(0,0,0,0.08); + border: honeydew; + display: block; + width: 100%; + padding: 16px; + font-size: 16px; + border-radius: 2px; + outline: none; +} + +/* TODO: Allow user to override default styles without using !important flag */ +.Demo__autocomplete-container { + border-bottom: honeydew !important; + border-left: honeydew !important; + border-right: honeydew !important; + border-top: 1px solid #e6e6e6 !important; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); + border-radius: 0 0 2px 2px; +} + +.Demo__suggestion-item { + padding: 4px; + text-align: left; +} + @media (max-width: 480px) { .autocomplete-container { text-align: left; From 892d787c4918a6491f32de48ed55050cb79f503e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 3 Feb 2017 21:05:37 -0800 Subject: [PATCH 005/165] chore(demo): Remove jumbotron in Demo --- demo/Demo.js | 18 ++++++++---------- demo/app.css | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index f3e1bfdb..bb1bc76f 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -72,16 +72,14 @@ class Demo extends React.Component { const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) return (
-
-
-

react-places-autocomplete

-

A React component to build a customized UI for Google Maps Places Autocomplete

-
- - -  View on GitHub - -
+
+

react-places-autocomplete

+

A React component to build a customized UI for Google Maps Places Autocomplete

+
+ + +  View on GitHub +
Date: Fri, 3 Feb 2017 21:34:14 -0800 Subject: [PATCH 006/165] chore(demo): Change loader in Demo --- demo/Demo.js | 2 +- demo/app.css | 71 ++++------------------------------------------------ 2 files changed, 6 insertions(+), 67 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index bb1bc76f..58b1218a 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -92,7 +92,7 @@ class Demo extends React.Component { placeholder="Search Places" hideLabel={true} /> - {this.state.loading ?
Loading...
: null} + {this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ?
{this.state.geocodeResults}
: null} diff --git a/demo/app.css b/demo/app.css index 096e4e6c..c2814de7 100644 --- a/demo/app.css +++ b/demo/app.css @@ -68,6 +68,11 @@ body, #root, .page-wrapper { text-align: left; } +.Demo__spinner { + color: #18bc9c !important; + font-size: 30px; +} + @media (max-width: 480px) { .autocomplete-container { text-align: left; @@ -127,69 +132,3 @@ body, #root, .page-wrapper { from { opacity: 0; } to { opacity: 1; } } - -.loader, -.loader:before, -.loader:after { - background: rgba(45, 62, 80, 0.54); - -webkit-animation: load1 1s infinite ease-in-out; - animation: load1 1s infinite ease-in-out; - width: 1em; - height: 4em; -} - -.loader { - color: rgba(45, 62, 80, 0.54); - text-indent: -9999em; - margin: 3rem auto; - position: relative; - font-size: 11px; - -webkit-transform: translateZ(0); - -ms-transform: translateZ(0); - transform: translateZ(0); - -webkit-animation-delay: -0.16s; - animation-delay: -0.16s; -} - -.loader:before, -.loader:after { - position: absolute; - top: 0; - content: ''; -} - -.loader:before { - left: -1.5em; - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; -} - -.loader:after { - left: 1.5em; -} - -@-webkit-keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} - -@keyframes load1 { - 0%, - 80%, - 100% { - box-shadow: 0 0; - height: 4em; - } - 40% { - box-shadow: 0 -2em; - height: 5em; - } -} From 6e9f33b66616785d8bdbe54437224e217dd04f9a Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 3 Feb 2017 21:35:12 -0800 Subject: [PATCH 007/165] chore(demo): Add Fork me on Github ribbon --- demo/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/demo/index.html b/demo/index.html index 3c5faa71..c26ef979 100644 --- a/demo/index.html +++ b/demo/index.html @@ -13,6 +13,7 @@ + Fork me on GitHub
From 6daffd3ca352145d5b97be1007e8eadd004a4a58 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 3 Feb 2017 21:49:14 -0800 Subject: [PATCH 008/165] chore(demo): Change background to very light grayish white --- demo/app.css | 1 + 1 file changed, 1 insertion(+) diff --git a/demo/app.css b/demo/app.css index c2814de7..c47f32c5 100644 --- a/demo/app.css +++ b/demo/app.css @@ -10,6 +10,7 @@ html { body, #root, .page-wrapper { height: 100%; + background-color: #fcfcfc; } .btn:hover { From 63887bfff1f835b39806b925de9e9cedd87c56bf Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 12:10:08 -0800 Subject: [PATCH 009/165] feat(autocomplete): Allow esc key to clear autocomplete dropdown --- src/PlacesAutocomplete.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 8a0d2828..9fd7e03d 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -124,6 +124,7 @@ class PlacesAutocomplete extends React.Component { const ARROW_UP = 38 const ARROW_DOWN = 40 const ENTER_KEY = 13 + const ESC_KEY = 27 switch (event.keyCode) { case ENTER_KEY: @@ -136,6 +137,9 @@ class PlacesAutocomplete extends React.Component { case ARROW_UP: this._handleUpKey() break + case ESC_KEY: + this.clearAutocomplete() + break } } From 382c460615a5b2a430f10f2e6116524a02946c35 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 12:34:25 -0800 Subject: [PATCH 010/165] chore(defaultStyles): Extract default styles to a separate file --- src/PlacesAutocomplete.js | 32 +------------------------------- src/defaultStyles.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 31 deletions(-) create mode 100644 src/defaultStyles.js diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 9fd7e03d..aa0ab2ca 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -1,36 +1,6 @@ import React from 'react' +import defaultStyles from './defaultStyles' -const defaultStyles = { - root: { - position: 'relative', - paddingBottom: '0px', - }, - autocompleteOverlay: { - position: 'fixed', - top: 0, - right: 0, - bottom: 0, - left: 0, - zIndex: 9998, - }, - autocompleteContainer: { - position: 'absolute', - top: '100%', - backgroundColor: 'white', - border: '1px solid #555', - width: '100%', - zIndex: 9999, - }, - autocompleteItem: { - backgroundColor: '#ffffff', - padding: '10px', - color: '#555', - cursor: 'pointer', - }, - autocompleteItemActive: { - backgroundColor: '#fafafa' - } -} class PlacesAutocomplete extends React.Component { constructor(props) { diff --git a/src/defaultStyles.js b/src/defaultStyles.js new file mode 100644 index 00000000..bfa0a44c --- /dev/null +++ b/src/defaultStyles.js @@ -0,0 +1,33 @@ +const defaultStyles = { + root: { + position: 'relative', + paddingBottom: '0px', + }, + autocompleteOverlay: { + position: 'fixed', + top: 0, + right: 0, + bottom: 0, + left: 0, + zIndex: 9998, + }, + autocompleteContainer: { + position: 'absolute', + top: '100%', + backgroundColor: 'white', + border: '1px solid #555', + width: '100%', + zIndex: 9999, + }, + autocompleteItem: { + backgroundColor: '#ffffff', + padding: '10px', + color: '#555', + cursor: 'pointer', + }, + autocompleteItemActive: { + backgroundColor: '#fafafa' + } +} + +export default defaultStyles From 924a8de7ed95f5422d50106ffdd441a5cdbb3d8b Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 12:49:17 -0800 Subject: [PATCH 011/165] feat(autocompleteItem): Allow custom autocompleteItem to use formatted suggestion strings --- src/PlacesAutocomplete.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index aa0ab2ca..25a943b0 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -24,16 +24,22 @@ class PlacesAutocomplete extends React.Component { if (this.props.clearItemsOnError) { this.clearAutocomplete() } return } + this.setState({ autocompleteItems: predictions.map((p, idx) => ({ suggestion: p.description, placeId: p.place_id, active: false, - index: idx + index: idx, + formattedSuggestion: this._formattedSuggestion(p.structured_formatting), })) }) } + _formattedSuggestion(structured_formatting) { + return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } + } + clearAutocomplete() { this.setState({ autocompleteItems: [] }) } @@ -173,7 +179,7 @@ class PlacesAutocomplete extends React.Component { onMouseOver={() => this._setActiveItemAtIndex(p.index)} onClick={() => this.selectAddress(p.suggestion)} style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion })} + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
))}
From 68bb3c001185d0c0609790505b9107b79ed327ce Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 15:56:33 -0800 Subject: [PATCH 012/165] docs(readme): Update readme to document `formattedSuggestion` key in autocompleteItem --- README.md | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7a42ee42..30a89f24 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,14 @@ Please see the example above Type: `Functional React Component`, Required: `false` -The function takes props with `suggestion` key (see the example below). +The function takes props with `suggestion`, `formattedSuggestion` keys (see the example below). We highly recommend that you create your own custom `AutocompleteItem` and pass it as a prop. ```js -// autocompleteItem example (with font-awesome icon) +/*********************************************** + Example #1 + autocompleteItem example with `suggestion` +************************************************/ render() { const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) @@ -138,6 +141,30 @@ render() { autocompleteItem={AutocompleteItem} /> ) +} + +/*************************************************** + Example #2 + autocompleteItem example with `formattedSuggestion` +****************************************************/ +render() { + const AutocompleteItem = ({ formattedSuggestion }) => ( +
+ { formattedSuggestion.mainText }{' '} + { formattedSuggestion.secondaryText } +
+ ) + + return ( + + ) +} + + } ``` @@ -251,7 +278,7 @@ Type: `boolean` Required: `false` Default: `false` -You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK +You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK #### onSelect Type: `function` @@ -289,7 +316,7 @@ const options = { #### autoFocus Type: `boolean` Required: `false` -Default: `false` +Default: `false` ### `geocodeByAddress` API From 47f9398aee3b8b33631f8c45f04bf001ff16af62 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 15:47:42 -0800 Subject: [PATCH 013/165] chore(demo): Update AutocompleteItem to use formatted suggestion --- demo/Demo.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/demo/Demo.js b/demo/Demo.js index 58b1218a..528a08ea 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -69,7 +69,13 @@ class Demo extends React.Component { autocompleteContainer: 'Demo__autocomplete-container' } - const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) + const AutocompleteItem = ({ formattedSuggestion }) => ( +
+ + {formattedSuggestion.mainText}{' '} + {formattedSuggestion.secondaryText} +
) + return (
From 7f7aed36933c59440b206e009e6d76fab18d29c7 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 16:00:16 -0800 Subject: [PATCH 014/165] chore(readme): Fix syntax error in readme example --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 30a89f24..72b9f8f0 100644 --- a/README.md +++ b/README.md @@ -163,9 +163,6 @@ render() { /> ) } - - -} ``` #### children From 2e4b17294092c2f66b00e3374d0f3a02d5da4511 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 17:31:51 -0800 Subject: [PATCH 015/165] feat(placeId): Allow user to use placeId Provide placeId using onSelect callback function. Also added `geocodeByPlceId` helper function as a named export. #13 --- README.md | 45 ++++++++++++++++++++++++++++++++++++--- src/PlacesAutocomplete.js | 13 ++++++----- src/index.js | 5 +++-- src/utils.js | 19 +++++++++++++++++ 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 72b9f8f0..bdc72be9 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,10 @@ The React component is exported as a default export import PlacesAutocomplete from 'react-places-autocomplete' ``` -`geocodeByAddress` utility function is a named export +`geocodeByAddress` and `geocodeByPlaceId` utility functions are named exports ```js -import { geocodeByAddress } from 'react-places-autocomplete' +import { geocodeByAddress, geocodeByPlaceId } from 'react-places-autocomplete' ``` ### Demo @@ -285,6 +285,23 @@ Default: `null` You can pass a function that gets called instead of `onChange` function when user hits the Enter key or clicks on an autocomplete item. +The function takes two positional arguments. First argument is `address`, second is `placeId`. + +```js +const handleSelect = (address, placeId) => { + this.setState({ address, placeId }) + + // You can do other things with address string or placeId. For example, geocode :) +} + +// Pass this function via onSelect prop. + +``` + #### options Type: `object` Required: `false` @@ -325,7 +342,29 @@ geocodeByAddress(address, callback) Type: `String`, Required: `true` -String that gets passed to Google Maps Geocoder +String that gets passed to Google Maps [Geocoder](https://developers.google.com/maps/documentation/javascript/geocoding) + +#### callback +Type: `Function`, +Required: `true` + +Two arguments will be passed to the callback. + +First argument is an error object, set to `null` when there's no error. + +Second argument is an object with `lat` and `lng` keys + +### `geocodeByPlaceId` API + +```js +geocodeByPlaceId(placeId, callback) +``` + +#### placeId +Type: `String`, +Required: `true` + +String that gets passed to Google Maps [Geocoder](https://developers.google.com/maps/documentation/javascript/geocoding) #### callback Type: `Function`, diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 25a943b0..d74a4542 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -44,13 +44,13 @@ class PlacesAutocomplete extends React.Component { this.setState({ autocompleteItems: [] }) } - selectAddress(address) { + selectAddress(address, placeId) { this.clearAutocomplete() - this._handleSelect(address) + this._handleSelect(address, placeId) } - _handleSelect(address) { - this.props.onSelect ? this.props.onSelect(address) : this.props.onChange(address) + _handleSelect(address, placeId) { + this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) } _getActiveItem() { @@ -67,8 +67,7 @@ class PlacesAutocomplete extends React.Component { const activeItem = this._getActiveItem() if (activeItem === undefined) { return } - this.clearAutocomplete() - this._handleSelect(activeItem.suggestion) + this.selectAddress(activeItem.suggestion, activeItem.placeId) } _handleDownKey() { @@ -177,7 +176,7 @@ class PlacesAutocomplete extends React.Component {
this._setActiveItemAtIndex(p.index)} - onClick={() => this.selectAddress(p.suggestion)} + onClick={() => this.selectAddress(p.suggestion, p.placeId)} style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
diff --git a/src/index.js b/src/index.js index 29c9cd21..3ae6caa1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,9 @@ import PlacesAutocomplete from './PlacesAutocomplete' -import { geocodeByAddress } from './utils' +import { geocodeByAddress, geocodeByPlaceId } from './utils' export { - geocodeByAddress + geocodeByAddress, + geocodeByPlaceId, } export default PlacesAutocomplete diff --git a/src/utils.js b/src/utils.js index bb7fb343..cf277481 100644 --- a/src/utils.js +++ b/src/utils.js @@ -18,3 +18,22 @@ export const geocodeByAddress = (address, callback) => { callback(null, latLng, placeId) }) } + +export const geocodeByPlaceId = (placeId, callback) => { + const geocoder = new google.maps.Geocoder() + const OK = google.maps.GeocoderStatus.OK + + geocoder.geocode({ placeId }, (results, status) => { + if (status !== OK) { + callback({ status }, null, null) + return + } + + const latLng = { + lat: results[0].geometry.location.lat(), + lng: results[0].geometry.location.lng(), + } + + callback(null, latLng, results) + }) +} From a69722bf9fcd82b34b76976c79d37c4e7cafac89 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Feb 2017 17:53:17 -0800 Subject: [PATCH 016/165] feat(geocode): Provide entire results from Google API through geocoder callback function Resolves #15 --- README.md | 28 ++++++++++++++++++++++++++-- src/utils.js | 6 ++---- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bdc72be9..6bbcee73 100644 --- a/README.md +++ b/README.md @@ -348,12 +348,25 @@ String that gets passed to Google Maps [Geocoder](https://developers.google.com/ Type: `Function`, Required: `true` -Two arguments will be passed to the callback. +Three arguments will be passed to the callback. First argument is an error object, set to `null` when there's no error. Second argument is an object with `lat` and `lng` keys +Third argument (optional) is entire payload from Google API + +```js +import { geocodeByAddress } from 'react-places-autocomplete' + +geocodeByAddress('Los Angeles, CA', (error, { lat, lng }, results) => { + if (error) { return } + + console.log('Geocoding success!', { lat, lng }) + console.log('Entire payload from Google API', results) +}) +``` + ### `geocodeByPlaceId` API ```js @@ -370,13 +383,24 @@ String that gets passed to Google Maps [Geocoder](https://developers.google.com/ Type: `Function`, Required: `true` -Two arguments will be passed to the callback. +Three arguments will be passed to the callback. First argument is an error object, set to `null` when there's no error. Second argument is an object with `lat` and `lng` keys +Third argument (optional) is entire payload from Google API + +```js +import { geocodeByPlaceId } from 'react-places-autocomplete' +geocodeByPlaceId('ChIJE9on3F3HwoAR9AhGJW_fL-I', (error, { lat, lng }, results) => { + if (error) { return } + + console.log('Geocoding success!', { lat, lng }) + console.log('Entire payload from Google API', results) +}) +``` ### Discussion Join us on [Gitter](https://gitter.im/react-places-autocomplete/Lobby) if you are interested in contributing! diff --git a/src/utils.js b/src/utils.js index cf277481..5527c709 100644 --- a/src/utils.js +++ b/src/utils.js @@ -4,7 +4,7 @@ export const geocodeByAddress = (address, callback) => { geocoder.geocode({ address }, (results, status) => { if (status !== OK) { - callback({ status }, null, null) + callback({ status }, null, results) return } @@ -13,9 +13,7 @@ export const geocodeByAddress = (address, callback) => { lng: results[0].geometry.location.lng(), } - const placeId = results[0].place_id; - - callback(null, latLng, placeId) + callback(null, latLng, results) }) } From 5e0593d7b93683016418d4c358e0af62abef92cf Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 6 Feb 2017 20:59:40 -0800 Subject: [PATCH 017/165] feat(props): Remove children prop Removed a feature which allowed user to pass custom input element as children prop to simplify the library. Removed children prop --- README.md | 26 -------------------------- src/PlacesAutocomplete.js | 21 ++++----------------- src/tests/index.spec.js | 33 --------------------------------- 3 files changed, 4 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 6bbcee73..c6f44904 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ export default SimpleForm #### Optional Props: * autocompleteItem -* children * classNames * styles * placeholder @@ -165,31 +164,6 @@ render() { } ``` -#### children -Type: `Element` -Required: `false` - -You can add autocomplete functionality to an existing input element by wrapping it in ``. -The wrapper will pass `onChange`, `onKeyDown`, and `value` props down to the child component. - -```js -// custom input element example -import MyCustomInput from 'my-custom-input' - -... - -render() { - return ( - - - - ) -} -``` - #### classNames Type: `Object`, Required: `false` diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d74a4542..aafe9b92 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -185,17 +185,7 @@ class PlacesAutocomplete extends React.Component { ) } - renderCustomInput() { - const { children, autoFocus, value } = this.props - return React.cloneElement(children, { - onChange: this.handleInputChange, - onKeyDown: this.handleInputKeyDown, - autoFocus: autoFocus, - value - }) - } - - renderDefaultInput() { + renderInput() { const { classNames, placeholder, styles, value, autoFocus } = this.props return ( + className={classNames.root || ''}> {this.renderLabel()} - {children ? this.renderCustomInput() : this.renderDefaultInput()} + {this.renderInput()} {this.renderOverlay()} {this.renderAutocomplete()}
@@ -229,7 +217,6 @@ class PlacesAutocomplete extends React.Component { } PlacesAutocomplete.propTypes = { - children: React.PropTypes.element, value: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired, onError: React.PropTypes.func, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index a4bd0f5b..ddeaca88 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -233,39 +233,6 @@ describe('AutocompletionRequest options', () => { }) }) -describe('custom input component', () => { - it('renders a custom input component passed as a child', () => { - const wrapper = shallow( {}}> {}}/>) - expect(wrapper.find('.test-input')).to.have.length(1) - }) - - it('adds the correct props to the child component', () => { - const wrapper = shallow( {}}>) - expect(wrapper.find('.test-input').props().onChange).to.be.defined - expect(wrapper.find('.test-input').props().onKeyDown).to.be.defined - expect(wrapper.find('.test-input').props().value).to.be.defined - }) - - it('correctly sets the value prop of the custom input component', () => { - const wrapper = shallow( {}}> {}}/>) - expect(wrapper.find('.test-input').props().value).to.equal('LA') - }) - - it('executes the onChange callback when the custom input is changed', () => { - const spy = sinon.spy() - const wrapper = shallow() - wrapper.find('.test-input').simulate('change', { target: { value: null } }) - expect(spy.calledOnce).to.equal(true) - }) - - it('executes handleInputKeyDown when a keyDown event happens on the custom input', () => { - const spy = sinon.spy(PlacesAutocomplete.prototype, 'handleInputKeyDown') - const wrapper = shallow( {}}>) - wrapper.find('.test-input').simulate('keyDown', { keyCode: null }) - expect(spy.calledOnce).to.equal(true) - }) -}) - describe('autoFocus prop', () => { it('automatically gives focus when set to true', () => { const wrapper = mount( {}} autoFocus={true} />) From 5de1aadd5f1d20b0b052fe6c7e72cf9838bb2204 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 6 Feb 2017 21:13:40 -0800 Subject: [PATCH 018/165] chore(readme): Update readme --- README.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c6f44904..02623bf8 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ A React component to build a customized UI for Google Maps Places Autocomplete ( To install the stable version ```sh -npm install --save react-places-autocomplete +npm install react-places-autocomplete --save ``` The React component is exported as a default export @@ -33,6 +33,12 @@ import { geocodeByAddress, geocodeByPlaceId } from 'react-places-autocomplete' ### Demo See live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hibino.github.io/react-places-autocomplete/) +To build the example locally, clone this repo and then run: + +```sh +npm run demo +``` + ### Getting Started To use this component, you are going to need to load [Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript/) @@ -54,17 +60,14 @@ class SimpleForm extends React.Component { super(props) this.state = { address: 'San Francisco, CA' } this.onChange = (address) => this.setState({ address }) - this.handleFormSubmit = this.handleFormSubmit.bind(this) } - handleFormSubmit(event) { + handleFormSubmit = (event) => { event.preventDefault() const { address } = this.state geocodeByAddress(address, (err, { lat, lng }) => { - if (err) { - console.log('Oh no!', err) - } + if (err) { console.log('Oh no!', err) } console.log(`Yay! got latitude and longitude for ${address}`, { lat, lng }) }) @@ -229,30 +232,29 @@ Default: `"Address"` You can pass `placeholder` prop to customize input's placeholder text #### hideLabel -Type: `boolean` +Type: `Boolean` Required: `false`, Default: `false` You can set `hideLabel` to `true` to not render the label element #### onError -Type: `function` +Type: `Function` Required: `false` -Default: `(status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://github.com/kenny-hibino/react-places-autocomplete)\nStatus: ', status)` You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) -Receives `status` as a parameter +Function takes `status` as a parameter #### clearItemsOnError -Type: `boolean` +Type: `Boolean` Required: `false` Default: `false` You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK #### onSelect -Type: `function` +Type: `Function` Required: `false`, Default: `null` @@ -277,7 +279,7 @@ const handleSelect = (address, placeId) => { ``` #### options -Type: `object` +Type: `Object` Required: `false` Default: `{}` @@ -302,7 +304,7 @@ const options = { ``` #### autoFocus -Type: `boolean` +Type: `Boolean` Required: `false` Default: `false` From 5910c8c16a114bc4ebabc21f81342cc866c6a995 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 9 Feb 2017 22:59:38 -0800 Subject: [PATCH 019/165] feat(props): Add onEnterKeyDown props Allow user to pass callback function that gets called when Enter key is pressed when no item is selected in the dropdown. --- README.md | 26 ++++++++++++++++++++++++++ src/PlacesAutocomplete.js | 15 +++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02623bf8..51f42857 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ export default SimpleForm * onError * clearItemsOnError * onSelect +* onEnterKeyDown * options * autoFocus @@ -278,6 +279,31 @@ const handleSelect = (address, placeId) => { /> ``` +#### onEnterKeyDown +Type: `Function` +Required: `false` +Deafult: `noop` + +You can pass a callback function that gets called when pressing down Enter key when no item in the dropdown is selected. +The function takes one argument, the value in the input field. + +```js +const handleEnter = (address) => { + geocodeByAddress(address, (err, { lat, lng }, results) => { + if (err) { console.error('Error'); return; } + + console.log("Geocode success", { lat, lng }) + }) +} + +// Pass this function via onEnterKeyDown prop. + +``` + #### options Type: `Object` Required: `false` diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index aafe9b92..d08ac392 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -65,9 +65,20 @@ class PlacesAutocomplete extends React.Component { _handleEnterKey() { const activeItem = this._getActiveItem() - if (activeItem === undefined) { return } + if (activeItem === undefined) { + this._handleEnterKeyWithoutActiveItem() + } else { + this.selectAddress(activeItem.suggestion, activeItem.placeId) + } + } - this.selectAddress(activeItem.suggestion, activeItem.placeId) + _handleEnterKeyWithoutActiveItem() { + if (this.props.onEnterKeyDown) { + this.props.onEnterKeyDown(this.props.value) + this.clearAutocomplete() + } else { + return //noop + } } _handleDownKey() { From 3f3f47164a6e8679faa463a80989c8c3b87de068 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 9 Feb 2017 23:00:20 -0800 Subject: [PATCH 020/165] feat(onBlur): Clear autocomplete on blur event --- src/PlacesAutocomplete.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d08ac392..5665fe6f 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -206,6 +206,7 @@ class PlacesAutocomplete extends React.Component { value={value} onChange={this.handleInputChange} onKeyDown={this.handleInputKeyDown} + onBlur={() => this.clearAutocomplete()} style={styles.input} autoFocus={autoFocus} /> From 80a647f411f927c7c8b3d57202e9128853ec58fb Mon Sep 17 00:00:00 2001 From: Mehdi Beddiaf Date: Fri, 10 Feb 2017 18:25:08 +0100 Subject: [PATCH 021/165] Fix address selection on click --- src/PlacesAutocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 5665fe6f..63d60a14 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -187,7 +187,7 @@ class PlacesAutocomplete extends React.Component {
this._setActiveItemAtIndex(p.index)} - onClick={() => this.selectAddress(p.suggestion, p.placeId)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
From 3f06b507297e0b298559b03cd5730b2e9e6a4606 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 10 Feb 2017 09:44:09 -0800 Subject: [PATCH 022/165] fix(onBlur): Remove onBlur handler #26 --- src/PlacesAutocomplete.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 5665fe6f..d08ac392 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -206,7 +206,6 @@ class PlacesAutocomplete extends React.Component { value={value} onChange={this.handleInputChange} onKeyDown={this.handleInputKeyDown} - onBlur={() => this.clearAutocomplete()} style={styles.input} autoFocus={autoFocus} /> From e62b0682d23ed1810882f66cf26ef1fb290c0f1f Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 10 Feb 2017 09:50:59 -0800 Subject: [PATCH 023/165] Fix onBlur --- src/PlacesAutocomplete.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 33272122..63d60a14 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -206,6 +206,7 @@ class PlacesAutocomplete extends React.Component { value={value} onChange={this.handleInputChange} onKeyDown={this.handleInputKeyDown} + onBlur={() => this.clearAutocomplete()} style={styles.input} autoFocus={autoFocus} /> From 2b0bb92daa0d090cd5c9a4ffa76a21f18681502a Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 11 Feb 2017 12:24:15 -0800 Subject: [PATCH 024/165] refactor(overlay): Remove overlay div --- src/PlacesAutocomplete.js | 12 ------------ src/defaultStyles.js | 8 -------- 2 files changed, 20 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 63d60a14..93aeb762 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -163,17 +163,6 @@ class PlacesAutocomplete extends React.Component { return () } - renderOverlay() { - if (this.state.autocompleteItems.length === 0) { return null } - return ( -
this.clearAutocomplete()}> -
- ) - } - renderAutocomplete() { const { autocompleteItems } = this.state const { styles } = this.props @@ -221,7 +210,6 @@ class PlacesAutocomplete extends React.Component { className={classNames.root || ''}> {this.renderLabel()} {this.renderInput()} - {this.renderOverlay()} {this.renderAutocomplete()}
) diff --git a/src/defaultStyles.js b/src/defaultStyles.js index bfa0a44c..1f0cbbc3 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -3,14 +3,6 @@ const defaultStyles = { position: 'relative', paddingBottom: '0px', }, - autocompleteOverlay: { - position: 'fixed', - top: 0, - right: 0, - bottom: 0, - left: 0, - zIndex: 9998, - }, autocompleteContainer: { position: 'absolute', top: '100%', From 9de81f30a7de82eba338e2fe00e2dd3055685e8f Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 11 Feb 2017 21:31:18 -0800 Subject: [PATCH 025/165] chore(misc): Add comment for licensing --- src/PlacesAutocomplete.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 93aeb762..e5933446 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -1,7 +1,12 @@ +/* +* Copyright (c) 2017 Ken Hibino. +* Licensed under the MIT License (MIT). +* See https://kenny-hibino.github.io/react-places-autocomplete +*/ + import React from 'react' import defaultStyles from './defaultStyles' - class PlacesAutocomplete extends React.Component { constructor(props) { super(props) @@ -145,7 +150,7 @@ class PlacesAutocomplete extends React.Component { this.props.onChange(event.target.value) if (!event.target.value) { this.clearAutocomplete() - return; + return } this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) } @@ -254,7 +259,7 @@ PlacesAutocomplete.propTypes = { ]), types: React.PropTypes.array }) -}; +} PlacesAutocomplete.defaultProps = { clearItemsOnError: false, From 324def447be4366ea6d78310e8bf392656e66fb2 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 11 Feb 2017 21:38:57 -0800 Subject: [PATCH 026/165] feat(label): Remove label element from the component Deprecate hideLabel prop and remove label element entirely from the component BREAKING CHANGE: Removed label element, and hideLabel prop --- README.md | 14 ++------------ src/PlacesAutocomplete.js | 10 ---------- src/tests/index.spec.js | 22 ---------------------- 3 files changed, 2 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 51f42857..22e2f3e8 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,6 @@ export default SimpleForm * classNames * styles * placeholder -* hideLabel * onError * clearItemsOnError * onSelect @@ -173,14 +172,13 @@ Type: `Object`, Required: `false` You can give a custom css classes to elements. -Accepted keys are `root`, `label`, `input`, `autocompleteContainer` +Accepted keys are `root`, `input`, `autocompleteContainer` ```js // classNames example render() { const cssClasses = { root: 'form-group', - label: 'form-label', input: 'form-control', autocompleteContainer: 'my-autocomplete-container' } @@ -201,14 +199,13 @@ Type `Object`, Required: `false` You can provide custom inline styles to elements. -Accepted keys are `root`, `label`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive` +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive` ```js // custom style examples render() { const myStyles = { root: { position: 'absolute' }, - label: { color: 'red' }, input: { width: '100%' }, autocompleteContainer: { backgroundColor: 'green' }, autocompleteItem: { color: 'black' }, @@ -232,13 +229,6 @@ Default: `"Address"` You can pass `placeholder` prop to customize input's placeholder text -#### hideLabel -Type: `Boolean` -Required: `false`, -Default: `false` - -You can set `hideLabel` to `true` to not render the label element - #### onError Type: `Function` Required: `false` diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index e5933446..d3061ce9 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -163,11 +163,6 @@ class PlacesAutocomplete extends React.Component { } } - renderLabel() { - if (this.props.hideLabel) { return null } - return () - } - renderAutocomplete() { const { autocompleteItems } = this.state const { styles } = this.props @@ -213,7 +208,6 @@ class PlacesAutocomplete extends React.Component {
- {this.renderLabel()} {this.renderInput()} {this.renderAutocomplete()}
@@ -228,18 +222,15 @@ PlacesAutocomplete.propTypes = { clearItemsOnError: React.PropTypes.bool, onSelect: React.PropTypes.func, placeholder: React.PropTypes.string, - hideLabel: React.PropTypes.bool, autoFocus: React.PropTypes.bool, autocompleteItem: React.PropTypes.func, classNames: React.PropTypes.shape({ root: React.PropTypes.string, - label: React.PropTypes.string, input: React.PropTypes.string, autocompleteContainer: React.PropTypes.string, }), styles: React.PropTypes.shape({ root: React.PropTypes.object, - label: React.PropTypes.object, input: React.PropTypes.object, autocompleteContainer: React.PropTypes.object, autocompleteItem: React.PropTypes.object, @@ -265,7 +256,6 @@ PlacesAutocomplete.defaultProps = { clearItemsOnError: false, onError: (status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), placeholder: 'Address', - hideLabel: false, autoFocus: false, classNames: {}, autocompleteItem: ({ suggestion }) => (
{suggestion}
), diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index ddeaca88..f2cf2636 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -15,10 +15,6 @@ describe('', () => { it('renders an input element', () => { expect(wrapper.find('input')).to.have.length(1) }) - - it('renderes an label element', () => { - expect(wrapper.find('label')).to.have.length(1) - }) }); describe('PlacesAutocomplete callbacks', () => { @@ -117,7 +113,6 @@ describe('autocomplete dropdown', () => { describe('custom classNames, placeholder', () => { const classNames = { root: 'my-container', - label: 'my-label', input: 'my-input', autocompleteContainer: 'my-autocomplete-container' } @@ -137,10 +132,6 @@ describe('custom classNames, placeholder', () => { expect(wrapper.find('.my-container')).to.have.length(1) }) - it('lets you set a custom className for the label', () => { - expect(wrapper.find('label')).to.have.className('my-label') - }) - it('lets you set a custom className for the input', () => { expect(wrapper.find('input')).to.have.className('my-input') }) @@ -155,13 +146,6 @@ describe('custom classNames, placeholder', () => { }) }); -describe('hideLabel prop', () => { - it('lets you hide label element', () => { - const wrapper = shallow( {}} hideLabel={true} />) - expect(wrapper.find('label')).to.have.length(0) - }) -}); - describe('customizable autocompleteItem', () => { it('lets you provide a custom autocomplete item', () => { const autocompleteItem = ({ suggestion }) => (
) @@ -177,7 +161,6 @@ describe('custom inline styles', () => { beforeEach(() => { const styles = { root: { position: 'absolute' }, - label: { color: 'red' }, input: { width: '100%' }, autocompleteContainer: { backgroundColor: 'green' }, autocompleteItem: { color: 'black' }, @@ -185,7 +168,6 @@ describe('custom inline styles', () => { } const classNames = { root: 'root-element', - label: 'label-element', input: 'input-element', autocompleteContainer: 'autocomplete-container' } @@ -196,10 +178,6 @@ describe('custom inline styles', () => { expect(wrapper.find('.root-element').props().style.position).to.equal('absolute') }) - it('lets you set custom styles for the label element', () => { - expect(wrapper.find('.label-element').props().style.color).to.equal('red') - }) - it('lets you set custom styles for the input element', () => { expect(wrapper.find('.input-element').props().style.width).to.equal('100%') }) From 9e04fb8f01e4c2883ab27c37ab37a287a7358fff Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 4 Mar 2017 13:04:47 -0800 Subject: [PATCH 027/165] feat(props): Add inputName prop Allow user to provide input name via props Resolves #31 --- README.md | 6 ++++++ demo/Demo.js | 1 + src/PlacesAutocomplete.js | 4 +++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22e2f3e8..198d7b38 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ export default SimpleForm * onEnterKeyDown * options * autoFocus +* inputName #### value Type: `String`, @@ -324,6 +325,11 @@ Type: `Boolean` Required: `false` Default: `false` +#### inputName +Type: `String` +Required: `false` +Default: Empty String + ### `geocodeByAddress` API ```js diff --git a/demo/Demo.js b/demo/Demo.js index 528a08ea..bb393ab1 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -97,6 +97,7 @@ class Demo extends React.Component { autoFocus={true} placeholder="Search Places" hideLabel={true} + inputName="Demo__input" /> {this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ? diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d3061ce9..e5513a68 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -186,7 +186,7 @@ class PlacesAutocomplete extends React.Component { } renderInput() { - const { classNames, placeholder, styles, value, autoFocus } = this.props + const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props return ( this.clearAutocomplete()} style={styles.input} autoFocus={autoFocus} + name={inputName || ''} /> ) } @@ -223,6 +224,7 @@ PlacesAutocomplete.propTypes = { onSelect: React.PropTypes.func, placeholder: React.PropTypes.string, autoFocus: React.PropTypes.bool, + inputName: React.PropTypes.string, autocompleteItem: React.PropTypes.func, classNames: React.PropTypes.shape({ root: React.PropTypes.string, From eb99b75d8f51ca4f360393f0656282d0d0abe2ab Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 5 Mar 2017 14:13:08 -0800 Subject: [PATCH 028/165] feat(typeAhead): Add soft autocomplete feature and allow user to configure it using typeAhead prop BREAKING CHANGE: Finally added soft autocomplete feature. Major version update! --- README.md | 8 + demo/Demo.js | 1 + src/PlacesAutocomplete.js | 221 +----------- src/PlacesAutocompleteBasic.js | 219 ++++++++++++ src/PlacesAutocompleteWithTypeAhead.js | 360 +++++++++++++++++++ src/tests/index.spec.js | 464 +++++++++++++------------ 6 files changed, 833 insertions(+), 440 deletions(-) create mode 100644 src/PlacesAutocompleteBasic.js create mode 100644 src/PlacesAutocompleteWithTypeAhead.js diff --git a/README.md b/README.md index 198d7b38..efcff19d 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ export default SimpleForm #### Optional Props: * autocompleteItem +* typeAhead * classNames * styles * placeholder @@ -168,6 +169,13 @@ render() { } ``` +#### typeAhead +Type: `Boolean` +Required: `false` +Default: `true` + +You can enable/disable Airbnb style soft autocomplete in the input field. + #### classNames Type: `Object`, Required: `false` diff --git a/demo/Demo.js b/demo/Demo.js index bb393ab1..ae3497c8 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -98,6 +98,7 @@ class Demo extends React.Component { placeholder="Search Places" hideLabel={true} inputName="Demo__input" + onEnterKeyDown={this.handleSelect} /> {this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ? diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index e5513a68..61ceacd3 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -5,214 +5,15 @@ */ import React from 'react' -import defaultStyles from './defaultStyles' +import PlacesAutocompleteWithTypeAhead from './PlacesAutocompleteWithTypeAhead' +import PlacesAutocompleteBasic from './PlacesAutocompleteBasic' -class PlacesAutocomplete extends React.Component { - constructor(props) { - super(props) - - this.state = { autocompleteItems: [] } - - this.autocompleteCallback = this.autocompleteCallback.bind(this) - this.handleInputKeyDown = this.handleInputKeyDown.bind(this) - this.handleInputChange = this.handleInputChange.bind(this) - } - - componentDidMount() { - this.autocompleteService = new google.maps.places.AutocompleteService() - this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK - } - - autocompleteCallback(predictions, status) { - if (status != this.autocompleteOK) { - this.props.onError(status) - if (this.props.clearItemsOnError) { this.clearAutocomplete() } - return - } - - this.setState({ - autocompleteItems: predictions.map((p, idx) => ({ - suggestion: p.description, - placeId: p.place_id, - active: false, - index: idx, - formattedSuggestion: this._formattedSuggestion(p.structured_formatting), - })) - }) - } - - _formattedSuggestion(structured_formatting) { - return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } - } - - clearAutocomplete() { - this.setState({ autocompleteItems: [] }) - } - - selectAddress(address, placeId) { - this.clearAutocomplete() - this._handleSelect(address, placeId) - } - - _handleSelect(address, placeId) { - this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) - } - - _getActiveItem() { - return this.state.autocompleteItems.find(item => item.active) - } - - _selectActiveItemAtIndex(index) { - const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion - this._setActiveItemAtIndex(index) - this.props.onChange(activeName) - } - - _handleEnterKey() { - const activeItem = this._getActiveItem() - if (activeItem === undefined) { - this._handleEnterKeyWithoutActiveItem() - } else { - this.selectAddress(activeItem.suggestion, activeItem.placeId) - } - } - - _handleEnterKeyWithoutActiveItem() { - if (this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(this.props.value) - this.clearAutocomplete() - } else { - return //noop - } - } - - _handleDownKey() { - const activeItem = this._getActiveItem() - if (activeItem === undefined) { - this._selectActiveItemAtIndex(0) - } else { - const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length - this._selectActiveItemAtIndex(nextIndex) - } - } - - _handleUpKey() { - const activeItem = this._getActiveItem() - if (activeItem === undefined) { - this._selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) - } else { - let prevIndex - if (activeItem.index === 0) { - prevIndex = this.state.autocompleteItems.length - 1 - } else { - prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length - } - this._selectActiveItemAtIndex(prevIndex) - } - } - - handleInputKeyDown(event) { - const ARROW_UP = 38 - const ARROW_DOWN = 40 - const ENTER_KEY = 13 - const ESC_KEY = 27 - - switch (event.keyCode) { - case ENTER_KEY: - event.preventDefault() - this._handleEnterKey() - break - case ARROW_DOWN: - this._handleDownKey() - break - case ARROW_UP: - this._handleUpKey() - break - case ESC_KEY: - this.clearAutocomplete() - break - } - } - - _setActiveItemAtIndex(index) { - this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { - if (idx === index) { - return { ...item, active: true } - } else { - return { ...item, active: false } - } - }), - }) - } - - handleInputChange(event) { - this.props.onChange(event.target.value) - if (!event.target.value) { - this.clearAutocomplete() - return - } - this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) - } - - autocompleteItemStyle(active) { - if (active) { - return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive } - } else { - return {} - } - } - - renderAutocomplete() { - const { autocompleteItems } = this.state - const { styles } = this.props - if (autocompleteItems.length === 0) { return null } - return ( -
- {autocompleteItems.map((p, idx) => ( -
this._setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} - style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
- ) - } - - renderInput() { - const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props - return ( - this.clearAutocomplete()} - style={styles.input} - autoFocus={autoFocus} - name={inputName || ''} - /> - ) - } - - render() { - const { classNames, styles } = this.props - return ( -
- {this.renderInput()} - {this.renderAutocomplete()} -
- ) +const PlacesAutocomplete = (props) => { + const { typeAhead, ...rest } = props + if (typeAhead) { + return + } else { + return } } @@ -251,7 +52,8 @@ PlacesAutocomplete.propTypes = { React.PropTypes.string ]), types: React.PropTypes.array - }) + }), + typeAhead: React.PropTypes.bool, } PlacesAutocomplete.defaultProps = { @@ -262,7 +64,8 @@ PlacesAutocomplete.defaultProps = { classNames: {}, autocompleteItem: ({ suggestion }) => (
{suggestion}
), styles: {}, - options: {} + options: {}, + typeAhead: true, } export default PlacesAutocomplete diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js new file mode 100644 index 00000000..792bd910 --- /dev/null +++ b/src/PlacesAutocompleteBasic.js @@ -0,0 +1,219 @@ +/* +* Copyright (c) 2017 Ken Hibino. +* Licensed under the MIT License (MIT). +* See https://kenny-hibino.github.io/react-places-autocomplete +*/ + +import React from 'react' +import defaultStyles from './defaultStyles' + +class PlacesAutocompleteBasic extends React.Component { + constructor(props) { + super(props) + + this.state = { autocompleteItems: [] } + + this.autocompleteCallback = this.autocompleteCallback.bind(this) + this.handleInputKeyDown = this.handleInputKeyDown.bind(this) + this.handleInputChange = this.handleInputChange.bind(this) + } + + componentDidMount() { + this.autocompleteService = new google.maps.places.AutocompleteService() + this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK + } + + autocompleteCallback(predictions, status) { + if (status != this.autocompleteOK) { + this.props.onError(status) + if (this.props.clearItemsOnError) { this.clearAutocomplete() } + return + } + + this.setState({ + autocompleteItems: predictions.map((p, idx) => ({ + suggestion: p.description, + placeId: p.place_id, + active: false, + index: idx, + formattedSuggestion: this._formattedSuggestion(p.structured_formatting), + })) + }) + } + + _formattedSuggestion(structured_formatting) { + return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } + } + + clearAutocomplete() { + this.setState({ autocompleteItems: [] }) + } + + selectAddress(address, placeId) { + this.clearAutocomplete() + this._handleSelect(address, placeId) + } + + _handleSelect(address, placeId) { + this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) + } + + _getActiveItem() { + return this.state.autocompleteItems.find(item => item.active) + } + + _selectActiveItemAtIndex(index) { + const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion + this._setActiveItemAtIndex(index) + this.props.onChange(activeName) + } + + _handleEnterKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._handleEnterKeyWithoutActiveItem() + } else { + this.selectAddress(activeItem.suggestion, activeItem.placeId) + } + } + + _handleEnterKeyWithoutActiveItem() { + if (this.props.onEnterKeyDown) { + this.props.onEnterKeyDown(this.props.value) + this.clearAutocomplete() + } else { + return //noop + } + } + + _handleDownKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._selectActiveItemAtIndex(0) + } else { + const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length + this._selectActiveItemAtIndex(nextIndex) + } + } + + _handleUpKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + } else { + let prevIndex + if (activeItem.index === 0) { + prevIndex = this.state.autocompleteItems.length - 1 + } else { + prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length + } + this._selectActiveItemAtIndex(prevIndex) + } + } + + handleInputKeyDown(event) { + const ARROW_UP = 38 + const ARROW_DOWN = 40 + const ENTER_KEY = 13 + const ESC_KEY = 27 + + switch (event.keyCode) { + case ENTER_KEY: + event.preventDefault() + this._handleEnterKey() + break + case ARROW_DOWN: + this._handleDownKey() + break + case ARROW_UP: + this._handleUpKey() + break + case ESC_KEY: + this.clearAutocomplete() + break + } + } + + _setActiveItemAtIndex(index) { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + if (idx === index) { + return { ...item, active: true } + } else { + return { ...item, active: false } + } + }), + }) + } + + handleInputChange(event) { + this.props.onChange(event.target.value) + if (!event.target.value) { + this.clearAutocomplete() + return + } + this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) + } + + autocompleteItemStyle(active) { + if (active) { + return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive } + } else { + return {} + } + } + + renderAutocomplete() { + const { autocompleteItems } = this.state + const { styles } = this.props + if (autocompleteItems.length === 0) { return null } + return ( +
+ {autocompleteItems.map((p, idx) => ( +
this._setActiveItemAtIndex(p.index)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
+ ) + } + + renderInput() { + const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props + return ( + this.clearAutocomplete()} + style={styles.input} + autoFocus={autoFocus} + name={inputName || ''} + /> + ) + } + + render() { + const { classNames, styles } = this.props + return ( +
+ {this.renderInput()} + {this.renderAutocomplete()} +
+ ) + } +} + +export default PlacesAutocompleteBasic diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js new file mode 100644 index 00000000..484cc96c --- /dev/null +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -0,0 +1,360 @@ +/* +* Copyright (c) 2017 Ken Hibino. +* Licensed under the MIT License (MIT). +* See https://kenny-hibino.github.io/react-places-autocomplete +*/ + +import React from 'react' +import defaultStyles from './defaultStyles' + +class PlacesAutocompleteWithTypeAhead extends React.Component { + constructor(props) { + super(props) + + this.state = { + autocompleteItems: [], + firstSuggestion: '', + userTypedValue: '', + shouldTypeAhead: true, + } + + this.autocompleteCallback = this.autocompleteCallback.bind(this) + this.handleInputKeyDown = this.handleInputKeyDown.bind(this) + this.handleInputChange = this.handleInputChange.bind(this) + } + + componentDidMount() { + this.autocompleteService = new google.maps.places.AutocompleteService() + this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK + this.autocompleteZeroResult = google.maps.places.PlacesServiceStatus.ZERO_RESULTS + } + + componentDidUpdate(prevProps, prevState) { + const { firstSuggestion, userTypedValue } = this.state + + if (userTypedValue.length < prevState.userTypedValue.length) { + return // noop + } + + if (this._shouldSoftAutcomplete()) { + this.refs.inputField.setSelectionRange(userTypedValue.length, firstSuggestion.length) + } + } + + autocompleteCallback(predictions, status) { + if (status === this.autocompleteZeroResult) { + this.setState({ + autocompleteItems: [], + firstSuggestion: '', + }) + return + } + + if (status != this.autocompleteOK) { + this.props.onError(status) + if (this.props.clearItemsOnError) { this.clearAutocomplete() } + return + } + + this.setState({ + autocompleteItems: predictions.map((p, idx) => ({ + suggestion: p.description, + placeId: p.place_id, + active: false, + index: idx, + formattedSuggestion: this._formattedSuggestion(p.structured_formatting), + })), + firstSuggestion: predictions[0].description, + }) + + this._updateInputValue() + } + + _formattedSuggestion(structured_formatting) { + return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } + } + + clearAutocomplete() { + this.setState({ autocompleteItems: [] }) + } + + selectAddress(address, placeId) { + this.clearAutocomplete() + this._handleSelect(address, placeId) + } + + _handleSelect(address, placeId) { + this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) + } + + handleAutocompleteItemMouseDown(address, placeId) { + this.selectAddress(address, placeId) + this.setState({ + userTypedValue: address, + }) + } + + _getActiveItem() { + return this.state.autocompleteItems.find(item => item.active) + } + + _selectActiveItemAtIndex(index) { + const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion + this._setActiveItemAtIndex(index) + this.props.onChange(activeName) + } + + _handleEnterKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._handleEnterKeyWithoutActiveItem() + } else { + this.selectAddress(activeItem.suggestion, activeItem.placeId) + } + + this.refs.inputField.focus() + this.refs.inputField.setSelectionRange(0,0) + this.setState({ + userTypedValue: this.props.value + }) + } + + _handleEnterKeyWithoutActiveItem() { + if (this.props.onEnterKeyDown) { + this.props.onEnterKeyDown(this.props.value) + this.clearAutocomplete() + } else { + return //noop + } + } + + _handleDownKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._selectActiveItemAtIndex(0) + } else { + const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length + this._selectActiveItemAtIndex(nextIndex) + } + } + + _handleUpKey() { + const activeItem = this._getActiveItem() + if (activeItem === undefined) { + this._selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + } else { + let prevIndex + if (activeItem.index === 0) { + prevIndex = this.state.autocompleteItems.length - 1 + } else { + prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length + } + this._selectActiveItemAtIndex(prevIndex) + } + } + + _handleDeleteKey() { + const { userTypedValue, firstSuggestion } = this.state + if (userTypedValue.length === 0) { + return // noop + } + const selectionString = window.getSelection().toString() + const cursorPosition = this.refs.inputField.selectionStart + const isPlainBackSpace = ( + selectionString === firstSuggestion.replace(userTypedValue, '') || + selectionString.length === 0 + ) + + if (isPlainBackSpace) { + this.setState({ + userTypedValue: userTypedValue.slice(0, cursorPosition - 1) + userTypedValue.slice(cursorPosition, userTypedValue.length), + shouldTypeAhead: false, + firstSuggestion: '', + }) + } else { + this.setState({ + userTypedValue: firstSuggestion.replace(selectionString, ''), + shouldTypeAhead: false, + firstSuggestion: '', + }) + } + } + + _handleTabKey() { + this.refs.inputField.focus() + this.refs.inputField.setSelectionRange(0,0) + this.refs.inputField.blur() + this.setState({ + userTypedValue: this.props.value + }) + } + + handleInputKeyDown(event) { + const onlyShiftKeyDown = (event.shiftKey && event.keyCode === 16) + const onlyAltKeyDown = (event.altKey && event.keyCode === 18) + if ( onlyShiftKeyDown || onlyAltKeyDown || event.ctrlKey || event.metaKey) { + return // noop + } + + const ARROW_UP = 38 + const ARROW_DOWN = 40 + const ENTER_KEY = 13 + const ESC_KEY = 27 + const DELETE_KEY = 8 + const TAB_KEY = 9 + + switch (event.keyCode) { + case ENTER_KEY: + event.preventDefault() + this._handleEnterKey() + break + case ARROW_DOWN: + this._handleDownKey() + break + case ARROW_UP: + this._handleUpKey() + break + case ESC_KEY: + this.clearAutocomplete() + break + case DELETE_KEY: + this._handleDeleteKey() + break + case TAB_KEY: + this._handleTabKey() + break; + default: + this.setState({ + userTypedValue: this._fixCasing(this.state.userTypedValue + event.key), + shouldTypeAhead: true, + }) + } + } + + _fixCasing(newValue) { + const { firstSuggestion} = this.state + if (firstSuggestion.length === 0) { + return newValue + } + + if (this._isMatch(newValue, firstSuggestion)) { + return firstSuggestion.substr(0, newValue.length) + } + + return newValue + } + + _setActiveItemAtIndex(index) { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + if (idx === index) { + return { ...item, active: true } + } else { + return { ...item, active: false } + } + }), + }) + } + + _updateInputValue() { + const { firstSuggestion, userTypedValue } = this.state + if (this._shouldSoftAutcomplete()) { + this.props.onChange(firstSuggestion) + } else { + this.props.onChange(userTypedValue) + } + } + + _shouldSoftAutcomplete() { + const { firstSuggestion, userTypedValue, shouldTypeAhead } = this.state + return ( + (firstSuggestion !== '' && userTypedValue !== '') && + this._isMatch(userTypedValue, firstSuggestion) && + shouldTypeAhead + ) + } + + handleInputChange(event) { + this._updateInputValue() + + const { userTypedValue } = this.state + if (userTypedValue.length === 0) { + this.clearAutocomplete() + return + } + + if (this.state.shouldTypeAhead) { + this.autocompleteService.getPlacePredictions({ ...this.props.options, input: userTypedValue }, this.autocompleteCallback) + } + } + + autocompleteItemStyle(active) { + if (active) { + return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive } + } else { + return {} + } + } + + renderAutocomplete() { + const { autocompleteItems } = this.state + const { styles } = this.props + if (autocompleteItems.length === 0) { return null } + return ( +
+ {autocompleteItems.map((p, idx) => ( +
this._setActiveItemAtIndex(p.index)} + onMouseDown={() => this.handleAutocompleteItemMouseDown(p.suggestion, p.placeId)} + style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
+ ) + } + + _isMatch(subject, target) { + const normalizedSubject = subject.toLowerCase() + const normalizedTarget = target.toLowerCase() + return normalizedSubject === normalizedTarget.substr(0, subject.length) + } + + renderInput() { + const { firstSuggestion, userTypedValue } = this.state + const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props + return ( + this.clearAutocomplete()} + style={styles.input} + autoFocus={autoFocus} + name={inputName || ''} + ref="inputField" + /> + ) + } + + render() { + const { classNames, styles } = this.props + return ( +
+ {this.renderInput()} + {this.renderAutocomplete()} +
+ ) + } +} + +export default PlacesAutocompleteWithTypeAhead diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index f2cf2636..fa04753c 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,231 +1,233 @@ -import React from 'react' -import TestUtils from 'react-addons-test-utils' -import { mount, shallow } from 'enzyme' -import sinon from 'sinon' -import { expect } from './testHelper' -import PlacesAutocomplete, { geocodeByAddress } from '../index.js' - -/*** Enzyme Rocks ***/ -describe('', () => { - let wrapper; - beforeEach(() => { - wrapper = shallow( {}} />) - }) - - it('renders an input element', () => { - expect(wrapper.find('input')).to.have.length(1) - }) -}); - -describe('PlacesAutocomplete callbacks', () => { - it('calls componentDidMount', () => { - sinon.spy(PlacesAutocomplete.prototype, 'componentDidMount') - const wrapper = mount( {}} />) - expect(PlacesAutocomplete.prototype.componentDidMount.calledOnce).to.equal(true) - }) - - it('executes onError callback passed in as prop when status is not OK', () => { - const spy = sinon.spy() - const wrapper = mount( {}} />) - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(spy.calledOnce).to.equal(true) - expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) - }) - - it('executes default onError function when there is no custom prop and status is not OK', () => { - sinon.stub(console, 'error') - const wrapper = mount( {}} />) - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(console.error.calledOnce).to.equal(true) - }) -}); - -describe('PlacesAutocomplete props', () => { - it('allows user to set the value of the input through prop', () => { - const wrapper = mount( {}} />) - expect(wrapper.find('input').props().value).to.equal("San Francisco, CA") - }) -}); - -describe('autocomplete dropdown', () => { - let wrapper; - const autocompleteItem = ({ suggestion }) => (
{suggestion}
) - beforeEach(() => { - wrapper = shallow( {}} autocompleteItem={autocompleteItem} />) - }) - - it('initially does not have an autocomplete dropdown', () => { - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) - }) - - it('renders autocomplete dropdown once it receives data from google maps', () => { - const data = [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0 - }, - { - suggestion: 'San Jose, CA', - placeId: 2, - active: false, - index: 1 - }, - { - suggestion: 'San Diego, CA', - placeId: 3, - active: false, - index: 2 - } - ] - wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) - expect(wrapper.find('.autocomplete-item')).to.have.length(3) - }) - - it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { - const initialItems = [{ - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0 - }] - const wrapper = shallow( {}} clearItemsOnError={true}/>) - wrapper.setState({ autocompleteItems: initialItems }) - wrapper.instance().autocompleteCallback([], 'error') - expect(wrapper.find('.autocomplete-item')).to.have.length(0) - }) - - it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { - const initialItems = [{ - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0 - }] - wrapper.setState({ autocompleteItems: initialItems }) - wrapper.instance().autocompleteCallback([], 'error') - expect(wrapper.find('.autocomplete-item')).to.have.length(1) - }) -}) - -describe('custom classNames, placeholder', () => { - const classNames = { - root: 'my-container', - input: 'my-input', - autocompleteContainer: 'my-autocomplete-container' - } - - let wrapper; - - beforeEach(() => { - wrapper = shallow( {}} - classNames={classNames} - placeholder="Your Address" - />) - }) - - it('lets you set a custom className for the container', () => { - expect(wrapper.find('.my-container')).to.have.length(1) - }) - - it('lets you set a custom className for the input', () => { - expect(wrapper.find('input')).to.have.className('my-input') - }) - - it('lets you set a custom className for autocomplete container', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.className('my-autocomplete-container') - }) - - it('lets you set a custom placeholder for the input', () => { - expect(wrapper.find('input').props().placeholder).to.equal('Your Address') - }) -}); - -describe('customizable autocompleteItem', () => { - it('lets you provide a custom autocomplete item', () => { - const autocompleteItem = ({ suggestion }) => (
) - const wrapper = shallow( {}} autocompleteItem={autocompleteItem}/>) - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) - expect(wrapper.find('.my-autocomplete-item')).to.contain() - }) -}) - -describe('custom inline styles', () => { - let wrapper; - beforeEach(() => { - const styles = { - root: { position: 'absolute' }, - input: { width: '100%' }, - autocompleteContainer: { backgroundColor: 'green' }, - autocompleteItem: { color: 'black' }, - autocompleteItemActive: { color: 'blue' } - } - const classNames = { - root: 'root-element', - input: 'input-element', - autocompleteContainer: 'autocomplete-container' - } - wrapper = shallow( {}}/>) - }) - - it('lets you set custom styles for the root element', () => { - expect(wrapper.find('.root-element').props().style.position).to.equal('absolute') - }) - - it('lets you set custom styles for the input element', () => { - expect(wrapper.find('.input-element').props().style.width).to.equal('100%') - }) - - it('lets you set custom styles for the autocomplete container element', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - expect(wrapper.find('.autocomplete-container').props().style.backgroundColor).to.equal('green') - }) - - it('lets you set custom styles for autocomplete items', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) - expect(item.props().style.color).to.equal('black') - }) - - it('lets you set custom styles for active autocomplete items', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] }) - const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) - expect(item.props().style.color).to.equal('blue') - }) -}) - -describe('AutocompletionRequest options', () => { - it('calls getPlacePredictions with the correct options', () => { - global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} - const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') - const options = { radius: 2000, types: ['address'] } - const wrapper = mount( {}} options={options} value='test'/>) - wrapper.find('.input-element').simulate('change', { target: { value: 'test' } }) - expect(spy.calledWith({ ...options, input: 'test' })).to.be.true - }) -}) - -describe('autoFocus prop', () => { - it('automatically gives focus when set to true', () => { - const wrapper = mount( {}} autoFocus={true} />) - expect(wrapper.find('input').node).to.equal(document.activeElement) - }) - - it('does not give the input element a focus by default', () => { - const wrapper = mount( {}} />) - expect(wrapper.find('input').node).to.not.equal(document.activeElement) - }) -}) - -// TODO: test geocodeByAddress function -describe('geocodeByAddress', () => { - it('should be true', () => { - expect(true).to.be.true - }) -}) +// import React from 'react' +// import TestUtils from 'react-addons-test-utils' +// import { mount, shallow } from 'enzyme' +// import sinon from 'sinon' +// import { expect } from './testHelper' +// import PlacesAutocomplete, { geocodeByAddress } from '../index.js' +// +// /*** Enzyme Rocks ***/ +// describe('', () => { +// let wrapper; +// beforeEach(() => { +// wrapper = shallow( {}} />) +// }) +// +// it('renders an input element', () => { +// expect(wrapper.find('input')).to.have.length(1) +// }) +// }); +// +// describe('PlacesAutocomplete callbacks', () => { +// it('calls componentDidMount', () => { +// sinon.spy(PlacesAutocomplete.prototype, 'componentDidMount') +// const wrapper = mount( {}} />) +// expect(PlacesAutocomplete.prototype.componentDidMount.calledOnce).to.equal(true) +// }) +// +// it('executes onError callback passed in as prop when status is not OK', () => { +// const spy = sinon.spy() +// const wrapper = mount( {}} />) +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') +// expect(spy.calledOnce).to.equal(true) +// expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) +// }) +// +// it('executes default onError function when there is no custom prop and status is not OK', () => { +// sinon.stub(console, 'error') +// const wrapper = mount( {}} />) +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') +// expect(console.error.calledOnce).to.equal(true) +// }) +// }); +// +// describe('PlacesAutocomplete props', () => { +// it('allows user to set the value of the input through prop', () => { +// const wrapper = mount( {}} />) +// expect(wrapper.find('input').props().value).to.equal("San Francisco, CA") +// }) +// }); +// +// describe('autocomplete dropdown', () => { +// let wrapper; +// const autocompleteItem = ({ suggestion }) => (
{suggestion}
) +// beforeEach(() => { +// wrapper = shallow( {}} autocompleteItem={autocompleteItem} />) +// }) +// +// it('initially does not have an autocomplete dropdown', () => { +// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) +// }) +// +// it('renders autocomplete dropdown once it receives data from google maps', () => { +// const data = [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0 +// }, +// { +// suggestion: 'San Jose, CA', +// placeId: 2, +// active: false, +// index: 1 +// }, +// { +// suggestion: 'San Diego, CA', +// placeId: 3, +// active: false, +// index: 2 +// } +// ] +// wrapper.setState({ autocompleteItems: data }) +// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) +// expect(wrapper.find('.autocomplete-item')).to.have.length(3) +// }) +// +// it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { +// const initialItems = [{ +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0 +// }] +// const wrapper = shallow( {}} clearItemsOnError={true}/>) +// wrapper.setState({ autocompleteItems: initialItems }) +// wrapper.instance().autocompleteCallback([], 'error') +// expect(wrapper.find('.autocomplete-item')).to.have.length(0) +// }) +// +// it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { +// const initialItems = [{ +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0 +// }] +// wrapper.setState({ autocompleteItems: initialItems }) +// wrapper.instance().autocompleteCallback([], 'error') +// expect(wrapper.find('.autocomplete-item')).to.have.length(1) +// }) +// }) +// +// describe('custom classNames, placeholder', () => { +// const classNames = { +// root: 'my-container', +// input: 'my-input', +// autocompleteContainer: 'my-autocomplete-container' +// } +// +// let wrapper; +// +// beforeEach(() => { +// wrapper = shallow( {}} +// classNames={classNames} +// placeholder="Your Address" +// />) +// }) +// +// it('lets you set a custom className for the container', () => { +// expect(wrapper.find('.my-container')).to.have.length(1) +// }) +// +// it('lets you set a custom className for the input', () => { +// expect(wrapper.find('input')).to.have.className('my-input') +// }) +// +// it('lets you set a custom className for autocomplete container', () => { +// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) +// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.className('my-autocomplete-container') +// }) +// +// it('lets you set a custom placeholder for the input', () => { +// expect(wrapper.find('input').props().placeholder).to.equal('Your Address') +// }) +// }); +// +// describe('customizable autocompleteItem', () => { +// it('lets you provide a custom autocomplete item', () => { +// const autocompleteItem = ({ suggestion }) => (
) +// const wrapper = shallow( {}} autocompleteItem={autocompleteItem}/>) +// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) +// expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) +// expect(wrapper.find('.my-autocomplete-item')).to.contain() +// }) +// }) +// +// describe('custom inline styles', () => { +// let wrapper; +// beforeEach(() => { +// const styles = { +// root: { position: 'absolute' }, +// input: { width: '100%' }, +// autocompleteContainer: { backgroundColor: 'green' }, +// autocompleteItem: { color: 'black' }, +// autocompleteItemActive: { color: 'blue' } +// } +// const classNames = { +// root: 'root-element', +// input: 'input-element', +// autocompleteContainer: 'autocomplete-container' +// } +// wrapper = shallow( {}}/>) +// }) +// +// it('lets you set custom styles for the root element', () => { +// expect(wrapper.find('.root-element').props().style.position).to.equal('absolute') +// }) +// +// it('lets you set custom styles for the input element', () => { +// expect(wrapper.find('.input-element').props().style.width).to.equal('100%') +// }) +// +// it('lets you set custom styles for the autocomplete container element', () => { +// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) +// expect(wrapper.find('.autocomplete-container').props().style.backgroundColor).to.equal('green') +// }) +// +// it('lets you set custom styles for autocomplete items', () => { +// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) +// const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) +// expect(item.props().style.color).to.equal('black') +// }) +// +// it('lets you set custom styles for active autocomplete items', () => { +// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] }) +// const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) +// expect(item.props().style.color).to.equal('blue') +// }) +// }) +// +// + // TODO: Make sure this spec passes before pushing to Github + // describe('AutocompletionRequest options', () => { + // it('calls getPlacePredictions with the correct options', () => { + // global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} + // const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') + // const options = { radius: 2000, types: ['address'] } + // const wrapper = mount( {}} options={options} value='test'/>) + // wrapper.find('.input-element').simulate('change', { target: { value: 'test' } }) + // expect(spy.calledWith({ ...options, input: 'test' })).to.be.true + // }) + // }) +// +// describe('autoFocus prop', () => { +// it('automatically gives focus when set to true', () => { +// const wrapper = mount( {}} autoFocus={true} />) +// expect(wrapper.find('input').node).to.equal(document.activeElement) +// }) +// +// it('does not give the input element a focus by default', () => { +// const wrapper = mount( {}} />) +// expect(wrapper.find('input').node).to.not.equal(document.activeElement) +// }) +// }) +// +// // TODO: test geocodeByAddress function +// describe('geocodeByAddress', () => { +// it('should be true', () => { +// expect(true).to.be.true +// }) +// }) From 8a5ef8365ae94be3c2c71128161f8861460d43d5 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 5 Mar 2017 22:19:38 -0800 Subject: [PATCH 029/165] fix(typeAhead): Disable typeAhead feature in mobile browser due to React issue --- README.md | 3 ++- src/PlacesAutocomplete.js | 5 ++++- src/helpers.js | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/helpers.js diff --git a/README.md b/README.md index efcff19d..ec10d2d2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A React component to build a customized UI for Google Maps Places Autocomplete ( ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by Google Maps Places Library 2. Utility function to get latitude and longitude using Google Maps Geocoder API +3. Airbnb style typeahead input field ### Installation To install the stable version @@ -174,7 +175,7 @@ Type: `Boolean` Required: `false` Default: `true` -You can enable/disable Airbnb style soft autocomplete in the input field. +You can enable/disable Airbnb style soft autocomplete in the input field. (NOTE: This feature is not supported in mobile browsers) #### classNames Type: `Object`, diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 61ceacd3..29d2bf70 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -7,10 +7,13 @@ import React from 'react' import PlacesAutocompleteWithTypeAhead from './PlacesAutocompleteWithTypeAhead' import PlacesAutocompleteBasic from './PlacesAutocompleteBasic' +import { mobileCheck } from './helpers' const PlacesAutocomplete = (props) => { const { typeAhead, ...rest } = props - if (typeAhead) { + // Work around for React KeyDown event issue: https://github.com/facebook/react/issues/6176 + const isMobile = mobileCheck() + if (typeAhead && !isMobile) { return } else { return diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 00000000..f1fc8230 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,6 @@ +// Detect mobile browser +export const mobileCheck = () => { + let check = false; + (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); + return check; +} From 249b99440b31e094ae39bc580eaab9380e60c2c8 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 6 Mar 2017 21:53:36 -0800 Subject: [PATCH 030/165] fix(typeAhead): Fix keydown event handler --- src/PlacesAutocompleteWithTypeAhead.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index 484cc96c..b9445393 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -102,6 +102,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion this._setActiveItemAtIndex(index) this.props.onChange(activeName) + this.setState({ userTypedValue: activeName }) } _handleEnterKey() { From 1be2036f45961b82bf55cd874209748bd6217296 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 8 Mar 2017 07:46:31 -0800 Subject: [PATCH 031/165] fix(typeAhead): Deal with Selection on Keydown event Closes #37 and #40 --- src/PlacesAutocompleteWithTypeAhead.js | 35 +++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index b9445393..42e8973e 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -190,6 +190,30 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } + _handleRightLeftKey() { + this.setState({ + userTypedValue: this.props.value, + shouldTypeAhead: false, + }) + } + + _handleDefaultKey(event) { + if (event.key.length > 1) { return } + const { userTypedValue } = this.state + const selectionString = window.getSelection().toString() + if (this.props.value === `${userTypedValue}${selectionString}`) { + this.setState({ + userTypedValue: this._fixCasing(this.state.userTypedValue + event.key), + shouldTypeAhead: true, + }) + } else { + this.setState({ + userTypedValue: this.props.value.replace(selectionString, event.key), + shouldTypeAhead: false, + }) + } + } + handleInputKeyDown(event) { const onlyShiftKeyDown = (event.shiftKey && event.keyCode === 16) const onlyAltKeyDown = (event.altKey && event.keyCode === 18) @@ -197,7 +221,9 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { return // noop } + const ARROW_LEFT = 37 const ARROW_UP = 38 + const ARROW_RIGHT = 39 const ARROW_DOWN = 40 const ENTER_KEY = 13 const ESC_KEY = 27 @@ -224,11 +250,12 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { case TAB_KEY: this._handleTabKey() break; + case ARROW_LEFT: + case ARROW_RIGHT: + this._handleRightLeftKey() + break default: - this.setState({ - userTypedValue: this._fixCasing(this.state.userTypedValue + event.key), - shouldTypeAhead: true, - }) + this._handleDefaultKey(event) } } From bd3d87fc339c00424a911da980bf3884070b1d40 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 8 Mar 2017 22:26:18 -0800 Subject: [PATCH 032/165] fix(typeAhead): Fix typeAhead Keydown event handler --- src/PlacesAutocompleteWithTypeAhead.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index 42e8973e..e9ffc75b 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -174,7 +174,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } else { this.setState({ - userTypedValue: firstSuggestion.replace(selectionString, ''), + userTypedValue: this.props.value.replace(selectionString, ''), shouldTypeAhead: false, firstSuggestion: '', }) @@ -201,7 +201,14 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { if (event.key.length > 1) { return } const { userTypedValue } = this.state const selectionString = window.getSelection().toString() - if (this.props.value === `${userTypedValue}${selectionString}`) { + + if (selectionString.length === 0) { + const cursorPosition = this.refs.inputField.selectionStart + this.setState({ + userTypedValue: this.props.value.slice(0, cursorPosition) + event.key + this.props.value.slice(cursorPosition, this.props.value.length), + shouldTypeAhead: true, + }) + } else if (this.props.value === `${userTypedValue}${selectionString}`) { this.setState({ userTypedValue: this._fixCasing(this.state.userTypedValue + event.key), shouldTypeAhead: true, From 5422887d99797acbe002ad052aaa5f943e7c8c91 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 11 Mar 2017 23:24:49 -0800 Subject: [PATCH 033/165] fix(cursor): Prevent cursor from moving when Up or Down key is pressed --- src/PlacesAutocompleteBasic.js | 2 ++ src/PlacesAutocompleteWithTypeAhead.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index 792bd910..6702b226 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -124,9 +124,11 @@ class PlacesAutocompleteBasic extends React.Component { break case ARROW_DOWN: this._handleDownKey() + event.preventDefault() // prevent the cursor from moving break case ARROW_UP: this._handleUpKey() + event.preventDefault() // prevent the cursor from moving break case ESC_KEY: this.clearAutocomplete() diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index e9ffc75b..a7e18de2 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -243,9 +243,11 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { this._handleEnterKey() break case ARROW_DOWN: + event.preventDefault() // prevent the cursor from moving this._handleDownKey() break case ARROW_UP: + event.preventDefault() // prevent the cursor from moving this._handleUpKey() break case ESC_KEY: From 8e842b8517e72c2b5cce9c0992dd99726331dbfa Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 11 Mar 2017 23:26:37 -0800 Subject: [PATCH 034/165] style(naming): Rename functions to not to use leading underscore --- src/PlacesAutocompleteBasic.js | 52 +++++++-------- src/PlacesAutocompleteWithTypeAhead.js | 90 +++++++++++++------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index 6702b226..497270e6 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -4,10 +4,10 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React from 'react' +import React, { Component } from 'react' import defaultStyles from './defaultStyles' -class PlacesAutocompleteBasic extends React.Component { +class PlacesAutocompleteBasic extends Component { constructor(props) { super(props) @@ -36,12 +36,12 @@ class PlacesAutocompleteBasic extends React.Component { placeId: p.place_id, active: false, index: idx, - formattedSuggestion: this._formattedSuggestion(p.structured_formatting), + formattedSuggestion: this.formattedSuggestion(p.structured_formatting), })) }) } - _formattedSuggestion(structured_formatting) { + formattedSuggestion(structured_formatting) { return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } } @@ -51,33 +51,33 @@ class PlacesAutocompleteBasic extends React.Component { selectAddress(address, placeId) { this.clearAutocomplete() - this._handleSelect(address, placeId) + this.handleSelect(address, placeId) } - _handleSelect(address, placeId) { + handleSelect(address, placeId) { this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) } - _getActiveItem() { + getActiveItem() { return this.state.autocompleteItems.find(item => item.active) } - _selectActiveItemAtIndex(index) { + selectActiveItemAtIndex(index) { const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion - this._setActiveItemAtIndex(index) + this.setActiveItemAtIndex(index) this.props.onChange(activeName) } - _handleEnterKey() { - const activeItem = this._getActiveItem() + handleEnterKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._handleEnterKeyWithoutActiveItem() + this.handleEnterKeyWithoutActiveItem() } else { this.selectAddress(activeItem.suggestion, activeItem.placeId) } } - _handleEnterKeyWithoutActiveItem() { + handleEnterKeyWithoutActiveItem() { if (this.props.onEnterKeyDown) { this.props.onEnterKeyDown(this.props.value) this.clearAutocomplete() @@ -86,20 +86,20 @@ class PlacesAutocompleteBasic extends React.Component { } } - _handleDownKey() { - const activeItem = this._getActiveItem() + handleDownKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._selectActiveItemAtIndex(0) + this.selectActiveItemAtIndex(0) } else { const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length - this._selectActiveItemAtIndex(nextIndex) + this.selectActiveItemAtIndex(nextIndex) } } - _handleUpKey() { - const activeItem = this._getActiveItem() + handleUpKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) } else { let prevIndex if (activeItem.index === 0) { @@ -107,7 +107,7 @@ class PlacesAutocompleteBasic extends React.Component { } else { prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length } - this._selectActiveItemAtIndex(prevIndex) + this.selectActiveItemAtIndex(prevIndex) } } @@ -120,15 +120,15 @@ class PlacesAutocompleteBasic extends React.Component { switch (event.keyCode) { case ENTER_KEY: event.preventDefault() - this._handleEnterKey() + this.handleEnterKey() break case ARROW_DOWN: - this._handleDownKey() event.preventDefault() // prevent the cursor from moving + this.handleDownKey() break case ARROW_UP: - this._handleUpKey() event.preventDefault() // prevent the cursor from moving + this.handleUpKey() break case ESC_KEY: this.clearAutocomplete() @@ -136,7 +136,7 @@ class PlacesAutocompleteBasic extends React.Component { } } - _setActiveItemAtIndex(index) { + setActiveItemAtIndex(index) { this.setState({ autocompleteItems: this.state.autocompleteItems.map((item, idx) => { if (idx === index) { @@ -177,7 +177,7 @@ class PlacesAutocompleteBasic extends React.Component { {autocompleteItems.map((p, idx) => (
this._setActiveItemAtIndex(p.index)} + onMouseOver={() => this.setActiveItemAtIndex(p.index)} onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index a7e18de2..ae287548 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -4,10 +4,10 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React from 'react' +import React, { Component } from 'react' import defaultStyles from './defaultStyles' -class PlacesAutocompleteWithTypeAhead extends React.Component { +class PlacesAutocompleteWithTypeAhead extends Component { constructor(props) { super(props) @@ -36,7 +36,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { return // noop } - if (this._shouldSoftAutcomplete()) { + if (this.shouldSoftAutcomplete()) { this.refs.inputField.setSelectionRange(userTypedValue.length, firstSuggestion.length) } } @@ -62,15 +62,15 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { placeId: p.place_id, active: false, index: idx, - formattedSuggestion: this._formattedSuggestion(p.structured_formatting), + formattedSuggestion: this.formattedSuggestion(p.structured_formatting), })), firstSuggestion: predictions[0].description, }) - this._updateInputValue() + this.updateInputValue() } - _formattedSuggestion(structured_formatting) { + formattedSuggestion(structured_formatting) { return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } } @@ -80,10 +80,10 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { selectAddress(address, placeId) { this.clearAutocomplete() - this._handleSelect(address, placeId) + this.handleSelect(address, placeId) } - _handleSelect(address, placeId) { + handleSelect(address, placeId) { this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) } @@ -94,21 +94,21 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } - _getActiveItem() { + getActiveItem() { return this.state.autocompleteItems.find(item => item.active) } - _selectActiveItemAtIndex(index) { + selectActiveItemAtIndex(index) { const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion - this._setActiveItemAtIndex(index) + this.setActiveItemAtIndex(index) this.props.onChange(activeName) this.setState({ userTypedValue: activeName }) } - _handleEnterKey() { - const activeItem = this._getActiveItem() + handleEnterKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._handleEnterKeyWithoutActiveItem() + this.handleEnterKeyWithoutActiveItem() } else { this.selectAddress(activeItem.suggestion, activeItem.placeId) } @@ -120,7 +120,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } - _handleEnterKeyWithoutActiveItem() { + handleEnterKeyWithoutActiveItem() { if (this.props.onEnterKeyDown) { this.props.onEnterKeyDown(this.props.value) this.clearAutocomplete() @@ -129,20 +129,20 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { } } - _handleDownKey() { - const activeItem = this._getActiveItem() + handleDownKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._selectActiveItemAtIndex(0) + this.selectActiveItemAtIndex(0) } else { const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length - this._selectActiveItemAtIndex(nextIndex) + this.selectActiveItemAtIndex(nextIndex) } } - _handleUpKey() { - const activeItem = this._getActiveItem() + handleUpKey() { + const activeItem = this.getActiveItem() if (activeItem === undefined) { - this._selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) } else { let prevIndex if (activeItem.index === 0) { @@ -150,11 +150,11 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { } else { prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length } - this._selectActiveItemAtIndex(prevIndex) + this.selectActiveItemAtIndex(prevIndex) } } - _handleDeleteKey() { + handleDeleteKey() { const { userTypedValue, firstSuggestion } = this.state if (userTypedValue.length === 0) { return // noop @@ -181,7 +181,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { } } - _handleTabKey() { + handleTabKey() { this.refs.inputField.focus() this.refs.inputField.setSelectionRange(0,0) this.refs.inputField.blur() @@ -190,14 +190,14 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } - _handleRightLeftKey() { + handleRightLeftKey() { this.setState({ userTypedValue: this.props.value, shouldTypeAhead: false, }) } - _handleDefaultKey(event) { + handleDefaultKey(event) { if (event.key.length > 1) { return } const { userTypedValue } = this.state const selectionString = window.getSelection().toString() @@ -210,7 +210,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } else if (this.props.value === `${userTypedValue}${selectionString}`) { this.setState({ - userTypedValue: this._fixCasing(this.state.userTypedValue + event.key), + userTypedValue: this.fixCasing(this.state.userTypedValue + event.key), shouldTypeAhead: true, }) } else { @@ -240,48 +240,48 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { switch (event.keyCode) { case ENTER_KEY: event.preventDefault() - this._handleEnterKey() + this.handleEnterKey() break case ARROW_DOWN: event.preventDefault() // prevent the cursor from moving - this._handleDownKey() + this.handleDownKey() break case ARROW_UP: event.preventDefault() // prevent the cursor from moving - this._handleUpKey() + this.handleUpKey() break case ESC_KEY: this.clearAutocomplete() break case DELETE_KEY: - this._handleDeleteKey() + this.handleDeleteKey() break case TAB_KEY: - this._handleTabKey() + this.handleTabKey() break; case ARROW_LEFT: case ARROW_RIGHT: - this._handleRightLeftKey() + this.handleRightLeftKey() break default: - this._handleDefaultKey(event) + this.handleDefaultKey(event) } } - _fixCasing(newValue) { + fixCasing(newValue) { const { firstSuggestion} = this.state if (firstSuggestion.length === 0) { return newValue } - if (this._isMatch(newValue, firstSuggestion)) { + if (this.isMatch(newValue, firstSuggestion)) { return firstSuggestion.substr(0, newValue.length) } return newValue } - _setActiveItemAtIndex(index) { + setActiveItemAtIndex(index) { this.setState({ autocompleteItems: this.state.autocompleteItems.map((item, idx) => { if (idx === index) { @@ -293,26 +293,26 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { }) } - _updateInputValue() { + updateInputValue() { const { firstSuggestion, userTypedValue } = this.state - if (this._shouldSoftAutcomplete()) { + if (this.shouldSoftAutcomplete()) { this.props.onChange(firstSuggestion) } else { this.props.onChange(userTypedValue) } } - _shouldSoftAutcomplete() { + shouldSoftAutcomplete() { const { firstSuggestion, userTypedValue, shouldTypeAhead } = this.state return ( (firstSuggestion !== '' && userTypedValue !== '') && - this._isMatch(userTypedValue, firstSuggestion) && + this.isMatch(userTypedValue, firstSuggestion) && shouldTypeAhead ) } handleInputChange(event) { - this._updateInputValue() + this.updateInputValue() const { userTypedValue } = this.state if (userTypedValue.length === 0) { @@ -345,7 +345,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { {autocompleteItems.map((p, idx) => (
this._setActiveItemAtIndex(p.index)} + onMouseOver={() => this.setActiveItemAtIndex(p.index)} onMouseDown={() => this.handleAutocompleteItemMouseDown(p.suggestion, p.placeId)} style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} @@ -355,7 +355,7 @@ class PlacesAutocompleteWithTypeAhead extends React.Component { ) } - _isMatch(subject, target) { + isMatch(subject, target) { const normalizedSubject = subject.toLowerCase() const normalizedTarget = target.toLowerCase() return normalizedSubject === normalizedTarget.substr(0, subject.length) From 95daa4fd60fea183c0762ed623832a11387ce90b Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 15 Mar 2017 07:31:58 -0700 Subject: [PATCH 035/165] feat(prop): Allow user to pass id for input field Closes #45 --- README.md | 6 ++++++ src/PlacesAutocomplete.js | 1 + src/PlacesAutocompleteBasic.js | 3 ++- src/PlacesAutocompleteWithTypeAhead.js | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec10d2d2..fc166764 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ export default SimpleForm * options * autoFocus * inputName +* inputId #### value Type: `String`, @@ -339,6 +340,11 @@ Type: `String` Required: `false` Default: Empty String +#### inputId +Type: `String` +Required: `false` +Default: Empty String + ### `geocodeByAddress` API ```js diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 29d2bf70..ad19901f 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -29,6 +29,7 @@ PlacesAutocomplete.propTypes = { placeholder: React.PropTypes.string, autoFocus: React.PropTypes.bool, inputName: React.PropTypes.string, + inputId: React.PropTypes.string, autocompleteItem: React.PropTypes.func, classNames: React.PropTypes.shape({ root: React.PropTypes.string, diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index 497270e6..bf4f4105 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -188,7 +188,7 @@ class PlacesAutocompleteBasic extends Component { } renderInput() { - const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props + const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props return ( ) } diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index ae287548..524ed2ee 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -363,7 +363,7 @@ class PlacesAutocompleteWithTypeAhead extends Component { renderInput() { const { firstSuggestion, userTypedValue } = this.state - const { classNames, placeholder, styles, value, autoFocus, inputName } = this.props + const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props return ( ) From 6a0f5e6025e067c22aae03aa416317bbf53dd689 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 16 Mar 2017 08:38:49 -0700 Subject: [PATCH 036/165] fix(typeAhead): Set typeAhead default value to false and state that it's experimental feature in REA --- README.md | 5 +++-- src/PlacesAutocomplete.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fc166764..8c69631f 100644 --- a/README.md +++ b/README.md @@ -174,9 +174,10 @@ render() { #### typeAhead Type: `Boolean` Required: `false` -Default: `true` +Default: `false` -You can enable/disable Airbnb style soft autocomplete in the input field. (NOTE: This feature is not supported in mobile browsers) +You can enable/disable Airbnb style soft autocomplete in the input field. +(NOTE: This feature is experimental and not supported in mobile browsers) #### classNames Type: `Object`, diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index ad19901f..5d54bc74 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -69,7 +69,7 @@ PlacesAutocomplete.defaultProps = { autocompleteItem: ({ suggestion }) => (
{suggestion}
), styles: {}, options: {}, - typeAhead: true, + typeAhead: false, } export default PlacesAutocomplete From 711d816d3adfa12ebc9096f2be44f0d36b578abf Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 5 Apr 2017 07:34:59 -0700 Subject: [PATCH 037/165] fix(keyboard-event-handler): Fix keydown event handler when no autocomplete items exist Fix #49 --- src/PlacesAutocompleteBasic.js | 12 ++++++++++++ src/PlacesAutocompleteWithTypeAhead.js | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index bf4f4105..406a83ea 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -69,6 +69,10 @@ class PlacesAutocompleteBasic extends Component { } handleEnterKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.handleEnterKeyWithoutActiveItem() @@ -87,6 +91,10 @@ class PlacesAutocompleteBasic extends Component { } handleDownKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.selectActiveItemAtIndex(0) @@ -97,6 +105,10 @@ class PlacesAutocompleteBasic extends Component { } handleUpKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index 524ed2ee..bd631443 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -106,6 +106,10 @@ class PlacesAutocompleteWithTypeAhead extends Component { } handleEnterKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.handleEnterKeyWithoutActiveItem() @@ -130,6 +134,10 @@ class PlacesAutocompleteWithTypeAhead extends Component { } handleDownKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.selectActiveItemAtIndex(0) @@ -140,6 +148,10 @@ class PlacesAutocompleteWithTypeAhead extends Component { } handleUpKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) From ea88da2965464208e07d532b34c5a7a91f79f830 Mon Sep 17 00:00:00 2001 From: Alexander Gusev Date: Thu, 6 Apr 2017 15:13:34 +0300 Subject: [PATCH 038/165] Changed the hardcoded React version to ^15.0.0 It is not good to hardcode the React version, especially when the library works good with React 15.0.0. By the way, it fixes #28 for those, who are using React !== 15.4.2. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b2dea25..b12dc34e 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,6 @@ ] }, "dependencies": { - "react": "15.4.2" + "react": "^15.0.0" } } From f503ba8c0e9760bba2f98f5b69ac85ab67b1c8bb Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 8 Apr 2017 10:08:03 -0700 Subject: [PATCH 039/165] chore(render): Refactor render function --- src/PlacesAutocompleteBasic.js | 74 +++++++++++-------------- src/PlacesAutocompleteWithTypeAhead.js | 75 +++++++++++--------------- src/defaultStyles.js | 5 +- 3 files changed, 62 insertions(+), 92 deletions(-) diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index 406a83ea..94ddc11f 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -72,7 +72,7 @@ class PlacesAutocompleteBasic extends Component { if (this.state.autocompleteItems.length === 0) { return } - + const activeItem = this.getActiveItem() if (activeItem === undefined) { this.handleEnterKeyWithoutActiveItem() @@ -177,55 +177,41 @@ class PlacesAutocompleteBasic extends Component { } } - renderAutocomplete() { - const { autocompleteItems } = this.state - const { styles } = this.props - if (autocompleteItems.length === 0) { return null } - return ( -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} - style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
- ) - } - - renderInput() { + render() { const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props - return ( - this.clearAutocomplete()} - style={styles.input} - autoFocus={autoFocus} - name={inputName || ''} - id={inputId || ''} - /> - ) - } + const { autocompleteItems } = this.state - render() { - const { classNames, styles } = this.props return (
- {this.renderInput()} - {this.renderAutocomplete()} + this.clearAutocomplete()} + style={styles.input} + autoFocus={autoFocus} + name={inputName || ''} + id={inputId || ''} + /> +
+ {autocompleteItems.map((p, idx) => ( +
this.setActiveItemAtIndex(p.index)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
) } diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index bd631443..68e206aa 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -345,63 +345,48 @@ class PlacesAutocompleteWithTypeAhead extends Component { } } - renderAutocomplete() { - const { autocompleteItems } = this.state - const { styles } = this.props - if (autocompleteItems.length === 0) { return null } - return ( -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.handleAutocompleteItemMouseDown(p.suggestion, p.placeId)} - style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
- ) - } - isMatch(subject, target) { const normalizedSubject = subject.toLowerCase() const normalizedTarget = target.toLowerCase() return normalizedSubject === normalizedTarget.substr(0, subject.length) } - renderInput() { - const { firstSuggestion, userTypedValue } = this.state + render() { const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props - return ( - this.clearAutocomplete()} - style={styles.input} - autoFocus={autoFocus} - name={inputName || ''} - id={inputId || ''} - ref="inputField" - /> - ) - } + const { firstSuggestion, userTypedValue, autocompleteItems } = this.state - render() { - const { classNames, styles } = this.props return (
- {this.renderInput()} - {this.renderAutocomplete()} + this.clearAutocomplete()} + style={styles.input} + autoFocus={autoFocus} + name={inputName || ''} + id={inputId || ''} + ref="inputField" + /> +
+ {autocompleteItems.map((p, idx) => ( +
this.setActiveItemAtIndex(p.index)} + onMouseDown={() => this.handleAutocompleteItemMouseDown(p.suggestion, p.placeId)} + style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
) } diff --git a/src/defaultStyles.js b/src/defaultStyles.js index 1f0cbbc3..fa7834ff 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -7,14 +7,13 @@ const defaultStyles = { position: 'absolute', top: '100%', backgroundColor: 'white', - border: '1px solid #555', + border: '1px solid #555555', width: '100%', - zIndex: 9999, }, autocompleteItem: { backgroundColor: '#ffffff', padding: '10px', - color: '#555', + color: '#555555', cursor: 'pointer', }, autocompleteItemActive: { From d8910496d176a2aadf26c4e21649a4d12b730768 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 8 Apr 2017 11:50:30 -0700 Subject: [PATCH 040/165] fix(styling): Allow for easy overrides with classNames and styles props Closes #30 --- README.md | 39 +++++++++++++++- demo/Demo.js | 5 +- demo/app.css | 11 ++--- src/PlacesAutocomplete.js | 2 + src/PlacesAutocompleteBasic.js | 64 ++++++++++++++++++-------- src/PlacesAutocompleteWithTypeAhead.js | 64 ++++++++++++++++++-------- src/defaultStyles.js | 5 ++ 7 files changed, 143 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 8c69631f..d48a5d83 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,9 @@ Type: `Object`, Required: `false` You can give a custom css classes to elements. -Accepted keys are `root`, `input`, `autocompleteContainer` +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. +If you pass `classNames` props, none of the default inline styles nor inline styles from `styles` prop will +be applied to the element, and you will have full control over styling via CSS. ```js // classNames example @@ -211,7 +213,40 @@ Type `Object`, Required: `false` You can provide custom inline styles to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive` +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. + +```js +const defaultStyles = { + root: { + position: 'relative', + paddingBottom: '0px', + }, + input: { + display: 'inline-block', + width: '100%', + padding: '10px', + }, + autocompleteContainer: { + position: 'absolute', + top: '100%', + backgroundColor: 'white', + border: '1px solid #555555', + width: '100%', + }, + autocompleteItem: { + backgroundColor: '#ffffff', + padding: '10px', + color: '#555555', + cursor: 'pointer', + }, + autocompleteItemActive: { + backgroundColor: '#fafafa' + } +} +``` + +Object passed via `styles` prop will be merged in with the above defaults and applied to their respective elements. +NOTE: Passing `classNames` will disable any inline styling for respective elements. ```js // custom style examples diff --git a/demo/Demo.js b/demo/Demo.js index ae3497c8..51303dcc 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -64,9 +64,8 @@ class Demo extends React.Component { render() { const cssClasses = { root: 'form-group', - label: 'form-label', input: 'Demo__search-input', - autocompleteContainer: 'Demo__autocomplete-container' + autocompleteContainer: 'Demo__autocomplete-container', } const AutocompleteItem = ({ formattedSuggestion }) => ( @@ -92,13 +91,13 @@ class Demo extends React.Component { value={this.state.address} onChange={this.handleChange} onSelect={this.handleSelect} - classNames={cssClasses} autocompleteItem={AutocompleteItem} autoFocus={true} placeholder="Search Places" hideLabel={true} inputName="Demo__input" onEnterKeyDown={this.handleSelect} + classNames={cssClasses} /> {this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ? diff --git a/demo/app.css b/demo/app.css index c47f32c5..6b3a5704 100644 --- a/demo/app.css +++ b/demo/app.css @@ -54,12 +54,11 @@ body, #root, .page-wrapper { outline: none; } -/* TODO: Allow user to override default styles without using !important flag */ .Demo__autocomplete-container { - border-bottom: honeydew !important; - border-left: honeydew !important; - border-right: honeydew !important; - border-top: 1px solid #e6e6e6 !important; + border-bottom: honeydew; + border-left: honeydew; + border-right: honeydew; + border-top: 1px solid #e6e6e6; box-shadow: 0 2px 4px rgba(0,0,0,0.2); border-radius: 0 0 2px 2px; } @@ -70,7 +69,7 @@ body, #root, .page-wrapper { } .Demo__spinner { - color: #18bc9c !important; + color: #18bc9c; font-size: 30px; } diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 5d54bc74..e1d3f5b6 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -35,6 +35,8 @@ PlacesAutocomplete.propTypes = { root: React.PropTypes.string, input: React.PropTypes.string, autocompleteContainer: React.PropTypes.string, + autocompleteItem: React.PropTypes.string, + autocompleteItemActive: React.PropTypes.string, }), styles: React.PropTypes.shape({ root: React.PropTypes.object, diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js index 94ddc11f..94796e19 100644 --- a/src/PlacesAutocompleteBasic.js +++ b/src/PlacesAutocompleteBasic.js @@ -177,41 +177,69 @@ class PlacesAutocompleteBasic extends Component { } } + inlineStyleFor(...props) { + const { classNames, styles } = this.props + // No inline style if className is passed via props for the element. + if (props.some(prop => classNames.hasOwnProperty(prop))) { + return {} + } + + return props.reduce((acc, prop) => { + return { + ...acc, + ...defaultStyles[prop], + ...styles[prop], + } + }, {}) + } + + classNameFor(...props) { + const { classNames } = this.props + + return props.reduce((acc, prop) => { + const name = classNames[prop] || '' + return name ? `${acc} ${name}` : acc + }, '') + } + render() { const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props const { autocompleteItems } = this.state return (
+ style={this.inlineStyleFor('root')} + className={this.classNameFor('root')}> this.clearAutocomplete()} - style={styles.input} + style={this.inlineStyleFor('input')} + className={this.classNameFor('input')} autoFocus={autoFocus} name={inputName || ''} id={inputId || ''} /> -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} - style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
+ {autocompleteItems.length > 0 && ( +
+ {autocompleteItems.map((p, idx) => ( +
this.setActiveItemAtIndex(p.index)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } + className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
+ )}
) } diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js index 68e206aa..851aca83 100644 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ b/src/PlacesAutocompleteWithTypeAhead.js @@ -351,42 +351,70 @@ class PlacesAutocompleteWithTypeAhead extends Component { return normalizedSubject === normalizedTarget.substr(0, subject.length) } + inlineStyleFor(...props) { + const { classNames, styles } = this.props + // No inline style if className is passed via props for the element. + if (props.some(prop => classNames.hasOwnProperty(prop))) { + return {} + } + + return props.reduce((acc, prop) => { + return { + ...acc, + ...defaultStyles[prop], + ...styles[prop], + } + }, {}) + } + + classNameFor(...props) { + const { classNames } = this.props + + return props.reduce((acc, prop) => { + const name = classNames[prop] || '' + return name ? `${acc} ${name}` : acc + }, '') + } + render() { const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props const { firstSuggestion, userTypedValue, autocompleteItems } = this.state return (
+ style={this.inlineStyleFor('root')} + className={this.classNameFor('root')}> this.clearAutocomplete()} - style={styles.input} + style={this.inlineStyleFor('input')} + className={this.classNameFor('input')} autoFocus={autoFocus} name={inputName || ''} id={inputId || ''} ref="inputField" /> -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.handleAutocompleteItemMouseDown(p.suggestion, p.placeId)} - style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
+ {autocompleteItems.length > 0 && ( +
+ {autocompleteItems.map((p, idx) => ( +
this.setActiveItemAtIndex(p.index)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } + className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
+ )}
) } diff --git a/src/defaultStyles.js b/src/defaultStyles.js index fa7834ff..adefa472 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -3,6 +3,11 @@ const defaultStyles = { position: 'relative', paddingBottom: '0px', }, + input: { + display: 'inline-block', + width: '100%', + padding: '10px', + }, autocompleteContainer: { position: 'absolute', top: '100%', From db63d3e0ebad404ca686e8151f11371c4c269da1 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 15 Apr 2017 10:59:39 -0700 Subject: [PATCH 041/165] feat(props): Add inputProps to allow user to pass arbitrary props to input element Added props inputProps (object): requires `value` and `onChange` properties. BREAKING CHANGE: Major version update --- .babelrc | 18 + README.md | 125 +++---- package.json | 17 +- src/PlacesAutocomplete.js | 339 +++++++++++++++--- src/PlacesAutocompleteBasic.js | 248 ------------- src/PlacesAutocompleteWithTypeAhead.js | 423 ---------------------- src/helpers.js | 6 - src/tests/index.spec.js | 472 +++++++++++++------------ 8 files changed, 608 insertions(+), 1040 deletions(-) create mode 100644 .babelrc delete mode 100644 src/PlacesAutocompleteBasic.js delete mode 100644 src/PlacesAutocompleteWithTypeAhead.js delete mode 100644 src/helpers.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..001d476f --- /dev/null +++ b/.babelrc @@ -0,0 +1,18 @@ +{ + "env": { + "development": { + "presets": ["es2015", "stage-0", "react"], + "plugins": ["transform-class-properties"] + }, + "production": { + "presets": ["es2015", "stage-0", "react"], + "plugins": [ + [ + "transform-react-remove-prop-types", { + "mode": "wrap" + } + ] + ] + } + } +} diff --git a/README.md b/README.md index d48a5d83..0fc9d560 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ A React component to build a customized UI for Google Maps Places Autocomplete ( [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/react-places-autocomplete/Lobby) ### Features -1. Enable you to easily build a customized autocomplete dropdown powered by Google Maps Places Library -2. Utility function to get latitude and longitude using Google Maps Geocoder API -3. Airbnb style typeahead input field +1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) +2. [Utility function](#geocode) to get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) +3. Pass through arbitrary props to the input element to integrate well with other libraries (e.g. Redux-Form) ### Installation To install the stable version @@ -65,22 +65,23 @@ class SimpleForm extends React.Component { handleFormSubmit = (event) => { event.preventDefault() - const { address } = this.state - geocodeByAddress(address, (err, { lat, lng }) => { + geocodeByAddress(this.state.address, (err, latLng) => { if (err) { console.log('Oh no!', err) } - console.log(`Yay! got latitude and longitude for ${address}`, { lat, lng }) + console.log(`Yay! Got latitude and longitude for ${address}`, latLng) }) } render() { + const inputProps = { + value: this.state.address, + onChange: this.onChange, + } + return (
- + ) @@ -94,37 +95,42 @@ export default SimpleForm #### Require Props: -* value -* onChange +* [`inputProps`](#inputProps) #### Optional Props: -* autocompleteItem -* typeAhead -* classNames -* styles -* placeholder -* onError -* clearItemsOnError -* onSelect -* onEnterKeyDown -* options -* autoFocus -* inputName -* inputId - -#### value -Type: `String`, +* [`autocompleteItem`](#autocompleteItem) +* [`classNames`](#classNames) +* [`styles`](#styles) +* [`onError`](#onError) +* [`clearItemsOnError`](#clearItemsOnError) +* [`onSelect`](#onSelect) +* [`onEnterKeyDown`](#onEnterKeyDown) +* [`options`](#options) + + +#### inputProps +Type: `Object`, Required: `true` -Value displayed in the input field +PlacesAutocomplete is a [controlled component](https://facebook.github.io/react/docs/forms.html#controlled-components). Therefore, you MUST pass at least `value` and `onChange` callback to the input element. -#### onChange -Type: `Function`, -Required: `true` +You can pass arbitrary props to the input element thorough `inputProps` object (NOTE: `className` and `style` props for the input element should be passed through `classNames.input` and `styles.input` respectively). -Please see the example above +```js + const inputProps = { + value, + onChange, + onBlur: () => { + console.log('blur!') + }, + type: 'search', + placeholder: 'Search Places...', + autoFocus: true, + } +``` + #### autocompleteItem Type: `Functional React Component`, Required: `false` @@ -142,8 +148,7 @@ render() { return ( ) @@ -163,22 +168,14 @@ render() { return ( ) } ``` -#### typeAhead -Type: `Boolean` -Required: `false` -Default: `false` - -You can enable/disable Airbnb style soft autocomplete in the input field. -(NOTE: This feature is experimental and not supported in mobile browsers) - + #### classNames Type: `Object`, Required: `false` @@ -199,8 +196,7 @@ render() { return ( ) @@ -208,6 +204,7 @@ render() { ``` Now you can easily apply custom CSS styles using the classNames! + #### styles Type `Object`, Required: `false` @@ -261,21 +258,14 @@ render() { return ( ) } ``` -#### placeholder -Type: `String`, -Required: `false`, -Default: `"Address"` - -You can pass `placeholder` prop to customize input's placeholder text - + #### onError Type: `Function` Required: `false` @@ -284,6 +274,7 @@ You can pass `onError` prop to customize the behavior when [google.maps.places.P Function takes `status` as a parameter + #### clearItemsOnError Type: `Boolean` Required: `false` @@ -291,6 +282,7 @@ Default: `false` You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK + #### onSelect Type: `Function` Required: `false`, @@ -310,12 +302,12 @@ const handleSelect = (address, placeId) => { // Pass this function via onSelect prop. ``` + #### onEnterKeyDown Type: `Function` Required: `false` @@ -341,6 +333,7 @@ const handleEnter = (address) => { /> ``` + #### options Type: `Object` Required: `false` @@ -366,21 +359,7 @@ const options = { /> ``` -#### autoFocus -Type: `Boolean` -Required: `false` -Default: `false` - -#### inputName -Type: `String` -Required: `false` -Default: Empty String - -#### inputId -Type: `String` -Required: `false` -Default: Empty String - + ### `geocodeByAddress` API ```js diff --git a/package.json b/package.json index b12dc34e..91966b8b 100644 --- a/package.json +++ b/package.json @@ -52,12 +52,15 @@ }, "homepage": "https://github.com/kenny-hibino/react-places-autocomplete#readme", "devDependencies": { - "babel-cli": "6.10.1", - "babel-loader": "6.2.4", - "babel-preset-es2015": "6.9.0", - "babel-preset-react": "6.11.1", - "babel-preset-stage-2": "6.11.0", - "babel-register": "6.9.0", + "babel-cli": "^6.23.0", + "babel-loader": "^6.3.2", + "babel-plugin-react-transform": "^2.0.2", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-react-remove-prop-types": "^0.3.2", + "babel-preset-es2015": "^6.22.0", + "babel-preset-react": "^6.23.1", + "babel-preset-stage-0": "^6.22.0", + "babel-register": "^6.23.0", "chai": "3.5.0", "chai-enzyme": "0.5.0", "commitizen": "2.8.2", @@ -76,7 +79,7 @@ "rimraf": "2.5.3", "semantic-release": "^4.3.5", "sinon": "1.17.4", - "webpack": "1.13.1", + "webpack": "^1.14.0", "webpack-dev-server": "^1.16.2" }, "config": { diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index e1d3f5b6..f441d9b0 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -4,74 +4,313 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React from 'react' -import PlacesAutocompleteWithTypeAhead from './PlacesAutocompleteWithTypeAhead' -import PlacesAutocompleteBasic from './PlacesAutocompleteBasic' -import { mobileCheck } from './helpers' - -const PlacesAutocomplete = (props) => { - const { typeAhead, ...rest } = props - // Work around for React KeyDown event issue: https://github.com/facebook/react/issues/6176 - const isMobile = mobileCheck() - if (typeAhead && !isMobile) { - return - } else { - return +import React, { Component, PropTypes } from 'react' +import defaultStyles from './defaultStyles' + +class PlacesAutocomplete extends Component { + constructor(props) { + super(props) + + this.state = { autocompleteItems: [] } + + this.autocompleteCallback = this.autocompleteCallback.bind(this) + this.handleInputKeyDown = this.handleInputKeyDown.bind(this) + this.handleInputChange = this.handleInputChange.bind(this) + } + + componentDidMount() { + this.autocompleteService = new google.maps.places.AutocompleteService() + this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK + } + + autocompleteCallback(predictions, status) { + if (status != this.autocompleteOK) { + this.props.onError(status) + if (this.props.clearItemsOnError) { this.clearAutocomplete() } + return + } + + // transform snake_case to camelCase + const formattedSuggestion = (structured_formatting) => ({ + mainText: structured_formatting.main_text, + secondaryText: structured_formatting.secondary_text, + }) + + this.setState({ + autocompleteItems: predictions.map((p, idx) => ({ + suggestion: p.description, + placeId: p.place_id, + active: false, + index: idx, + formattedSuggestion: formattedSuggestion(p.structured_formatting), + })) + }) + } + + clearAutocomplete() { + this.setState({ autocompleteItems: [] }) + } + + selectAddress(address, placeId) { + this.clearAutocomplete() + this.handleSelect(address, placeId) + } + + handleSelect(address, placeId) { + this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.inputProps.onChange(address) + } + + getActiveItem() { + return this.state.autocompleteItems.find(item => item.active) + } + + selectActiveItemAtIndex(index) { + const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion + this.setActiveItemAtIndex(index) + this.props.inputProps.onChange(activeName) + } + + handleEnterKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + + const activeItem = this.getActiveItem() + if (activeItem === undefined) { + this.handleEnterKeyWithoutActiveItem() + } else { + this.selectAddress(activeItem.suggestion, activeItem.placeId) + } + } + + handleEnterKeyWithoutActiveItem() { + if (this.props.onEnterKeyDown) { + this.props.onEnterKeyDown(this.props.inputProps.value) + this.clearAutocomplete() + } else { + return //noop + } + } + + handleDownKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + + const activeItem = this.getActiveItem() + if (activeItem === undefined) { + this.selectActiveItemAtIndex(0) + } else { + const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length + this.selectActiveItemAtIndex(nextIndex) + } + } + + handleUpKey() { + if (this.state.autocompleteItems.length === 0) { + return + } + + const activeItem = this.getActiveItem() + if (activeItem === undefined) { + this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + } else { + let prevIndex + if (activeItem.index === 0) { + prevIndex = this.state.autocompleteItems.length - 1 + } else { + prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length + } + this.selectActiveItemAtIndex(prevIndex) + } + } + + handleInputKeyDown(event) { + switch (event.key) { + case 'Enter': + event.preventDefault() + this.handleEnterKey() + break + case 'ArrowDown': + event.preventDefault() // prevent the cursor from moving + this.handleDownKey() + break + case 'ArrowUp': + event.preventDefault() // prevent the cursor from moving + this.handleUpKey() + break + case 'Escape': + this.clearAutocomplete() + break + } + + if (this.props.inputProps.onKeyDown) { + this.props.inputProps.onKeyDown(event) + } + } + + setActiveItemAtIndex(index) { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + if (idx === index) { + return { ...item, active: true } + } else { + return { ...item, active: false } + } + }), + }) + } + + handleInputChange(event) { + this.props.inputProps.onChange(event.target.value) + if (!event.target.value) { + this.clearAutocomplete() + return + } + this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) + } + + handleInputOnBlur(event) { + this.clearAutocomplete() + + if (this.props.inputProps.onBlur) { + this.props.inputProps.onBlur(event) + } + } + + inlineStyleFor(...props) { + const { classNames, styles } = this.props + // No inline style if className is passed via props for the element. + if (props.some(prop => classNames.hasOwnProperty(prop))) { + return {} + } + + return props.reduce((acc, prop) => { + return { + ...acc, + ...defaultStyles[prop], + ...styles[prop], + } + }, {}) + } + + classNameFor(...props) { + const { classNames } = this.props + + return props.reduce((acc, prop) => { + const name = classNames[prop] || '' + return name ? `${acc} ${name}` : acc + }, '') + } + + getInputProps() { + const defaultInputProps = { + type: "text", + } + + return { + ...defaultInputProps, + ...this.props.inputProps, + onChange: (event) => { + this.handleInputChange(event) + }, + onKeyDown: (event) => { + this.handleInputKeyDown(event) + }, + onBlur: (event) => { + this.handleInputOnBlur(event) + }, + style: this.inlineStyleFor('input'), + className: this.classNameFor('input'), + } + } + + render() { + const { classNames, styles } = this.props + const { autocompleteItems } = this.state + const inputProps = this.getInputProps() + + return ( +
+ + {autocompleteItems.length > 0 && ( +
+ {autocompleteItems.map((p, idx) => ( +
this.setActiveItemAtIndex(p.index)} + onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } + className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> + {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} +
+ ))} +
+ )} +
+ ) } } PlacesAutocomplete.propTypes = { - value: React.PropTypes.string.isRequired, - onChange: React.PropTypes.func.isRequired, - onError: React.PropTypes.func, - clearItemsOnError: React.PropTypes.bool, - onSelect: React.PropTypes.func, - placeholder: React.PropTypes.string, - autoFocus: React.PropTypes.bool, - inputName: React.PropTypes.string, - inputId: React.PropTypes.string, - autocompleteItem: React.PropTypes.func, - classNames: React.PropTypes.shape({ - root: React.PropTypes.string, - input: React.PropTypes.string, - autocompleteContainer: React.PropTypes.string, - autocompleteItem: React.PropTypes.string, - autocompleteItemActive: React.PropTypes.string, + inputProps: (props, propName) => { + const inputProps = props[propName]; + + if (!inputProps.hasOwnProperty('value')) { + throw new Error('\'inputProps\' must have \'value\'.') + } + + if (!inputProps.hasOwnProperty('onChange')) { + throw new Error('\'inputProps\' must have \'onChange\'.') + } + }, + onError: PropTypes.func, + clearItemsOnError: PropTypes.bool, + onSelect: PropTypes.func, + autocompleteItem: PropTypes.func, + classNames: PropTypes.shape({ + root: PropTypes.string, + input: PropTypes.string, + autocompleteContainer: PropTypes.string, + autocompleteItem: PropTypes.string, + autocompleteItemActive: PropTypes.string, }), - styles: React.PropTypes.shape({ - root: React.PropTypes.object, - input: React.PropTypes.object, - autocompleteContainer: React.PropTypes.object, - autocompleteItem: React.PropTypes.object, - autocompleteItemActive: React.PropTypes.object + styles: PropTypes.shape({ + root: PropTypes.object, + input: PropTypes.object, + autocompleteContainer: PropTypes.object, + autocompleteItem: PropTypes.object, + autocompleteItemActive: PropTypes.object }), - options: React.PropTypes.shape({ - bounds: React.PropTypes.object, - componentRestrictions: React.PropTypes.object, - location: React.PropTypes.object, - offset: React.PropTypes.oneOfType([ - React.PropTypes.number, - React.PropTypes.string + options: PropTypes.shape({ + bounds: PropTypes.object, + componentRestrictions: PropTypes.object, + location: PropTypes.object, + offset: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string ]), - radius: React.PropTypes.oneOfType([ - React.PropTypes.number, - React.PropTypes.string + radius: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string ]), - types: React.PropTypes.array + types: PropTypes.array }), - typeAhead: React.PropTypes.bool, } PlacesAutocomplete.defaultProps = { clearItemsOnError: false, onError: (status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), - placeholder: 'Address', - autoFocus: false, classNames: {}, autocompleteItem: ({ suggestion }) => (
{suggestion}
), styles: {}, options: {}, - typeAhead: false, } export default PlacesAutocomplete diff --git a/src/PlacesAutocompleteBasic.js b/src/PlacesAutocompleteBasic.js deleted file mode 100644 index 94796e19..00000000 --- a/src/PlacesAutocompleteBasic.js +++ /dev/null @@ -1,248 +0,0 @@ -/* -* Copyright (c) 2017 Ken Hibino. -* Licensed under the MIT License (MIT). -* See https://kenny-hibino.github.io/react-places-autocomplete -*/ - -import React, { Component } from 'react' -import defaultStyles from './defaultStyles' - -class PlacesAutocompleteBasic extends Component { - constructor(props) { - super(props) - - this.state = { autocompleteItems: [] } - - this.autocompleteCallback = this.autocompleteCallback.bind(this) - this.handleInputKeyDown = this.handleInputKeyDown.bind(this) - this.handleInputChange = this.handleInputChange.bind(this) - } - - componentDidMount() { - this.autocompleteService = new google.maps.places.AutocompleteService() - this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK - } - - autocompleteCallback(predictions, status) { - if (status != this.autocompleteOK) { - this.props.onError(status) - if (this.props.clearItemsOnError) { this.clearAutocomplete() } - return - } - - this.setState({ - autocompleteItems: predictions.map((p, idx) => ({ - suggestion: p.description, - placeId: p.place_id, - active: false, - index: idx, - formattedSuggestion: this.formattedSuggestion(p.structured_formatting), - })) - }) - } - - formattedSuggestion(structured_formatting) { - return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } - } - - clearAutocomplete() { - this.setState({ autocompleteItems: [] }) - } - - selectAddress(address, placeId) { - this.clearAutocomplete() - this.handleSelect(address, placeId) - } - - handleSelect(address, placeId) { - this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) - } - - getActiveItem() { - return this.state.autocompleteItems.find(item => item.active) - } - - selectActiveItemAtIndex(index) { - const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion - this.setActiveItemAtIndex(index) - this.props.onChange(activeName) - } - - handleEnterKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.handleEnterKeyWithoutActiveItem() - } else { - this.selectAddress(activeItem.suggestion, activeItem.placeId) - } - } - - handleEnterKeyWithoutActiveItem() { - if (this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(this.props.value) - this.clearAutocomplete() - } else { - return //noop - } - } - - handleDownKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.selectActiveItemAtIndex(0) - } else { - const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length - this.selectActiveItemAtIndex(nextIndex) - } - } - - handleUpKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) - } else { - let prevIndex - if (activeItem.index === 0) { - prevIndex = this.state.autocompleteItems.length - 1 - } else { - prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length - } - this.selectActiveItemAtIndex(prevIndex) - } - } - - handleInputKeyDown(event) { - const ARROW_UP = 38 - const ARROW_DOWN = 40 - const ENTER_KEY = 13 - const ESC_KEY = 27 - - switch (event.keyCode) { - case ENTER_KEY: - event.preventDefault() - this.handleEnterKey() - break - case ARROW_DOWN: - event.preventDefault() // prevent the cursor from moving - this.handleDownKey() - break - case ARROW_UP: - event.preventDefault() // prevent the cursor from moving - this.handleUpKey() - break - case ESC_KEY: - this.clearAutocomplete() - break - } - } - - setActiveItemAtIndex(index) { - this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { - if (idx === index) { - return { ...item, active: true } - } else { - return { ...item, active: false } - } - }), - }) - } - - handleInputChange(event) { - this.props.onChange(event.target.value) - if (!event.target.value) { - this.clearAutocomplete() - return - } - this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) - } - - autocompleteItemStyle(active) { - if (active) { - return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive } - } else { - return {} - } - } - - inlineStyleFor(...props) { - const { classNames, styles } = this.props - // No inline style if className is passed via props for the element. - if (props.some(prop => classNames.hasOwnProperty(prop))) { - return {} - } - - return props.reduce((acc, prop) => { - return { - ...acc, - ...defaultStyles[prop], - ...styles[prop], - } - }, {}) - } - - classNameFor(...props) { - const { classNames } = this.props - - return props.reduce((acc, prop) => { - const name = classNames[prop] || '' - return name ? `${acc} ${name}` : acc - }, '') - } - - render() { - const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props - const { autocompleteItems } = this.state - - return ( -
- this.clearAutocomplete()} - style={this.inlineStyleFor('input')} - className={this.classNameFor('input')} - autoFocus={autoFocus} - name={inputName || ''} - id={inputId || ''} - /> - {autocompleteItems.length > 0 && ( -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} - style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } - className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
- )} -
- ) - } -} - -export default PlacesAutocompleteBasic diff --git a/src/PlacesAutocompleteWithTypeAhead.js b/src/PlacesAutocompleteWithTypeAhead.js deleted file mode 100644 index 851aca83..00000000 --- a/src/PlacesAutocompleteWithTypeAhead.js +++ /dev/null @@ -1,423 +0,0 @@ -/* -* Copyright (c) 2017 Ken Hibino. -* Licensed under the MIT License (MIT). -* See https://kenny-hibino.github.io/react-places-autocomplete -*/ - -import React, { Component } from 'react' -import defaultStyles from './defaultStyles' - -class PlacesAutocompleteWithTypeAhead extends Component { - constructor(props) { - super(props) - - this.state = { - autocompleteItems: [], - firstSuggestion: '', - userTypedValue: '', - shouldTypeAhead: true, - } - - this.autocompleteCallback = this.autocompleteCallback.bind(this) - this.handleInputKeyDown = this.handleInputKeyDown.bind(this) - this.handleInputChange = this.handleInputChange.bind(this) - } - - componentDidMount() { - this.autocompleteService = new google.maps.places.AutocompleteService() - this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK - this.autocompleteZeroResult = google.maps.places.PlacesServiceStatus.ZERO_RESULTS - } - - componentDidUpdate(prevProps, prevState) { - const { firstSuggestion, userTypedValue } = this.state - - if (userTypedValue.length < prevState.userTypedValue.length) { - return // noop - } - - if (this.shouldSoftAutcomplete()) { - this.refs.inputField.setSelectionRange(userTypedValue.length, firstSuggestion.length) - } - } - - autocompleteCallback(predictions, status) { - if (status === this.autocompleteZeroResult) { - this.setState({ - autocompleteItems: [], - firstSuggestion: '', - }) - return - } - - if (status != this.autocompleteOK) { - this.props.onError(status) - if (this.props.clearItemsOnError) { this.clearAutocomplete() } - return - } - - this.setState({ - autocompleteItems: predictions.map((p, idx) => ({ - suggestion: p.description, - placeId: p.place_id, - active: false, - index: idx, - formattedSuggestion: this.formattedSuggestion(p.structured_formatting), - })), - firstSuggestion: predictions[0].description, - }) - - this.updateInputValue() - } - - formattedSuggestion(structured_formatting) { - return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text } - } - - clearAutocomplete() { - this.setState({ autocompleteItems: [] }) - } - - selectAddress(address, placeId) { - this.clearAutocomplete() - this.handleSelect(address, placeId) - } - - handleSelect(address, placeId) { - this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.onChange(address) - } - - handleAutocompleteItemMouseDown(address, placeId) { - this.selectAddress(address, placeId) - this.setState({ - userTypedValue: address, - }) - } - - getActiveItem() { - return this.state.autocompleteItems.find(item => item.active) - } - - selectActiveItemAtIndex(index) { - const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion - this.setActiveItemAtIndex(index) - this.props.onChange(activeName) - this.setState({ userTypedValue: activeName }) - } - - handleEnterKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.handleEnterKeyWithoutActiveItem() - } else { - this.selectAddress(activeItem.suggestion, activeItem.placeId) - } - - this.refs.inputField.focus() - this.refs.inputField.setSelectionRange(0,0) - this.setState({ - userTypedValue: this.props.value - }) - } - - handleEnterKeyWithoutActiveItem() { - if (this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(this.props.value) - this.clearAutocomplete() - } else { - return //noop - } - } - - handleDownKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.selectActiveItemAtIndex(0) - } else { - const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length - this.selectActiveItemAtIndex(nextIndex) - } - } - - handleUpKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - - const activeItem = this.getActiveItem() - if (activeItem === undefined) { - this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) - } else { - let prevIndex - if (activeItem.index === 0) { - prevIndex = this.state.autocompleteItems.length - 1 - } else { - prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length - } - this.selectActiveItemAtIndex(prevIndex) - } - } - - handleDeleteKey() { - const { userTypedValue, firstSuggestion } = this.state - if (userTypedValue.length === 0) { - return // noop - } - const selectionString = window.getSelection().toString() - const cursorPosition = this.refs.inputField.selectionStart - const isPlainBackSpace = ( - selectionString === firstSuggestion.replace(userTypedValue, '') || - selectionString.length === 0 - ) - - if (isPlainBackSpace) { - this.setState({ - userTypedValue: userTypedValue.slice(0, cursorPosition - 1) + userTypedValue.slice(cursorPosition, userTypedValue.length), - shouldTypeAhead: false, - firstSuggestion: '', - }) - } else { - this.setState({ - userTypedValue: this.props.value.replace(selectionString, ''), - shouldTypeAhead: false, - firstSuggestion: '', - }) - } - } - - handleTabKey() { - this.refs.inputField.focus() - this.refs.inputField.setSelectionRange(0,0) - this.refs.inputField.blur() - this.setState({ - userTypedValue: this.props.value - }) - } - - handleRightLeftKey() { - this.setState({ - userTypedValue: this.props.value, - shouldTypeAhead: false, - }) - } - - handleDefaultKey(event) { - if (event.key.length > 1) { return } - const { userTypedValue } = this.state - const selectionString = window.getSelection().toString() - - if (selectionString.length === 0) { - const cursorPosition = this.refs.inputField.selectionStart - this.setState({ - userTypedValue: this.props.value.slice(0, cursorPosition) + event.key + this.props.value.slice(cursorPosition, this.props.value.length), - shouldTypeAhead: true, - }) - } else if (this.props.value === `${userTypedValue}${selectionString}`) { - this.setState({ - userTypedValue: this.fixCasing(this.state.userTypedValue + event.key), - shouldTypeAhead: true, - }) - } else { - this.setState({ - userTypedValue: this.props.value.replace(selectionString, event.key), - shouldTypeAhead: false, - }) - } - } - - handleInputKeyDown(event) { - const onlyShiftKeyDown = (event.shiftKey && event.keyCode === 16) - const onlyAltKeyDown = (event.altKey && event.keyCode === 18) - if ( onlyShiftKeyDown || onlyAltKeyDown || event.ctrlKey || event.metaKey) { - return // noop - } - - const ARROW_LEFT = 37 - const ARROW_UP = 38 - const ARROW_RIGHT = 39 - const ARROW_DOWN = 40 - const ENTER_KEY = 13 - const ESC_KEY = 27 - const DELETE_KEY = 8 - const TAB_KEY = 9 - - switch (event.keyCode) { - case ENTER_KEY: - event.preventDefault() - this.handleEnterKey() - break - case ARROW_DOWN: - event.preventDefault() // prevent the cursor from moving - this.handleDownKey() - break - case ARROW_UP: - event.preventDefault() // prevent the cursor from moving - this.handleUpKey() - break - case ESC_KEY: - this.clearAutocomplete() - break - case DELETE_KEY: - this.handleDeleteKey() - break - case TAB_KEY: - this.handleTabKey() - break; - case ARROW_LEFT: - case ARROW_RIGHT: - this.handleRightLeftKey() - break - default: - this.handleDefaultKey(event) - } - } - - fixCasing(newValue) { - const { firstSuggestion} = this.state - if (firstSuggestion.length === 0) { - return newValue - } - - if (this.isMatch(newValue, firstSuggestion)) { - return firstSuggestion.substr(0, newValue.length) - } - - return newValue - } - - setActiveItemAtIndex(index) { - this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { - if (idx === index) { - return { ...item, active: true } - } else { - return { ...item, active: false } - } - }), - }) - } - - updateInputValue() { - const { firstSuggestion, userTypedValue } = this.state - if (this.shouldSoftAutcomplete()) { - this.props.onChange(firstSuggestion) - } else { - this.props.onChange(userTypedValue) - } - } - - shouldSoftAutcomplete() { - const { firstSuggestion, userTypedValue, shouldTypeAhead } = this.state - return ( - (firstSuggestion !== '' && userTypedValue !== '') && - this.isMatch(userTypedValue, firstSuggestion) && - shouldTypeAhead - ) - } - - handleInputChange(event) { - this.updateInputValue() - - const { userTypedValue } = this.state - if (userTypedValue.length === 0) { - this.clearAutocomplete() - return - } - - if (this.state.shouldTypeAhead) { - this.autocompleteService.getPlacePredictions({ ...this.props.options, input: userTypedValue }, this.autocompleteCallback) - } - } - - autocompleteItemStyle(active) { - if (active) { - return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive } - } else { - return {} - } - } - - isMatch(subject, target) { - const normalizedSubject = subject.toLowerCase() - const normalizedTarget = target.toLowerCase() - return normalizedSubject === normalizedTarget.substr(0, subject.length) - } - - inlineStyleFor(...props) { - const { classNames, styles } = this.props - // No inline style if className is passed via props for the element. - if (props.some(prop => classNames.hasOwnProperty(prop))) { - return {} - } - - return props.reduce((acc, prop) => { - return { - ...acc, - ...defaultStyles[prop], - ...styles[prop], - } - }, {}) - } - - classNameFor(...props) { - const { classNames } = this.props - - return props.reduce((acc, prop) => { - const name = classNames[prop] || '' - return name ? `${acc} ${name}` : acc - }, '') - } - - render() { - const { classNames, placeholder, styles, value, autoFocus, inputName, inputId } = this.props - const { firstSuggestion, userTypedValue, autocompleteItems } = this.state - - return ( -
- this.clearAutocomplete()} - style={this.inlineStyleFor('input')} - className={this.classNameFor('input')} - autoFocus={autoFocus} - name={inputName || ''} - id={inputId || ''} - ref="inputField" - /> - {autocompleteItems.length > 0 && ( -
- {autocompleteItems.map((p, idx) => ( -
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} - style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } - className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} -
- ))} -
- )} -
- ) - } -} - -export default PlacesAutocompleteWithTypeAhead diff --git a/src/helpers.js b/src/helpers.js deleted file mode 100644 index f1fc8230..00000000 --- a/src/helpers.js +++ /dev/null @@ -1,6 +0,0 @@ -// Detect mobile browser -export const mobileCheck = () => { - let check = false; - (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); - return check; -} diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index fa04753c..f863561f 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,233 +1,239 @@ -// import React from 'react' -// import TestUtils from 'react-addons-test-utils' -// import { mount, shallow } from 'enzyme' -// import sinon from 'sinon' -// import { expect } from './testHelper' -// import PlacesAutocomplete, { geocodeByAddress } from '../index.js' -// -// /*** Enzyme Rocks ***/ -// describe('', () => { -// let wrapper; -// beforeEach(() => { -// wrapper = shallow( {}} />) -// }) -// -// it('renders an input element', () => { -// expect(wrapper.find('input')).to.have.length(1) -// }) -// }); -// -// describe('PlacesAutocomplete callbacks', () => { -// it('calls componentDidMount', () => { -// sinon.spy(PlacesAutocomplete.prototype, 'componentDidMount') -// const wrapper = mount( {}} />) -// expect(PlacesAutocomplete.prototype.componentDidMount.calledOnce).to.equal(true) -// }) -// -// it('executes onError callback passed in as prop when status is not OK', () => { -// const spy = sinon.spy() -// const wrapper = mount( {}} />) -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') -// expect(spy.calledOnce).to.equal(true) -// expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) -// }) -// -// it('executes default onError function when there is no custom prop and status is not OK', () => { -// sinon.stub(console, 'error') -// const wrapper = mount( {}} />) -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') -// expect(console.error.calledOnce).to.equal(true) -// }) -// }); -// -// describe('PlacesAutocomplete props', () => { -// it('allows user to set the value of the input through prop', () => { -// const wrapper = mount( {}} />) -// expect(wrapper.find('input').props().value).to.equal("San Francisco, CA") -// }) -// }); -// -// describe('autocomplete dropdown', () => { -// let wrapper; -// const autocompleteItem = ({ suggestion }) => (
{suggestion}
) -// beforeEach(() => { -// wrapper = shallow( {}} autocompleteItem={autocompleteItem} />) -// }) -// -// it('initially does not have an autocomplete dropdown', () => { -// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) -// }) -// -// it('renders autocomplete dropdown once it receives data from google maps', () => { -// const data = [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0 -// }, -// { -// suggestion: 'San Jose, CA', -// placeId: 2, -// active: false, -// index: 1 -// }, -// { -// suggestion: 'San Diego, CA', -// placeId: 3, -// active: false, -// index: 2 -// } -// ] -// wrapper.setState({ autocompleteItems: data }) -// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) -// expect(wrapper.find('.autocomplete-item')).to.have.length(3) -// }) -// -// it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { -// const initialItems = [{ -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0 -// }] -// const wrapper = shallow( {}} clearItemsOnError={true}/>) -// wrapper.setState({ autocompleteItems: initialItems }) -// wrapper.instance().autocompleteCallback([], 'error') -// expect(wrapper.find('.autocomplete-item')).to.have.length(0) -// }) -// -// it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { -// const initialItems = [{ -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0 -// }] -// wrapper.setState({ autocompleteItems: initialItems }) -// wrapper.instance().autocompleteCallback([], 'error') -// expect(wrapper.find('.autocomplete-item')).to.have.length(1) -// }) -// }) -// -// describe('custom classNames, placeholder', () => { -// const classNames = { -// root: 'my-container', -// input: 'my-input', -// autocompleteContainer: 'my-autocomplete-container' -// } -// -// let wrapper; -// -// beforeEach(() => { -// wrapper = shallow( {}} -// classNames={classNames} -// placeholder="Your Address" -// />) -// }) -// -// it('lets you set a custom className for the container', () => { -// expect(wrapper.find('.my-container')).to.have.length(1) -// }) -// -// it('lets you set a custom className for the input', () => { -// expect(wrapper.find('input')).to.have.className('my-input') -// }) -// -// it('lets you set a custom className for autocomplete container', () => { -// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) -// expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.className('my-autocomplete-container') -// }) -// -// it('lets you set a custom placeholder for the input', () => { -// expect(wrapper.find('input').props().placeholder).to.equal('Your Address') -// }) -// }); -// -// describe('customizable autocompleteItem', () => { -// it('lets you provide a custom autocomplete item', () => { -// const autocompleteItem = ({ suggestion }) => (
) -// const wrapper = shallow( {}} autocompleteItem={autocompleteItem}/>) -// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) -// expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) -// expect(wrapper.find('.my-autocomplete-item')).to.contain() -// }) -// }) -// -// describe('custom inline styles', () => { -// let wrapper; -// beforeEach(() => { -// const styles = { -// root: { position: 'absolute' }, -// input: { width: '100%' }, -// autocompleteContainer: { backgroundColor: 'green' }, -// autocompleteItem: { color: 'black' }, -// autocompleteItemActive: { color: 'blue' } -// } -// const classNames = { -// root: 'root-element', -// input: 'input-element', -// autocompleteContainer: 'autocomplete-container' -// } -// wrapper = shallow( {}}/>) -// }) -// -// it('lets you set custom styles for the root element', () => { -// expect(wrapper.find('.root-element').props().style.position).to.equal('absolute') -// }) -// -// it('lets you set custom styles for the input element', () => { -// expect(wrapper.find('.input-element').props().style.width).to.equal('100%') -// }) -// -// it('lets you set custom styles for the autocomplete container element', () => { -// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) -// expect(wrapper.find('.autocomplete-container').props().style.backgroundColor).to.equal('green') -// }) -// -// it('lets you set custom styles for autocomplete items', () => { -// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) -// const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) -// expect(item.props().style.color).to.equal('black') -// }) -// -// it('lets you set custom styles for active autocomplete items', () => { -// wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] }) -// const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) -// expect(item.props().style.color).to.equal('blue') -// }) -// }) -// -// - // TODO: Make sure this spec passes before pushing to Github - // describe('AutocompletionRequest options', () => { - // it('calls getPlacePredictions with the correct options', () => { - // global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} - // const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') - // const options = { radius: 2000, types: ['address'] } - // const wrapper = mount( {}} options={options} value='test'/>) - // wrapper.find('.input-element').simulate('change', { target: { value: 'test' } }) - // expect(spy.calledWith({ ...options, input: 'test' })).to.be.true - // }) - // }) -// -// describe('autoFocus prop', () => { -// it('automatically gives focus when set to true', () => { -// const wrapper = mount( {}} autoFocus={true} />) -// expect(wrapper.find('input').node).to.equal(document.activeElement) -// }) -// -// it('does not give the input element a focus by default', () => { -// const wrapper = mount( {}} />) -// expect(wrapper.find('input').node).to.not.equal(document.activeElement) -// }) -// }) -// -// // TODO: test geocodeByAddress function -// describe('geocodeByAddress', () => { -// it('should be true', () => { -// expect(true).to.be.true -// }) -// }) +import React from 'react' +import TestUtils from 'react-addons-test-utils' +import { mount, shallow } from 'enzyme' +import sinon from 'sinon' +import { expect } from './testHelper' +import PlacesAutocomplete, { geocodeByAddress } from '../index.js' + +const testInputProps = { + value: "San Francisco, CA", + onChange: () => {}, +} + +/*** Enzyme Rocks ***/ +describe('', () => { + let wrapper; + beforeEach(() => { + wrapper = shallow() + }) + + it('renders an input element', () => { + expect(wrapper.find('input')).to.have.length(1) + }) +}); + +// TODO: What's the value of this test? +describe('PlacesAutocomplete callbacks', () => { + it('executes onError callback passed in as prop when status is not OK', () => { + const spy = sinon.spy() + const wrapper = mount() + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') + expect(spy.calledOnce).to.equal(true) + expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) + }) + + it('executes default onError function when there is no custom prop and status is not OK', () => { + sinon.stub(console, 'error') + const wrapper = mount() + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') + expect(console.error.calledOnce).to.equal(true) + }) +}); + +describe('PlacesAutocomplete props', () => { + it('allows user to set the value of the input through prop', () => { + const inputProps = { + ...testInputProps, + value: "New York, NY", + } + + const wrapper = mount() + expect(wrapper.find('input').props().value).to.equal("New York, NY") + }) +}); + +describe('autocomplete dropdown', () => { + let wrapper; + const autocompleteItem = ({ suggestion }) => (
{suggestion}
) + beforeEach(() => { + wrapper = shallow() + }) + + it('initially does not have an autocomplete dropdown', () => { + expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) + }) + + it('renders autocomplete dropdown once it receives data from google maps', () => { + const data = [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0 + }, + { + suggestion: 'San Jose, CA', + placeId: 2, + active: false, + index: 1 + }, + { + suggestion: 'San Diego, CA', + placeId: 3, + active: false, + index: 2 + } + ] + wrapper.setState({ autocompleteItems: data }) + expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) + expect(wrapper.find('.autocomplete-item')).to.have.length(3) + }) + + it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { + const initialItems = [{ + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0 + }] + const wrapper = shallow() + wrapper.setState({ autocompleteItems: initialItems }) + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') + expect(wrapper.find('.autocomplete-item')).to.have.length(0) + }) + + it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { + const initialItems = [{ + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0 + }] + wrapper.setState({ autocompleteItems: initialItems }) + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') + expect(wrapper.find('.autocomplete-item')).to.have.length(1) + }) +}) + +describe('custom classNames, placeholder', () => { + const inputProps = { + ...testInputProps, + placeholder: "Your Address", + } + + const classNames = { + root: 'my-container', + input: 'my-input', + autocompleteContainer: 'my-autocomplete-container' + } + + let wrapper; + + beforeEach(() => { + wrapper = shallow() + }) + + it('lets you set a custom className for the container', () => { + expect(wrapper.find('.my-container')).to.have.length(1) + }) + + it('lets you set a custom className for the input', () => { + expect(wrapper.find('input')).to.have.className('my-input') + }) + + it('lets you set a custom className for autocomplete container', () => { + wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) + expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.className('my-autocomplete-container') + }) + + it('lets you set a custom placeholder for the input', () => { + expect(wrapper.find('input').props().placeholder).to.equal('Your Address') + }) +}); + +// TODO: test formattedSuggestion +describe('customizable autocompleteItem', () => { + it('lets you provide a custom autocomplete item', () => { + const autocompleteItem = ({ suggestion }) => (
) + const wrapper = shallow() + wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) + expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) + expect(wrapper.find('.my-autocomplete-item')).to.contain() + }) +}) + +describe('custom inline styles', () => { + const styles = { + root: { position: 'absolute' }, + input: { width: '100%' }, + autocompleteContainer: { backgroundColor: 'green' }, + autocompleteItem: { color: 'black' }, + autocompleteItemActive: { color: 'blue' } + } + + let wrapper; + beforeEach(() => { + + wrapper = shallow() + }) + + it('lets you set custom styles for the root element', () => { + expect(wrapper.find('#PlacesAutocomplete__root').props().style.position).to.equal('absolute') + }) + + it('lets you set custom styles for the input element', () => { + expect(wrapper.find('input').props().style.width).to.equal('100%') + }) + + it('lets you set custom styles for the autocomplete container element', () => { + wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) + expect(wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style.backgroundColor).to.equal('green') + }) + + it('lets you set custom styles for autocomplete items', () => { + wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) + const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) + expect(item.props().style.color).to.equal('black') + }) + + it('lets you set custom styles for active autocomplete items', () => { + wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] }) + const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) + expect(item.props().style.color).to.equal('blue') + }) +}) + + describe('AutocompletionRequest options', () => { + const inputProps = { + ...testInputProps, + value: 'Boston, MA', + } + it('calls getPlacePredictions with the correct options', () => { + global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} + const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') + const options = { radius: 2000, types: ['address'] } + const wrapper = mount() + wrapper.find('input').simulate('change', { target: { value: 'Los Angeles, CA' } }) + expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be.true + }) + }) + +describe('autoFocus prop', () => { + const inputProps = { + ...testInputProps, + autoFocus: true, + } + + it('automatically gives focus when set to true', () => { + const wrapper = mount() + expect(wrapper.find('input').node).to.equal(document.activeElement) + }) + + it('does not give the input element a focus by default', () => { + const wrapper = mount() + expect(wrapper.find('input').node).to.not.equal(document.activeElement) + }) +}) + +// TODOs: +// * Test geocodeByAddress function From 7be6eeb9ccd10826e0ec0e1b70898b5af63a5450 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 15 Apr 2017 12:09:27 -0700 Subject: [PATCH 042/165] chore(demo): Update Demo --- demo/Demo.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index 51303dcc..a15127c8 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -75,6 +75,18 @@ class Demo extends React.Component { {formattedSuggestion.secondaryText}
) + const inputProps = { + type: "text", + value: this.state.address, + onChange: this.handleChange, + onBlur: () => { console.log('Blur event!'); }, + onFocus: () => { console.log('Focused!'); }, + autoFocus: true, + placeholder: "Search Places", + name: 'Demo__input', + id: "my-input-id", + } + return (
@@ -88,16 +100,11 @@ class Demo extends React.Component {
{this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ? From e3b94c516ff248bfe4ec7fed296e462e7a333b05 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 17 Apr 2017 08:42:50 -0700 Subject: [PATCH 043/165] chore(readme): Update readme --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0fc9d560..4f61c853 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,8 @@ You can pass arbitrary props to the input element thorough `inputProps` object ( ```js const inputProps = { - value, - onChange, + value, // `value` is required + onChange, // `onChange` is required onBlur: () => { console.log('blur!') }, @@ -327,8 +327,7 @@ const handleEnter = (address) => { // Pass this function via onEnterKeyDown prop. ``` @@ -353,8 +352,7 @@ const options = { } ``` From 259356e447954a1d4fca1892d1f36da954be6ccd Mon Sep 17 00:00:00 2001 From: bvellek Date: Tue, 18 Apr 2017 15:03:29 -0700 Subject: [PATCH 044/165] chore(deps): add prop-types package and update to react ^15.3.0 Added the prop-types package to avoid issues with the deprecation of React.PropTypes in future versions of React. Changed to React^15.3.0 to match suggestions of package. issue #28 --- package.json | 3 ++- src/PlacesAutocomplete.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 91966b8b..395318d6 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ ] }, "dependencies": { - "react": "^15.0.0" + "prop-types": "^15.5.8", + "react": "^15.3.0" } } diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index f441d9b0..16f7823c 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -4,7 +4,8 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React, { Component, PropTypes } from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import defaultStyles from './defaultStyles' class PlacesAutocomplete extends Component { From a9d1a96b6506e3eea07758c5713454d910523199 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 23 Apr 2017 11:36:52 -0700 Subject: [PATCH 045/165] chore(error-handling): Show meaningful error message when Google Maps Libraries are not loaded on th --- README.md | 1 + src/PlacesAutocomplete.js | 8 ++++++++ src/tests/testHelper.js | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f61c853..597c344e 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ npm run demo ### Getting Started + To use this component, you are going to need to load [Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript/) Load the library in your project diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 16f7823c..7e9ff5f2 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -20,6 +20,14 @@ class PlacesAutocomplete extends Component { } componentDidMount() { + if (!window.google) { + throw new Error('Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library') + } + + if (!window.google.maps.places) { + throw new Error('Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library') + } + this.autocompleteService = new google.maps.places.AutocompleteService() this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK } diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js index ba1ed826..5b14d5a6 100644 --- a/src/tests/testHelper.js +++ b/src/tests/testHelper.js @@ -7,7 +7,7 @@ global.document = jsdom.jsdom('') global.window = global.document.defaultView /*** Mock Google Maps JavaScript API ***/ -global.google = { +const google = { maps: { places: { AutocompleteService: () => {}, @@ -17,6 +17,8 @@ global.google = { } } } +global.google = google +global.window.google = google chai.use(chaiEnzyme()) From 6caf269275160f0358d0ac8bd331149a8d0b8e03 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 23 Apr 2017 11:44:03 -0700 Subject: [PATCH 046/165] docs(installation): Add yarn installation instruction to README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 597c344e..2c340f89 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ A React component to build a customized UI for Google Maps Places Autocomplete ( ### Installation To install the stable version +```sh +yarn add react-places-autocomplete +``` + +or + ```sh npm install react-places-autocomplete --save ``` From bbcfa655b29ec4e9e0e1c2de17158c5f9dd6b242 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 30 Apr 2017 14:25:10 -0700 Subject: [PATCH 047/165] docs(contributing): Add CONTRIBUTING.md --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..977f0374 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,16 @@ +## Development +* Fork this repo +* `npm run demo` will run the local dev server with the demo app on port 8080. +* `npm test` will run the tests. + +## Git commits +This project is using `commitizen` for Git commits. +After adding all of your changes to the staging area, please run `npm run commit` to write the commit message. + +Before creating a PR, please squash your commits for clean git commit history :octocat:. + +## Documentation +Please update the README file with any API changes, the code and docs should always be in sync. + +## Community +If you have any questions, please feel free to ask in our [Gitter channel](https://gitter.im/react-places-autocomplete/Lobby)! From 1c7f0e8612db46e4e219002f5771a9eaba83946d Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 13 May 2017 13:57:20 -0700 Subject: [PATCH 048/165] feat(utilities): Add Promise support to geocoding functions --- README.md | 88 +++++++++++++++++++++++++++++++--------------------- demo/Demo.js | 41 +++++++++++++++++------- src/index.js | 3 +- src/utils.js | 82 ++++++++++++++++++++++++++++++++++++------------ 4 files changed, 145 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 2c340f89..63c8b48e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A React component to build a customized UI for Google Maps Places Autocomplete ( ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) -2. [Utility function](#geocode) to get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) +2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) 3. Pass through arbitrary props to the input element to integrate well with other libraries (e.g. Redux-Form) ### Installation @@ -364,11 +364,22 @@ const options = { /> ``` - + +## Utility Functions +* [`geocodeByAddress`](#geocode-by-address) +* [`geocodeByPlaceId`](#geocode-by-place-id) +* [`getLatLng`](#get-lat-lng) + + ### `geocodeByAddress` API ```js -geocodeByAddress(address, callback) +/** + * Returns a promise + * @param {String} address + * @return {Promise} +*/ +geocodeByAddress(address) ``` #### address @@ -377,33 +388,25 @@ Required: `true` String that gets passed to Google Maps [Geocoder](https://developers.google.com/maps/documentation/javascript/geocoding) -#### callback -Type: `Function`, -Required: `true` - -Three arguments will be passed to the callback. - -First argument is an error object, set to `null` when there's no error. - -Second argument is an object with `lat` and `lng` keys - -Third argument (optional) is entire payload from Google API - ```js import { geocodeByAddress } from 'react-places-autocomplete' -geocodeByAddress('Los Angeles, CA', (error, { lat, lng }, results) => { - if (error) { return } - - console.log('Geocoding success!', { lat, lng }) - console.log('Entire payload from Google API', results) -}) +// `results` is an entire payload from Google API. +geocodeByAddress('Los Angeles, CA') + .then(results => console.log(results)) + .catch(error => console.error(error)) ``` + ### `geocodeByPlaceId` API ```js -geocodeByPlaceId(placeId, callback) +/** + * Returns a promise + * @param {String} placeId + * @return {Promise} +*/ +geocodeByPlaceId(placeId) ``` #### placeId @@ -412,28 +415,41 @@ Required: `true` String that gets passed to Google Maps [Geocoder](https://developers.google.com/maps/documentation/javascript/geocoding) -#### callback -Type: `Function`, -Required: `true` -Three arguments will be passed to the callback. +```js +import { geocodeByPlaceId } from 'react-places-autocomplete' + +// `results` is an entire payload from Google API. +geocodeByPlaceId('ChIJE9on3F3HwoAR9AhGJW_fL-I') + .then(results => console.log(results)) + .catch(error => console.error(error)) +``` + +### `getLatLng` API -First argument is an error object, set to `null` when there's no error. +```js +/** + * Returns a promise + * @param {Object} result + * @return {Promise} +*/ +getLatLng(result) +``` -Second argument is an object with `lat` and `lng` keys +#### result +Type: `Object` +Required: `true` -Third argument (optional) is entire payload from Google API +One of the element from `results` (returned from Google Maps Geocoder) ```js -import { geocodeByPlaceId } from 'react-places-autocomplete' +import { geocodeByAddress, getLatLng } from 'react-places-autocomplete' -geocodeByPlaceId('ChIJE9on3F3HwoAR9AhGJW_fL-I', (error, { lat, lng }, results) => { - if (error) { return } - - console.log('Geocoding success!', { lat, lng }) - console.log('Entire payload from Google API', results) -}) +geocodeByAddress('Tokyo, Japan') + .then(results => getLatLng(results[0])) + .then(({ lat, lng }) => console.log('Successfully got latitude and longitude', { lat, lng })) ``` + ### Discussion Join us on [Gitter](https://gitter.im/react-places-autocomplete/Lobby) if you are interested in contributing! diff --git a/demo/Demo.js b/demo/Demo.js index a15127c8..1fa0c275 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -1,5 +1,5 @@ import React from 'react' -import PlacesAutocomplete, { geocodeByAddress } from '../src' +import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../src' class Demo extends React.Component { constructor(props) { @@ -21,20 +21,38 @@ class Demo extends React.Component { loading: true }) - geocodeByAddress(address, (err, { lat, lng }) => { - if (err) { - console.log('Oh no!', err) + geocodeByAddress(address) + .then((results) => getLatLng(results[0])) + .then(({ lat, lng }) => { + console.log('Success Yay', { lat, lng }) this.setState({ - geocodeResults: this.renderGeocodeFailure(err), + geocodeResults: this.renderGeocodeSuccess(lat, lng), loading: false }) - } - console.log(`Yay! got latitude and longitude for ${address}`, { lat, lng }) - this.setState({ - geocodeResults: this.renderGeocodeSuccess(lat, lng), - loading: false }) - }) + .catch((error) => { + console.log('Oh no!', error) + this.setState({ + geocodeResults: this.renderGeocodeFailure(error), + loading: false + }) + }) + + /* NOTE: Using callback (Deprecated version) */ + // geocodeByAddress(address, (err, { lat, lng }) => { + // if (err) { + // console.log('Oh no!', err) + // this.setState({ + // geocodeResults: this.renderGeocodeFailure(err), + // loading: false + // }) + // } + // console.log(`Yay! got latitude and longitude for ${address}`, { lat, lng }) + // this.setState({ + // geocodeResults: this.renderGeocodeSuccess(lat, lng), + // loading: false + // }) + // }) } handleChange(address) { @@ -42,7 +60,6 @@ class Demo extends React.Component { address, geocodeResults: null }) - } renderGeocodeFailure(err) { diff --git a/src/index.js b/src/index.js index 3ae6caa1..24de300c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,10 @@ import PlacesAutocomplete from './PlacesAutocomplete' -import { geocodeByAddress, geocodeByPlaceId } from './utils' +import { geocodeByAddress, geocodeByPlaceId, getLatLng } from './utils' export { geocodeByAddress, geocodeByPlaceId, + getLatLng, } export default PlacesAutocomplete diff --git a/src/utils.js b/src/utils.js index 5527c709..850d1842 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,18 +2,46 @@ export const geocodeByAddress = (address, callback) => { const geocoder = new google.maps.Geocoder() const OK = google.maps.GeocoderStatus.OK - geocoder.geocode({ address }, (results, status) => { - if (status !== OK) { - callback({ status }, null, results) - return - } + return new Promise((resolve, reject) => { + geocoder.geocode({ address }, (results, status) => { + if (status !== OK) { - const latLng = { - lat: results[0].geometry.location.lat(), - lng: results[0].geometry.location.lng(), - } + // TODO: Remove callback support in the next major version. + if (callback) { + console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"') + callback({ status }, null, results) + return + } + + reject(status) + } + + // TODO: Remove callback support in the next major version. + if (callback) { + const latLng = { + lat: results[0].geometry.location.lat(), + lng: results[0].geometry.location.lng(), + } + console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"') + callback(null, latLng, results) + } + + resolve(results) + }) + }) +} - callback(null, latLng, results) +export const getLatLng = (result) => { + return new Promise((resolve, reject) =>{ + try { + const latLng = { + lat: result.geometry.location.lat(), + lng: result.geometry.location.lng(), + } + resolve(latLng) + } catch (e) { + reject(e) + } }) } @@ -21,17 +49,31 @@ export const geocodeByPlaceId = (placeId, callback) => { const geocoder = new google.maps.Geocoder() const OK = google.maps.GeocoderStatus.OK - geocoder.geocode({ placeId }, (results, status) => { - if (status !== OK) { - callback({ status }, null, null) - return - } + return new Promise((resolve, reject) => { + geocoder.geocode({ placeId }, (results, status) => { + if (status !== OK) { - const latLng = { - lat: results[0].geometry.location.lat(), - lng: results[0].geometry.location.lng(), - } + // TODO: Remove callback support in the next major version. + if (callback) { + console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') + callback({ status }, null, results) + return + } + + reject(status) + } + + // TODO: Remove callback support in the next major version. + if (callback) { + const latLng = { + lat: results[0].geometry.location.lat(), + lng: results[0].geometry.location.lng(), + } + console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') + callback(null, latLng, results) + } - callback(null, latLng, results) + resolve(results) + }) }) } From 658701e8334351492314d82b7cdf639c64eb6999 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 13 May 2017 14:14:43 -0700 Subject: [PATCH 049/165] docs(readme): Update readme --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 63c8b48e..4c5b747d 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Declare your PlacesAutocomplete component using React component ```js import React from 'react' -import PlacesAutocomplete, { geocodeByAddress } from 'react-places-autocomplete' +import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete' class SimpleForm extends React.Component { constructor(props) { @@ -73,11 +73,10 @@ class SimpleForm extends React.Component { handleFormSubmit = (event) => { event.preventDefault() - geocodeByAddress(this.state.address, (err, latLng) => { - if (err) { console.log('Oh no!', err) } - - console.log(`Yay! Got latitude and longitude for ${address}`, latLng) - }) + geocodeByAddress(this.state.address) + .then(results => getLatLng(results[0])) + .then(latLng => console.log('Success', latLng)) + .catch(error => console.error('Error', error)) } render() { From d14dd4c6ed9d12b2d9c8091754c16749998eb61c Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 18 May 2017 22:45:35 -0700 Subject: [PATCH 050/165] feat(props): Add debounce prop to allow user to set the number of millisecond to delay API calls Debounce calls to Google Maps API. Allow user to set the number of millisconde through `debounce` prop. Closes #79 --- README.md | 9 +++++++++ package.json | 1 + src/PlacesAutocomplete.js | 11 ++++++++++- src/tests/index.spec.js | 7 +++++-- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4c5b747d..8bc7b773 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ export default SimpleForm * [`onSelect`](#onSelect) * [`onEnterKeyDown`](#onEnterKeyDown) * [`options`](#options) +* [`debounce`](#debounce) #### inputProps @@ -363,6 +364,14 @@ const options = { /> ``` + +#### debounce +Type: `Number` +Required: `false` +Default: `200` + +The number of milliseconds to delay before making a call to Google API. + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/package.json b/package.json index 395318d6..ab9674dc 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ ] }, "dependencies": { + "lodash.debounce": "^4.0.8", "prop-types": "^15.5.8", "react": "^15.3.0" } diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 7e9ff5f2..becdb3fd 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -6,6 +6,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import debounce from 'lodash.debounce' import defaultStyles from './defaultStyles' class PlacesAutocomplete extends Component { @@ -17,6 +18,7 @@ class PlacesAutocomplete extends Component { this.autocompleteCallback = this.autocompleteCallback.bind(this) this.handleInputKeyDown = this.handleInputKeyDown.bind(this) this.handleInputChange = this.handleInputChange.bind(this) + this.debouncedFetchPredictions = debounce(this.fetchPredictions, this.props.debounce) } componentDidMount() { @@ -56,6 +58,11 @@ class PlacesAutocomplete extends Component { }) } + fetchPredictions() { + const { value } = this.props.inputProps; + this.autocompleteService.getPlacePredictions({ ...this.props.options, input: value || '' }, this.autocompleteCallback) + } + clearAutocomplete() { this.setState({ autocompleteItems: [] }) } @@ -176,7 +183,7 @@ class PlacesAutocomplete extends Component { this.clearAutocomplete() return } - this.autocompleteService.getPlacePredictions({ ...this.props.options, input: event.target.value }, this.autocompleteCallback) + this.debouncedFetchPredictions() } handleInputOnBlur(event) { @@ -311,6 +318,7 @@ PlacesAutocomplete.propTypes = { ]), types: PropTypes.array }), + debounce: PropTypes.number, } PlacesAutocomplete.defaultProps = { @@ -320,6 +328,7 @@ PlacesAutocomplete.defaultProps = { autocompleteItem: ({ suggestion }) => (
{suggestion}
), styles: {}, options: {}, + debounce: 200, } export default PlacesAutocomplete diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index f863561f..75a1cb8c 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -208,13 +208,16 @@ describe('custom inline styles', () => { ...testInputProps, value: 'Boston, MA', } - it('calls getPlacePredictions with the correct options', () => { + it('calls getPlacePredictions with the correct options', (done) => { global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') const options = { radius: 2000, types: ['address'] } const wrapper = mount() wrapper.find('input').simulate('change', { target: { value: 'Los Angeles, CA' } }) - expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be.true + setTimeout(() => { + done() + expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be.true + }, 0) }) }) From 226659708c267a56bc3ae50b8fcc04267cb1c9dc Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 19 May 2017 10:35:16 -0700 Subject: [PATCH 051/165] fix(EnterKeyHandler): Fix bug related to onEnterKeyDown Closes #74 --- src/PlacesAutocomplete.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index becdb3fd..b6354552 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -87,10 +87,6 @@ class PlacesAutocomplete extends Component { } handleEnterKey() { - if (this.state.autocompleteItems.length === 0) { - return - } - const activeItem = this.getActiveItem() if (activeItem === undefined) { this.handleEnterKeyWithoutActiveItem() From 7763aef2931485c504def0c0628ed688def469de Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 19 May 2017 10:35:45 -0700 Subject: [PATCH 052/165] docs(readme): Update readme --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8bc7b773..b9a3d70b 100644 --- a/README.md +++ b/README.md @@ -325,11 +325,10 @@ The function takes one argument, the value in the input field. ```js const handleEnter = (address) => { - geocodeByAddress(address, (err, { lat, lng }, results) => { - if (err) { console.error('Error'); return; } - - console.log("Geocode success", { lat, lng }) - }) + geocodeByAddress(address) + .then(results => { + console.log('results', results) + }) } // Pass this function via onEnterKeyDown prop. From 56c5d1b7d151288691104d8f47ab09b121f300b6 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 27 May 2017 16:39:39 -0700 Subject: [PATCH 053/165] feat(prop): Add highlightFirstSuggestion prop Allow user to highlight the first suggestion in the dropdown Closes #23 --- README.md | 9 +++++++++ src/PlacesAutocomplete.js | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b9a3d70b..73aa589e 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ export default SimpleForm * [`onEnterKeyDown`](#onEnterKeyDown) * [`options`](#options) * [`debounce`](#debounce) +* [`highlightFirstSuggestion`](#highlightFirstSuggestion) #### inputProps @@ -371,6 +372,14 @@ Default: `200` The number of milliseconds to delay before making a call to Google API. + +#### highlightFirstSuggestion +Type: `Boolean` +Required: `false` +Default: `false` + +If set to `true`, first suggestion in the dropdown will be automatically highlighted. + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index b6354552..296fa399 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -47,11 +47,13 @@ class PlacesAutocomplete extends Component { secondaryText: structured_formatting.secondary_text, }) + const { highlightFirstSuggestion } = this.props + this.setState({ autocompleteItems: predictions.map((p, idx) => ({ suggestion: p.description, placeId: p.place_id, - active: false, + active: (highlightFirstSuggestion && idx === 0 ? true : false), index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), })) @@ -315,6 +317,7 @@ PlacesAutocomplete.propTypes = { types: PropTypes.array }), debounce: PropTypes.number, + highlightFirstSuggestion: PropTypes.bool, } PlacesAutocomplete.defaultProps = { @@ -325,6 +328,7 @@ PlacesAutocomplete.defaultProps = { styles: {}, options: {}, debounce: 200, + highlightFirstSuggestion: false, } export default PlacesAutocomplete From 8a68168a37e15ec8df8ef83724344e1809940acc Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 7 Jun 2017 22:52:33 -0700 Subject: [PATCH 054/165] fix(google-api): Fix error thrown by Google API when sending request with empty input value Closes #88 --- src/PlacesAutocomplete.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 296fa399..a68c4e41 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -61,8 +61,13 @@ class PlacesAutocomplete extends Component { } fetchPredictions() { - const { value } = this.props.inputProps; - this.autocompleteService.getPlacePredictions({ ...this.props.options, input: value || '' }, this.autocompleteCallback) + const { value } = this.props.inputProps + if (value.length) { + this.autocompleteService.getPlacePredictions({ + ...this.props.options, + input: value + }, this.autocompleteCallback) + } } clearAutocomplete() { From 0e8f89f89a6c7c63f1d4d663c4b928e56643a935 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 20 Jul 2017 22:12:54 -0700 Subject: [PATCH 055/165] chore(typo): Fix typo --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index 850d1842..cc5d2b9a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -69,7 +69,7 @@ export const geocodeByPlaceId = (placeId, callback) => { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), } - console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') + console.warn('Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') callback(null, latLng, results) } From e53cf33f2e388ca79299858b2676d52c0550197e Mon Sep 17 00:00:00 2001 From: jmlag Date: Mon, 31 Jul 2017 03:31:12 -0500 Subject: [PATCH 056/165] feat(autocomplete dropdown): add toggleable "powered by Google" to autocomplete dropdown add toggleable "powered by Google" to dropdown, add tests for Google logo, update readme closes #75 --- README.md | 9 +++++++++ src/PlacesAutocomplete.js | 4 ++++ src/tests/index.spec.js | 16 +++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73aa589e..9e9ad205 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ export default SimpleForm * [`options`](#options) * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) +* [`googleLogo`](#googleLogo) #### inputProps @@ -380,6 +381,14 @@ Default: `false` If set to `true`, first suggestion in the dropdown will be automatically highlighted. + +#### googleLogo +Type: `Boolean` +Required: `false` +Default: `true` + +Allows you to toggle the "powered by Google" logo. For more information on Google's logo requirements, refer to this link: [https://developers.google.com/places/web-service/policies](https://developers.google.com/places/web-service/policies) + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index a68c4e41..8ab84e61 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -270,6 +270,9 @@ class PlacesAutocomplete extends Component { {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
))} + { this.props.googleLogo ? () : '' }
)}
@@ -334,6 +337,7 @@ PlacesAutocomplete.defaultProps = { options: {}, debounce: 200, highlightFirstSuggestion: false, + googleLogo: true, } export default PlacesAutocomplete diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 75a1cb8c..95419eba 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -57,7 +57,7 @@ describe('autocomplete dropdown', () => { const autocompleteItem = ({ suggestion }) => (
{suggestion}
) beforeEach(() => { wrapper = shallow() - }) + }) it('initially does not have an autocomplete dropdown', () => { expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) @@ -87,6 +87,20 @@ describe('autocomplete dropdown', () => { wrapper.setState({ autocompleteItems: data }) expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) expect(wrapper.find('.autocomplete-item')).to.have.length(3) + + describe('the Google logo', () => { + it('is displayed by default', () => { + wrapper = shallow() + wrapper.setState({ autocompleteItems: data }) + expect(wrapper.find('#google-logo')).to.have.length(1) + }) + + it('is not displayed when toggled off', () => { + wrapper = shallow() + wrapper.setState({ autocompleteItems: data }) + expect(wrapper.find('#google-logo')).to.have.length(0) + }) + }) }) it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { From 6ec49fcb4627353ad4ee5a233f1f1e404eb6e1e7 Mon Sep 17 00:00:00 2001 From: jmlag Date: Tue, 1 Aug 2017 16:02:31 -0500 Subject: [PATCH 057/165] Update PlacesAutocomplete.js add typecheck for googleLogo prop --- src/PlacesAutocomplete.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 8ab84e61..9ba46490 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -326,6 +326,7 @@ PlacesAutocomplete.propTypes = { }), debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, + googleLogo: PropTypes.bool, } PlacesAutocomplete.defaultProps = { From 502eda28bfa55f3c16cb9e666277ad25f097c2ad Mon Sep 17 00:00:00 2001 From: Alexandre Kilian Date: Wed, 2 Aug 2017 14:35:09 +0200 Subject: [PATCH 058/165] fix(eventhandler): fixed touch handling added touch-events in addition to mouse events to add support for mobile devices 93 --- src/PlacesAutocomplete.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index a68c4e41..af196cc1 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -265,6 +265,8 @@ class PlacesAutocomplete extends Component { key={p.placeId} onMouseOver={() => this.setActiveItemAtIndex(p.index)} onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + onTouchStart={() => this.setActiveItemAtIndex(p.index)} + onTouchEnd={() => this.selectAddress(p.suggestion, p.placeId)} style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} From 3f376b005257ab07c055d8ac641aa49490393635 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 5 Aug 2017 10:06:53 -0700 Subject: [PATCH 059/165] docs(readme): Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73aa589e..eccb6264 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ export default SimpleForm ### Props for `PlacesAutocomplete` -#### Require Props: +#### Required Props: * [`inputProps`](#inputProps) From d799cf18fadd79db8d47103b6a7eb233571d4a70 Mon Sep 17 00:00:00 2001 From: Alexandre Kilian Date: Wed, 2 Aug 2017 14:35:09 +0200 Subject: [PATCH 060/165] fix(eventhandler): fixed touch handling added touch-events in addition to mouse events to add support for mobile devices 93 --- src/PlacesAutocomplete.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 9ba46490..25c0375d 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -265,6 +265,8 @@ class PlacesAutocomplete extends Component { key={p.placeId} onMouseOver={() => this.setActiveItemAtIndex(p.index)} onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + onTouchStart={() => this.setActiveItemAtIndex(p.index)} + onTouchEnd={() => this.selectAddress(p.suggestion, p.placeId)} style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} From 9c60821aa9ec284d5c6d77bdbb1cd3dea17e4c70 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 5 Aug 2017 10:06:53 -0700 Subject: [PATCH 061/165] docs(readme): Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e9ad205..2c4c142e 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ export default SimpleForm ### Props for `PlacesAutocomplete` -#### Require Props: +#### Required Props: * [`inputProps`](#inputProps) From 17e04f839121ab14b6316c355cd40a0e7647b9a7 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 5 Aug 2017 11:00:54 -0700 Subject: [PATCH 062/165] chore(webpack): Add support for image files 1. Added webpack loaders for images files 2. Add tests/setup.js for setting up for test runs (ignore some webpack features mocha doesn't understand) --- demo/webpack.config.js | 9 ++++++- package.json | 4 ++- src/PlacesAutocomplete.js | 7 ++--- src/images/powered_by_google_on_non_white.png | Bin 0 -> 3126 bytes src/images/powered_by_google_on_white.png | Bin 0 -> 4550 bytes src/tests/setup.js | 24 ++++++++++++++++++ webpack.config.babel.js | 14 +++++++++- 7 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 src/images/powered_by_google_on_non_white.png create mode 100644 src/images/powered_by_google_on_white.png create mode 100644 src/tests/setup.js diff --git a/demo/webpack.config.js b/demo/webpack.config.js index c26a27d5..88ee37f0 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -20,7 +20,14 @@ module.exports = { presets:['es2015', 'react'] } }, - {test: /\.json$/, loader: 'json'} + {test: /\.json$/, loader: 'json'}, + { + test: /\.(jpe?g|png|gif|svg)$/i, + loaders: [ + 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', + 'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false' + ] + } ] }, plugins: process.argv.indexOf('-p') !== -1 ? [ diff --git a/package.json b/package.json index ab9674dc..b9f262d3 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "commit": "git-cz", "watch:test": "npm t -- -w", - "test": "mocha src/tests/index.spec.js --compilers js:babel-register", + "test": "mocha src/tests/setup.js src/tests/index.spec.js", "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:*", "build:main": "babel --copy-files --out-dir dist --ignore *.spec.js src", @@ -67,8 +67,10 @@ "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", "enzyme": "2.4.1", + "file-loader": "0.11.2", "gh-pages": "^0.12.0", "ghooks": "1.3.2", + "image-webpack-loader": "3.3.1", "jsdom": "9.4.1", "json-loader": "0.5.4", "mocha": "2.5.3", diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 25c0375d..3c00fa40 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -8,6 +8,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import debounce from 'lodash.debounce' import defaultStyles from './defaultStyles' +import googleLogoDefault from './images/powered_by_google_on_white.png' class PlacesAutocomplete extends Component { constructor(props) { @@ -272,9 +273,9 @@ class PlacesAutocomplete extends Component { {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
))} - { this.props.googleLogo ? () : '' } + {this.props.googleLogo && ()}
)}
diff --git a/src/images/powered_by_google_on_non_white.png b/src/images/powered_by_google_on_non_white.png new file mode 100644 index 0000000000000000000000000000000000000000..0245b1f25bbfbb17768b04bd7beff8af0e73b26f GIT binary patch literal 3126 zcmV-649W9}P)U-nsmlaiAc=hJJ(V0Gf-RbTr zL}W!}-i(ZhtpAI!^S~)W`jQv=4DdZcQ>17 zqgaGjBv6eA6cI>jV!6_1jT{tW*FHQe;f;tu5rJ^8(x-s?q^TMaC?XIW+tCllrLP?k zC?e41V&PYbMFffnls532SQx(zQB*E_;Tk-GhjluFww$2{qe8}JZrWN*nTJFg}+ z%l=hOP9WCd7~E#G1~4y~xtZKcI{R**1PhDdCye`rC&jPf8gEU+$c=TL-5gJ%SX=xDZ_55byI2J`V!e@g!@1WQ&!WUmkL6YF6(l-t zvO5c#a2u=3kW>g1Cmr5(-f}ue+MUG%&HFs1;(j~N30SbNwy`(?xtd9bkbfCYyLIt{ zBmkb!$(ycRReT(f`3w2s1kw?jD*@mk7lq_%qcRxtd_ps&xtry9D$q?^Q=Q0LKgV0&0}G862Y7}hhB^99KJaMO|1tP1xmZHLw)RrvEP#R{{ER91&pCh8h@>p1)_>%p z%~Z@6MKS`h8fJ?EOYjM1h=P~<2!wTJYws1F${+((Fl-CZOs5W!N5y*$JkDoo|2oW#rUlPdJL?a}~LK>URF@SU~D@hB^| z!EbUgC-Dj;DqYX1i^b+z37+IBJRL8`I~D6wAkaT36v0Z|#>u=uz7zvIquqJ74oiS0 z_+C#F5$LD12y~cQbE`erJVSEzt?qWD`Wc}V<m>VVO9a9lslK9$0pLlG>N4pm#5Q*?B$LT@li4Y zNllb!6{~%D2-^s`iHu4{OLp?lhBu2aJD%6Ek!O`aG>ps1gjou(5(E<=bzBdHs0YFLw z`cMUF7D8polpd zB$k2asUJE{TbyZ1`Wdd7+u8rkjA`)&mt7C~ta?Y{ILN1WycIT@<8#gNO@UeeYAOU` zZ-3^3rRI7IomLdVEGMwODA`7+{3;esOd;hrfiP%!KRhc2Ji;gDcy^wYmfXD}zW!F= zn{Wc*E}Mi>iQVxYC^k0ZZrR-%td0$SgkWCjv9e|-1iM~IvqA*4NFz6!cDfov&N9cX zq_xfu!*+B0h#J07Gq1nh|1`Rp>ev;i;bLW|p85&AC~Ge+ntNlQE&&tT8S(dYMb$>Vz<1_OQ!BhO^7kmOH7CO#B3LUK_F}+ps#z?d zz;c&eLwrv}6219G;xj2ju!h59QXtTZFdFc5J?m^*dCeSm)u1{AY-HC@cxsr8$CC-} z+Cc<*C#)ichm#Y?oAk@mJXF1}pFli5V8UKjv|%p_JT=rwH&lPLOau!g#zvqBFVk|q z(i0!JlX?@5=F9j*|2WiLUhqEA#2gz#^h^w-fnn>w`*cr%Kx>27)sB-Kulu{nK^i+n ziM_&!fxDa>>CkW~wzJC_+|Nk^40u#P_CjY_Oh@hkmFpO=@T(*Q(i}`P^7E8_Asuv9 zz=WZiGwG2(8gbI{5<4HlJrc+6mannaNbX^D?`IzV62Y^c;R36LcWVfN=9}TG60V0w zgRzVg8zm)Bh?9R!J*R?Wtt^m@P%45?lGc)IV5wcqR39Gz+hdW+yyxhh=*wUglA*b) z(l%8&jtr4&j?!=faj1EpSRh>0N&*|`7cIWpGzXdMA35iptk4;s zi{MYEotegjURvYvy3X;w7OSy(astWIny2|USR6f$Nt6^w3_qt7M4u6ePKx5$X!#<+ z9IO_>3b|T|niM?TE=&TrO=|i#TjWIK>-|EuakT27#8cf;;2M?vLt^R3Nmbdba$P-X z{0GU>cvitCJ@4xEZkW%G{uoF&$s^QPxo5a$JqY(H$vovcj&SjQjR>Xyy7n62dM*12 zikaujw^n#lT-<{qJjkZu1k%FYQr7e6J%~cw&&C!BWpjd;o}5}82LVP8OJk8NOgzb3%2jDg=an<1ac&xdhyzs{=8c{te3ieD_&WW=A z=Gj_EY=aNO3yHpZQZXk>wiYh#v#5wWCFT%FU*RInr!sk}7SK+%t0Ee{>p3_d>%|nU$wpZbqDQ${&!CFZMvxVZ{UB{2Et%oU?1v=;VZ-rbY zz7PdU@Q1U*m7G9X_^O=z_#J-&fz1qE!oJu1{u6wJ^{Vo+!~!$;KYWk(F-OlUEZ6$!_$+$&*f|Ft9l9+Zr9!4vle_G}Bdxc^7hwc4TIXV&r}ZgvTrk@iWR|7pumGDd3y=6~y&9^Xg-@_p zHe)_sVsGF2uQW5I`L>>GZOt`b;H&X`S3HZkvKedfEiaY2?(mamm;Gy}r+&TecwY6s z;U$R@Odf$}umJg3gcsO3PS>~<(jjz!$M9@UHec6F#-~_=P52!*nB_D8JSPH5>#g`a ztTWHT?RW@x@e&STgDq-g@mOAp`*9D?=7AF1RykJTK-`2!ag+5y8D_ilKOTaIm6qpS^(`>d7V->gRa%cN&2r@G`BMRVZ+xDDVgmmAY)l zQ?T6o<>F2tPz2_gV(EJ3Rk--)X-NnyW}Tfzpa?w4bovby&vMDc{SpA?Xr8-s2o!-$ zWOvz}RVt|U$KX>y6j;Pdr1G{ivx8h*_HXz99|VXXwb+q;P}8GqNxvuqKVTmoU|2Kf8K~EKNpTB4M0~0kL%(jJUon8 z+pUOlKFQ|d7VP&~-XD+$0D%v#SX=Rd<>x!_e{jY9fC>#Su4z0xBGF`ZD4sgv)_4@H z)zQREKpqJSd}!6Wz=u|*JE-{3ss{iS8eUwpczED$z1)Z<&R*QbN*%`QtFeA@r0&Fs z>c+NPs_Kppi`1p&A>wHa#S;I~`-J1E9e~0fo&n{D2Q(2hW|&Lv^_qfyRpl*_ z%7x95U~RJzd~-`A@J76DZw?2hr)#JPkSo4M<>$UqyztzC(%N$ei{FgbH=aFMvidV`^8u7Me81;*X;>kB6w^N7cW|9BR=~6(`8(VvFE)9U@9)L2qHlTk;g8gyc zn_D8mm-2OJF@kkXMsWE*r%vq($O_99P!YHh3<3jykKC&q+yn-L8$l6WeJTMrgTdey zP)hl!2=oR$fG@}6-JEA5FA~@FCUspq%Ye$k?O+h-b0w!(z<@4fcfU^b2XwheuO3s@ z90}}f4*QRw!KKY;3j6=qVpOh96Zrty@)0UKd!S_JnS-TA&K)dGn^XM9^M}e-BRKH^ zvSal}(#5Eadd{jgDilrr#fT?nA#(h=$f125P==fh=wv+#B6UB*Jm|3NL|laOX52SOW`0d!I1dtgV$)E=6E6#a&f10fIlxldzWUkF(yW30* za=*iOthX@2*q)GzS! zpY^(Y4XAbc^q#mDzt`uA>+la;j{~?Czt-!(9zYUaNCSGYXnY&N3@{z61$AP(ZJ^xb zmuWp{6g&b#Ue{9N>HuAdmt;36|0(2up5$B* zAci9(y!R^I_+U&+0ZCvcFOkLqvpI#X*pr+K0+e9@azU@U$b=4*Ed?au!piJxlQ#w z?Eo&M+F=satx;W{zCi0{unRO6!hi%DK^f4Rpp12l>MHIRzYFDL zu8m^<34q*o!NT#xKLI)8-hjf<6Vm}P|D88!Anxp^|F1CxFEmvLBY@0kt`6={QPMAE z<81!|4Me1KT0}h;5Di5DnE_+kp`xH)%6t$foHNr;GKP|955-ao0comg(j{y{`5Mr% zs)>DII46aG!>9v2MI(~tG}$5SzF%x> z$VMdIzZ+;hF7B3(3lq}~cA@y3!7|Sz-oMWwS-i^Re6#^Y9TKvW#kQLqj<-Q|g*((2 zG>9CU-SKV#4Fxoyr}VW|nkKe=0!S?u>t+D09>TzOf#N)q&>(puAUimk;b_1PHM#~8 zV*oM8lO9m>z%_UXbd~J87{= zlyal$(m0Kn-D;8V@rj5bszzb@h<#q9qK4r>>Uq!z_JSgdJMIv&*PUY9^%e%Soa}YC z*!EVk*KmudZkCGJoV2lk1~fW{(YT#rdl{Ma6K1%@v>N`00RfI^-XqNf|DFcOmO~|5xhX_vhi9KZ|p3zj#zIc$~YYt#kaN0Cn)fLMKn18;b7V z2VDNr`$RsdK^e__@mV7*@(TS_K4^v5PQNd;T_t_vHq=Q|l?LSEdhKz0JRMD_yxJgg zR-ixzRG(vsz)Bst3Ed^u4ORdD+eH_x8@Uh~%r4b^_>~^9atl8pksnefX2$;(PzNoB z|DbG87y;@H$PSE_&CgCo2cm!&bh!>nGf5wy-hk{tw`;!K2SfoeFwakACD3aU0|429 zecqgx0fmDfQqf>7UjGEr8cy1y9O3@|&7RO5kcN2SA}Y|MRri?O%_=E3Jtp?)E#ALf zyuU=e|ENjC^t4Ex7pZQ6HZT(1N4M;f2IL}d(U9lywt)^kB;M~s&Kg=E1KORdABf{k z2U0^+7qmko)J@ElX2nuBUo;ComUs+Mz953wt|qp=5>SS#-+*GtPrI#+LV@C&3SdAc z_)oQj1MlJ_v_lcn>mxIljH{VMWv(#QfC(2L1g`g%+;iFBV95mhgf5{VmuYq3G- zp=Kl2Rtd;0JTk0;c#=s}X#jtD*tr0xzTi%_L_{Fd1Q* z;36-ghsk3m`GFfar@LA<{Vl!_ttwKk2b0dyhva%(`_MB^)?{IpW#WSlgs zfH|P<A{UeT?atqnC_RmIw->W9zs$PSX!FU`zxB5TqmoV=FRz!{R^=<%U| zBz#xT9(oS8bJ7)%1-02z68t~Q8iqeW{V{rVQjBP|W0Y$iAahD<)iC_eCVR+8x;QWut^J4=7WJV?u{4;Vvvj9nWq3eKxWUVna^)dH~bxVbj zITh7S0$N4lm-ZRa{h9-`=9&}+#z3jV$kuMqgRHd#M8R^xFY;VIxRsEjfkuI5FZJAqfGgm%eJpAlm07wE;iK`0e zGd$AO{$=V8=>PLYx|u7Vd3_d#iWdNq=sXsiGZ!byLPR!KnDiGewGh#y&Z&*(eDORv zKmgZc+6_EUEX%Zw;47pN>l_eM4?>_s8NxI*QZrT8ps4k$O&Z)FReJxVNFG~8D-LD- zx0r0VDaQzIo5{#hnHq_Uf}VLAkgj>!0`AbqQ*}%GK@Xb(%oqr&>sA6nprI2A5qE$g z$}GBrb!tA_K(ba3lPMiDs6gUw7aC0qH>7;wN3*h-0kR-7`#t!5v!pBdIckM|XEp>4 zUI$3S70)oC?`w16is%<=eu{s`k&#}HeO?Dh!;uX}?7nufxg<^^=kqhH`(vS|Vx;~4 zQWPM5!{l6(7;^t9cR#sU(`h<}o{I69nmGCZxF6J*%>VJ_a0jjjkAZuY@i2QFlBy%r z_S^L_^^mSZR3#hFHj_D2cY}vO)Zw#~0XeFtiujl<7RPG<6D=abd(>y_1^0pb)x_b) z3S>b0lo@RW_kc&#jfM%3vsS6!tu9nRRlOv26aPK1ybK6+MdAI)v4EU7K4)sbrbytM zs!>^E1m3{;AV6lce~J2`(D0kmU>tY@=Ys&5!MQP06EZO+*=5UfGHP!`fnRgH24c8g zkBaFCXcSlu8ZBr5OB^1nF<#6mv*Iz(*C|o08rDKm(v{CD7vW?I4>)|sT5Se-8W5`& zc-ZN94#WB-Dj{vgDsX3k3}_eVqbJ)cq7G&+HA)X&bcT=@3WTGn_lBa$l(YFHzXR5} zts&ys?TC1u1x+?X(Z6mr0*e7T!L!>@X!tCmohD1;`AYGx&mAmV49E$Ngm8Y_z%h$+ z|1(cB;R&ju?&)iJ{8fz1wFo{3T5Yby&tcltfHcGllLj>itOMJ@KClI>0Jpk$4$w^S z0N4R)!8Wh~jCRrYA1|t&`;)c$i|r;;Zt{T2u=8RLb+gFxgCfd{YPhkF1^v$cjJC8`g#Eo2VyMJQZ4fMe_M>>RfqB zr+xfqhX7eI@73*H)Cl710bOo*(b)#%$VV?OHGnj;YmztM^{-;vv-}>Q%MC9& z(||mAGE|LOC&?4?TlbkH+TYAmRCsbKPdP#4^QiuVj+y)rT?w%0Gz0SFsZ Date: Sat, 5 Aug 2017 11:19:07 -0700 Subject: [PATCH 063/165] refactor(googleLogo): Allow user to customize styles for google logo Added support for classNames and styles for google logo --- README.md | 11 +++++++++-- src/PlacesAutocomplete.js | 16 ++++++++++++---- src/defaultStyles.js | 9 ++++++++- src/tests/index.spec.js | 6 +++--- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 2c4c142e..fbccde88 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ Type: `Object`, Required: `false` You can give a custom css classes to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`, `googleLogoContainer`, `googleLogoImage`. If you pass `classNames` props, none of the default inline styles nor inline styles from `styles` prop will be applied to the element, and you will have full control over styling via CSS. @@ -219,7 +219,7 @@ Type `Object`, Required: `false` You can provide custom inline styles to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`, `googleLogoContainer`, `googleLogoImage`. ```js const defaultStyles = { @@ -247,6 +247,13 @@ const defaultStyles = { }, autocompleteItemActive: { backgroundColor: '#fafafa' + }, + googleLogoContainer: { + textAlign: 'right', + padding: '1px', + }, + googleLogoImage: { + width: 150, } } ``` diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 3c00fa40..cac41071 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -8,7 +8,6 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import debounce from 'lodash.debounce' import defaultStyles from './defaultStyles' -import googleLogoDefault from './images/powered_by_google_on_white.png' class PlacesAutocomplete extends Component { constructor(props) { @@ -273,9 +272,18 @@ class PlacesAutocomplete extends Component { {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
))} - {this.props.googleLogo && ()} + {this.props.googleLogo && ( + ) + } )} diff --git a/src/defaultStyles.js b/src/defaultStyles.js index adefa472..417e17fb 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -23,7 +23,14 @@ const defaultStyles = { }, autocompleteItemActive: { backgroundColor: '#fafafa' - } + }, + googleLogoContainer: { + textAlign: 'right', + padding: '1px', + }, + googleLogoImage: { + width: 150, + }, } export default defaultStyles diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 95419eba..fbd8a274 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -57,7 +57,7 @@ describe('autocomplete dropdown', () => { const autocompleteItem = ({ suggestion }) => (
{suggestion}
) beforeEach(() => { wrapper = shallow() - }) + }) it('initially does not have an autocomplete dropdown', () => { expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) @@ -92,13 +92,13 @@ describe('autocomplete dropdown', () => { it('is displayed by default', () => { wrapper = shallow() wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#google-logo')).to.have.length(1) + expect(wrapper.find('#PlacesAutocomplete__google-logo')).to.have.length(1) }) it('is not displayed when toggled off', () => { wrapper = shallow() wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#google-logo')).to.have.length(0) + expect(wrapper.find('#PlacesAutocomplete__google-logo')).to.have.length(0) }) }) }) From d29ac071684e0864de0f174e04a11ba1cf068680 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 5 Aug 2017 11:38:04 -0700 Subject: [PATCH 064/165] refactor(googleLogo): Allow user to pick the right theme for Google logo image --- README.md | 13 ++++++++++++- src/PlacesAutocomplete.js | 4 +++- src/defaultStyles.js | 1 + ..._on_white.png => powered_by_google_default.png} | Bin ...non_white.png => powered_by_google_inverse.png} | Bin 5 files changed, 16 insertions(+), 2 deletions(-) rename src/images/{powered_by_google_on_white.png => powered_by_google_default.png} (100%) rename src/images/{powered_by_google_on_non_white.png => powered_by_google_inverse.png} (100%) diff --git a/README.md b/README.md index fbccde88..f8894648 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ export default SimpleForm * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) * [`googleLogo`](#googleLogo) +* [`googleLogoType`](#googleLogoType) #### inputProps @@ -251,9 +252,10 @@ const defaultStyles = { googleLogoContainer: { textAlign: 'right', padding: '1px', + backgroundColor: '#fafafa' }, googleLogoImage: { - width: 150, + width: 150 } } ``` @@ -396,6 +398,15 @@ Default: `true` Allows you to toggle the "powered by Google" logo. For more information on Google's logo requirements, refer to this link: [https://developers.google.com/places/web-service/policies](https://developers.google.com/places/web-service/policies) + +#### googleLogoType +Type: `String` ("default" or "inverse") +Required: `false` +Default: `"default"` + +Allows you to pick right color theme for "powered by Google" logo. +Please see Google's API page for more information: [https://developers.google.com/places/web-service/policies](https://developers.google.com/places/web-service/policies) + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index cac41071..4d8aebba 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -278,7 +278,7 @@ class PlacesAutocomplete extends Component { style={this.inlineStyleFor('googleLogoContainer')} className={this.classNameFor('googleLogoContainer')}> @@ -338,6 +338,7 @@ PlacesAutocomplete.propTypes = { debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, googleLogo: PropTypes.bool, + googleLogoType: PropTypes.oneOf(["default", "inverse"]), } PlacesAutocomplete.defaultProps = { @@ -350,6 +351,7 @@ PlacesAutocomplete.defaultProps = { debounce: 200, highlightFirstSuggestion: false, googleLogo: true, + googleLogoType: 'default', } export default PlacesAutocomplete diff --git a/src/defaultStyles.js b/src/defaultStyles.js index 417e17fb..6118adeb 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -27,6 +27,7 @@ const defaultStyles = { googleLogoContainer: { textAlign: 'right', padding: '1px', + backgroundColor: '#fafafa' }, googleLogoImage: { width: 150, diff --git a/src/images/powered_by_google_on_white.png b/src/images/powered_by_google_default.png similarity index 100% rename from src/images/powered_by_google_on_white.png rename to src/images/powered_by_google_default.png diff --git a/src/images/powered_by_google_on_non_white.png b/src/images/powered_by_google_inverse.png similarity index 100% rename from src/images/powered_by_google_on_non_white.png rename to src/images/powered_by_google_inverse.png From 32b244406bd569eade7ca03f3a714da0d9694b2c Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 5 Aug 2017 11:42:49 -0700 Subject: [PATCH 065/165] chore(webpack): Use default settings for image-webpack-loader --- demo/webpack.config.js | 2 +- webpack.config.babel.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 88ee37f0..96adf4d6 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -25,7 +25,7 @@ module.exports = { test: /\.(jpe?g|png|gif|svg)$/i, loaders: [ 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', - 'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false' + 'image-webpack-loader' ] } ] diff --git a/webpack.config.babel.js b/webpack.config.babel.js index b2c5cfe7..b81e0872 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -27,7 +27,7 @@ export default { test: /\.(jpe?g|png|gif|svg)$/i, loaders: [ 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', - 'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false' + 'image-webpack-loader' ], include } From 7de34b27fc27c4d0efced0dc7eaedab517be7a9b Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 7 Aug 2017 21:28:46 -0700 Subject: [PATCH 066/165] 5.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b9f262d3..3bb97b5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "0.0.0-semantically-released", + "version": "5.4.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 598d1f864cc559e731ed83d6f08309e283c07588 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 7 Aug 2017 22:59:10 -0700 Subject: [PATCH 067/165] chore(script): Fix postpublish npm script --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 3bb97b5e..862ac4f0 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,7 @@ "demo:test": "mocha demo/tests/index.spec.js --compilers js:babel-register", "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", "demo:deploy": "gh-pages -d demo/dist", - "deploy": "gh-pages -d demo:build", - "postpublish": "npm run deploy" + "postpublish": "npm run demo:deploy" }, "repository": { "type": "git", From 95d08e0bfc99d777844be71131b9c32d026ccece Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 8 Aug 2017 07:41:33 -0700 Subject: [PATCH 068/165] fix(input): Add default autocomplete='off' to input element --- src/PlacesAutocomplete.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 4d8aebba..183c9511 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -225,6 +225,7 @@ class PlacesAutocomplete extends Component { getInputProps() { const defaultInputProps = { type: "text", + autoComplete: "off", } return { From 47d8c6ee392b9aab936c5ca2e422a4ad8c0fc7bd Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 8 Aug 2017 07:56:06 -0700 Subject: [PATCH 069/165] 5.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 862ac4f0..9b5883d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "5.4.1", + "version": "5.4.2", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From bfbbe85016d002a8e32ce42761ce7928463f971e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 2 Sep 2017 17:35:35 -0700 Subject: [PATCH 070/165] chore(deps): Remove react from dependencies and move it to peerDependencies list Closes #113 --- package.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9b5883d0..d44f7b93 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,9 @@ "mocha": "2.5.3", "npm-run-all": "2.3.0", "nyc": "7.0.0", - "react-addons-test-utils": "15.4.2", - "react-dom": "15.4.2", + "react": "^15.6.1", + "react-addons-test-utils": "^15.6.0", + "react-dom": "^15.6.1", "rimraf": "2.5.3", "semantic-release": "^4.3.5", "sinon": "1.17.4", @@ -100,7 +101,9 @@ }, "dependencies": { "lodash.debounce": "^4.0.8", - "prop-types": "^15.5.8", - "react": "^15.3.0" + "prop-types": "^15.5.8" + }, + "peerDependencies": { + "react": ">=0.14.7" } } From b30df64406d1c88f71ad1479bc7e078082bbc664 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 16 Dec 2017 15:41:34 -0800 Subject: [PATCH 071/165] v5.4.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d44f7b93..8ba722d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "5.4.2", + "version": "5.4.3", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 25507f6d53c8bc592676f1ae99e1f7c0f4e32090 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 16 Dec 2017 15:42:22 -0800 Subject: [PATCH 072/165] refactor(cleanup): Minor code cleanup --- src/PlacesAutocomplete.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 183c9511..98c07808 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -35,7 +35,7 @@ class PlacesAutocomplete extends Component { } autocompleteCallback(predictions, status) { - if (status != this.autocompleteOK) { + if (status !== this.autocompleteOK) { this.props.onError(status) if (this.props.clearItemsOnError) { this.clearAutocomplete() } return @@ -246,7 +246,6 @@ class PlacesAutocomplete extends Component { } render() { - const { classNames, styles } = this.props const { autocompleteItems } = this.state const inputProps = this.getInputProps() From b42ede7bda075faceaace85f5e536854c746afea Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 4 Jan 2018 16:27:13 -0800 Subject: [PATCH 073/165] feat(Allow user to pass footer component as a prop): Added `renderFooter` prop to allow user to pass --- README.md | 51 +++++++++--------- demo/Demo.js | 13 +++++ demo/app.css | 11 ++++ .../images/powered_by_google_default.png | Bin .../images/powered_by_google_inverse.png | Bin src/PlacesAutocomplete.js | 18 +------ src/defaultStyles.js | 8 --- src/tests/index.spec.js | 24 ++++----- 8 files changed, 60 insertions(+), 65 deletions(-) rename {src => demo}/images/powered_by_google_default.png (100%) rename {src => demo}/images/powered_by_google_inverse.png (100%) diff --git a/README.md b/README.md index f8894648..ebbfa6bc 100644 --- a/README.md +++ b/README.md @@ -115,8 +115,7 @@ export default SimpleForm * [`options`](#options) * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) -* [`googleLogo`](#googleLogo) -* [`googleLogoType`](#googleLogoType) +* [`renderFooter`](#renderFooter) #### inputProps @@ -129,7 +128,7 @@ You can pass arbitrary props to the input element thorough `inputProps` object ( ```js const inputProps = { - value, // `value` is required + value, // `value` is required onChange, // `onChange` is required onBlur: () => { console.log('blur!') @@ -191,7 +190,7 @@ Type: `Object`, Required: `false` You can give a custom css classes to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`, `googleLogoContainer`, `googleLogoImage`. +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. If you pass `classNames` props, none of the default inline styles nor inline styles from `styles` prop will be applied to the element, and you will have full control over styling via CSS. @@ -219,8 +218,8 @@ Now you can easily apply custom CSS styles using the classNames! Type `Object`, Required: `false` -You can provide custom inline styles to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`, `googleLogoContainer`, `googleLogoImage`. +You can provide custom inline styles to elements. +Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. ```js const defaultStyles = { @@ -249,14 +248,6 @@ const defaultStyles = { autocompleteItemActive: { backgroundColor: '#fafafa' }, - googleLogoContainer: { - textAlign: 'right', - padding: '1px', - backgroundColor: '#fafafa' - }, - googleLogoImage: { - width: 150 - } } ``` @@ -368,6 +359,7 @@ const options = { types: ['address'] } +// In render function -#### googleLogo -Type: `Boolean` + +#### renderFooter +Type: `Functional React Component` Required: `false` -Default: `true` -Allows you to toggle the "powered by Google" logo. For more information on Google's logo requirements, refer to this link: [https://developers.google.com/places/web-service/policies](https://developers.google.com/places/web-service/policies) +You can provide a component that will get rendered at the bottom of dropdown. +For example, you can provide a component to show "Powered by Google" logo. - -#### googleLogoType -Type: `String` ("default" or "inverse") -Required: `false` -Default: `"default"` +```js +const renderFooter = () => ( +
+
+ +
+
+) -Allows you to pick right color theme for "powered by Google" logo. -Please see Google's API page for more information: [https://developers.google.com/places/web-service/policies](https://developers.google.com/places/web-service/policies) +// In render function + +``` ## Utility Functions diff --git a/demo/Demo.js b/demo/Demo.js index 1fa0c275..f6b1106d 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -92,6 +92,18 @@ class Demo extends React.Component { {formattedSuggestion.secondaryText}
) + + const Footer = () => ( +
+
+ +
+
+ ) + const inputProps = { type: "text", value: this.state.address, @@ -119,6 +131,7 @@ class Demo extends React.Component { ))} - {this.props.googleLogo && ( - ) - } + {this.props.renderFooter && this.props.renderFooter()}
)}
@@ -337,8 +326,7 @@ PlacesAutocomplete.propTypes = { }), debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, - googleLogo: PropTypes.bool, - googleLogoType: PropTypes.oneOf(["default", "inverse"]), + renderFooter: PropTypes.func, } PlacesAutocomplete.defaultProps = { @@ -350,8 +338,6 @@ PlacesAutocomplete.defaultProps = { options: {}, debounce: 200, highlightFirstSuggestion: false, - googleLogo: true, - googleLogoType: 'default', } export default PlacesAutocomplete diff --git a/src/defaultStyles.js b/src/defaultStyles.js index 6118adeb..c330355a 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -24,14 +24,6 @@ const defaultStyles = { autocompleteItemActive: { backgroundColor: '#fafafa' }, - googleLogoContainer: { - textAlign: 'right', - padding: '1px', - backgroundColor: '#fafafa' - }, - googleLogoImage: { - width: 150, - }, } export default defaultStyles diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index fbd8a274..277c1e65 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -55,8 +55,15 @@ describe('PlacesAutocomplete props', () => { describe('autocomplete dropdown', () => { let wrapper; const autocompleteItem = ({ suggestion }) => (
{suggestion}
) + const renderFooter = () => (
Footer element
) beforeEach(() => { - wrapper = shallow() + wrapper = shallow( + + ) }) it('initially does not have an autocomplete dropdown', () => { @@ -87,20 +94,7 @@ describe('autocomplete dropdown', () => { wrapper.setState({ autocompleteItems: data }) expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) expect(wrapper.find('.autocomplete-item')).to.have.length(3) - - describe('the Google logo', () => { - it('is displayed by default', () => { - wrapper = shallow() - wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#PlacesAutocomplete__google-logo')).to.have.length(1) - }) - - it('is not displayed when toggled off', () => { - wrapper = shallow() - wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#PlacesAutocomplete__google-logo')).to.have.length(0) - }) - }) + expect(wrapper.find('.my-dropdown-footer')).to.have.length(1) }) it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { From 2dfd625312e8c8ae24c82b2602b5ba02f9dc2161 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 4 Jan 2018 17:02:55 -0800 Subject: [PATCH 074/165] refactor(props): Rename `autocompleteItem` prop to `renderSuggestion` prop BREAKING CHANGE --- README.md | 109 +++++++++++++++++++------------------- demo/Demo.js | 2 +- src/PlacesAutocomplete.js | 6 +-- src/tests/index.spec.js | 8 +-- 4 files changed, 63 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index ebbfa6bc..81b8335a 100644 --- a/README.md +++ b/README.md @@ -105,17 +105,17 @@ export default SimpleForm #### Optional Props: -* [`autocompleteItem`](#autocompleteItem) +* [`renderSuggestion`](#renderSuggestion) +* [`renderFooter`](#renderFooter) * [`classNames`](#classNames) * [`styles`](#styles) -* [`onError`](#onError) -* [`clearItemsOnError`](#clearItemsOnError) * [`onSelect`](#onSelect) * [`onEnterKeyDown`](#onEnterKeyDown) +* [`onError`](#onError) +* [`clearItemsOnError`](#clearItemsOnError) * [`options`](#options) * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) -* [`renderFooter`](#renderFooter) #### inputProps @@ -139,36 +139,36 @@ You can pass arbitrary props to the input element thorough `inputProps` object ( } ``` - -#### autocompleteItem + +#### renderSuggestion Type: `Functional React Component`, Required: `false` The function takes props with `suggestion`, `formattedSuggestion` keys (see the example below). -We highly recommend that you create your own custom `AutocompleteItem` and pass it as a prop. +We highly recommend that you create your own custom list item component and pass it as a prop. ```js /*********************************************** Example #1 - autocompleteItem example with `suggestion` + List item example with `suggestion` ************************************************/ render() { - const AutocompleteItem = ({ suggestion }) => (
{suggestion}
) + const renderSuggestion = ({ suggestion }) => (
{suggestion}
) return ( ) } /*************************************************** Example #2 - autocompleteItem example with `formattedSuggestion` + List item example with `formattedSuggestion` ****************************************************/ render() { - const AutocompleteItem = ({ formattedSuggestion }) => ( + const renderSuggestion = ({ formattedSuggestion }) => (
{ formattedSuggestion.mainText }{' '} { formattedSuggestion.secondaryText } @@ -178,12 +178,36 @@ render() { return ( ) } ``` + +#### renderFooter +Type: `Functional React Component` +Required: `false` + +You can provide a component that will get rendered at the bottom of dropdown. +For example, you can provide a component to show "Powered by Google" logo. + +```js +const renderFooter = () => ( +
+
+ +
+
+) + +// In render function + +``` + #### classNames Type: `Object`, @@ -274,23 +298,6 @@ render() { } ``` - -#### onError -Type: `Function` -Required: `false` - -You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) - -Function takes `status` as a parameter - - -#### clearItemsOnError -Type: `Boolean` -Required: `false` -Default: `false` - -You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK - #### onSelect Type: `Function` @@ -340,6 +347,24 @@ const handleEnter = (address) => { /> ``` + +#### onError +Type: `Function` +Required: `false` + +You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) + +Function takes `status` as a parameter + + +#### clearItemsOnError +Type: `Boolean` +Required: `false` +Default: `false` + +You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK + + #### options Type: `Object` @@ -382,30 +407,6 @@ Default: `false` If set to `true`, first suggestion in the dropdown will be automatically highlighted. - -#### renderFooter -Type: `Functional React Component` -Required: `false` - -You can provide a component that will get rendered at the bottom of dropdown. -For example, you can provide a component to show "Powered by Google" logo. - -```js -const renderFooter = () => ( -
-
- -
-
-) - -// In render function - -``` - ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/demo/Demo.js b/demo/Demo.js index f6b1106d..10f67421 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -130,7 +130,7 @@ class Demo extends React.Component {
this.selectAddress(p.suggestion, p.placeId)} style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> - {this.props.autocompleteItem({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} + {this.props.renderSuggestion({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })}
))} {this.props.renderFooter && this.props.renderFooter()} @@ -295,7 +295,7 @@ PlacesAutocomplete.propTypes = { onError: PropTypes.func, clearItemsOnError: PropTypes.bool, onSelect: PropTypes.func, - autocompleteItem: PropTypes.func, + renderSuggestion: PropTypes.func, classNames: PropTypes.shape({ root: PropTypes.string, input: PropTypes.string, @@ -333,7 +333,7 @@ PlacesAutocomplete.defaultProps = { clearItemsOnError: false, onError: (status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), classNames: {}, - autocompleteItem: ({ suggestion }) => (
{suggestion}
), + renderSuggestion: ({ suggestion }) => (
{suggestion}
), styles: {}, options: {}, debounce: 200, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 277c1e65..98aeb10a 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -54,13 +54,13 @@ describe('PlacesAutocomplete props', () => { describe('autocomplete dropdown', () => { let wrapper; - const autocompleteItem = ({ suggestion }) => (
{suggestion}
) + const renderSuggestion = ({ suggestion }) => (
{suggestion}
) const renderFooter = () => (
Footer element
) beforeEach(() => { wrapper = shallow( ) @@ -162,8 +162,8 @@ describe('custom classNames, placeholder', () => { // TODO: test formattedSuggestion describe('customizable autocompleteItem', () => { it('lets you provide a custom autocomplete item', () => { - const autocompleteItem = ({ suggestion }) => (
) - const wrapper = shallow() + const renderSuggestion = ({ suggestion }) => (
) + const wrapper = shallow() wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) expect(wrapper.find('.my-autocomplete-item')).to.contain() From ad6190726c8a81fcd83968446e35e568c6005587 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 7 Jan 2018 10:50:12 -0800 Subject: [PATCH 075/165] feat(prop) Add shouldFetchSuggestions prop --- README.md | 23 ++++++++++++++++++++++- demo/Demo.js | 3 +++ src/PlacesAutocomplete.js | 11 ++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 81b8335a..4b89612d 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ export default SimpleForm * [`options`](#options) * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) +* [`shouldFetchSuggestions`](#shouldFetchSuggestions) #### inputProps @@ -397,7 +398,7 @@ Type: `Number` Required: `false` Default: `200` -The number of milliseconds to delay before making a call to Google API. +The number of milliseconds to delay before making a call to Google Maps API. #### highlightFirstSuggestion @@ -407,6 +408,26 @@ Default: `false` If set to `true`, first suggestion in the dropdown will be automatically highlighted. + +#### shouldFetchSuggestions +Type: `Function` +Required: `false` +Default: `() => true` + +You can pass a function to tell when to fetch suggestions from Google Maps API. +It takes an input `{ value }` and should return a boolean. + +```js +// Only fetch suggestions when the input text is longer than 3 characters. +const shouldFetchSuggestions = ({ value }) => value.length > 3 + +// In render function + +``` + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/demo/Demo.js b/demo/Demo.js index 10f67421..497a80dd 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -116,6 +116,8 @@ class Demo extends React.Component { id: "my-input-id", } + const shouldFetchSuggestions = ({ value }) => value.length > 3 + return (
@@ -135,6 +137,7 @@ class Demo extends React.Component { onEnterKeyDown={this.handleSelect} classNames={cssClasses} inputProps={inputProps} + shouldFetchSuggestions={shouldFetchSuggestions} /> {this.state.loading ?
: null} {!this.state.loading && this.state.geocodeResults ? diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index adcbced1..a4be8e0a 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -181,12 +181,15 @@ class PlacesAutocomplete extends Component { } handleInputChange(event) { - this.props.inputProps.onChange(event.target.value) - if (!event.target.value) { + const { value } = event.target + this.props.inputProps.onChange(value) + if (!value) { this.clearAutocomplete() return } - this.debouncedFetchPredictions() + if (this.props.shouldFetchSuggestions({ value })) { + this.debouncedFetchPredictions() + } } handleInputOnBlur(event) { @@ -327,6 +330,7 @@ PlacesAutocomplete.propTypes = { debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, renderFooter: PropTypes.func, + shouldFetchSuggestions: PropTypes.func.isRequired, } PlacesAutocomplete.defaultProps = { @@ -338,6 +342,7 @@ PlacesAutocomplete.defaultProps = { options: {}, debounce: 200, highlightFirstSuggestion: false, + shouldFetchSuggestions: () => true, } export default PlacesAutocomplete From 9b693f61ba7f51d0a891344e93aa32da565cf281 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 7 Jan 2018 20:41:31 -0800 Subject: [PATCH 076/165] Rename clearItemsOnError to clearSuggestionsOnError --- README.md | 18 +++++++++--------- demo/Demo.js | 2 +- src/PlacesAutocomplete.js | 6 +++--- src/tests/index.spec.js | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4b89612d..7eff93ff 100644 --- a/README.md +++ b/README.md @@ -112,11 +112,11 @@ export default SimpleForm * [`onSelect`](#onSelect) * [`onEnterKeyDown`](#onEnterKeyDown) * [`onError`](#onError) -* [`clearItemsOnError`](#clearItemsOnError) * [`options`](#options) * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) * [`shouldFetchSuggestions`](#shouldFetchSuggestions) +* [`clearSuggestionsOnError`](#clearSuggestionsOnError) #### inputProps @@ -357,14 +357,6 @@ You can pass `onError` prop to customize the behavior when [google.maps.places.P Function takes `status` as a parameter - -#### clearItemsOnError -Type: `Boolean` -Required: `false` -Default: `false` - -You can pass `clearItemsOnError` prop to indicate whether the autocomplete predictions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK - #### options @@ -428,6 +420,14 @@ const shouldFetchSuggestions = ({ value }) => value.length > 3 /> ``` + +#### clearSuggestionsOnError +Type: `Boolean` +Required: `false` +Default: `false` + +You can pass `clearSuggestionsOnError` prop to indicate whether the autocomplete suggestions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/demo/Demo.js b/demo/Demo.js index 497a80dd..e488014e 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -116,7 +116,7 @@ class Demo extends React.Component { id: "my-input-id", } - const shouldFetchSuggestions = ({ value }) => value.length > 3 + const shouldFetchSuggestions = ({ value }) => value.length > 2 return (
diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index a4be8e0a..5e81c329 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -37,7 +37,7 @@ class PlacesAutocomplete extends Component { autocompleteCallback(predictions, status) { if (status !== this.autocompleteOK) { this.props.onError(status) - if (this.props.clearItemsOnError) { this.clearAutocomplete() } + if (this.props.clearSuggestionsOnError) { this.clearAutocomplete() } return } @@ -296,7 +296,7 @@ PlacesAutocomplete.propTypes = { } }, onError: PropTypes.func, - clearItemsOnError: PropTypes.bool, + clearSuggestionsOnError: PropTypes.bool, onSelect: PropTypes.func, renderSuggestion: PropTypes.func, classNames: PropTypes.shape({ @@ -334,7 +334,7 @@ PlacesAutocomplete.propTypes = { } PlacesAutocomplete.defaultProps = { - clearItemsOnError: false, + clearSuggestionsOnError: false, onError: (status) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), classNames: {}, renderSuggestion: ({ suggestion }) => (
{suggestion}
), diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 98aeb10a..f48ed234 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -97,20 +97,20 @@ describe('autocomplete dropdown', () => { expect(wrapper.find('.my-dropdown-footer')).to.have.length(1) }) - it('clears the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is true', () => { + it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { const initialItems = [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] - const wrapper = shallow() + const wrapper = shallow() wrapper.setState({ autocompleteItems: initialItems }) wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(wrapper.find('.autocomplete-item')).to.have.length(0) }) - it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearItemsOnError prop is false', () => { + it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { const initialItems = [{ suggestion: 'San Francisco, CA', placeId: 1, From 157cd3c1242f4d4bed00fd9d3dd8152f2b4a765d Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 7 Jan 2018 20:54:21 -0800 Subject: [PATCH 077/165] v6.0.0-beta.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8ba722d1..20aa9dcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "5.4.3", + "version": "6.0.0-beta.0", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 428983f68def7a2a92da135643a3867c8268a28e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 9 Jan 2018 07:35:09 -0800 Subject: [PATCH 078/165] feat(prop) Allow user to clear suggestions using `onError` prop Remove `clearSuggesionsOnError` prop --- README.md | 25 +++++++++++++++---------- demo/Demo.js | 6 ++++++ src/PlacesAutocomplete.js | 20 +++++++++----------- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7eff93ff..48141de0 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,6 @@ export default SimpleForm * [`debounce`](#debounce) * [`highlightFirstSuggestion`](#highlightFirstSuggestion) * [`shouldFetchSuggestions`](#shouldFetchSuggestions) -* [`clearSuggestionsOnError`](#clearSuggestionsOnError) #### inputProps @@ -355,7 +354,21 @@ Required: `false` You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) -Function takes `status` as a parameter +Function takes `status` (string) and `clearSuggestions` (function) as parameters + +```js +// Log error status and clear dropdown when Google Maps API returns an error. +const onError = (status, clearSuggestions) => { + console.log('Google Maps API returned error with status: ', status) + clearSuggestions() +} + +// In render function + +``` @@ -420,14 +433,6 @@ const shouldFetchSuggestions = ({ value }) => value.length > 3 /> ``` - -#### clearSuggestionsOnError -Type: `Boolean` -Required: `false` -Default: `false` - -You can pass `clearSuggestionsOnError` prop to indicate whether the autocomplete suggestions should be cleared when `google.maps.places.PlacesServiceStatus` is not OK - ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/demo/Demo.js b/demo/Demo.js index e488014e..3a04de24 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -118,6 +118,11 @@ class Demo extends React.Component { const shouldFetchSuggestions = ({ value }) => value.length > 2 + const onError = (status, clearSuggestions) => { + console.log('Error happened while fetching suggestions from Google Maps API', status) + clearSuggestions() + } + return (
@@ -132,6 +137,7 @@ class Demo extends React.Component {
console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), + onError: (status, _clearSuggestions) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), classNames: {}, renderSuggestion: ({ suggestion }) => (
{suggestion}
), styles: {}, From 92ccac4aaa8d66cb0b6aecdfc313203f279cba75 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 9 Jan 2018 08:12:00 -0800 Subject: [PATCH 079/165] v6.0.0-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20aa9dcd..03ab2542 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.0.0-beta.0", + "version": "6.0.0-beta.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 4627a63d5741fd5e52967f49ececed60cc1866e6 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 11 Jan 2018 20:34:36 -0800 Subject: [PATCH 080/165] chore(tooling): Add pettier package and script for code formatting --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 03ab2542..bf01c8f0 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "demo:test": "mocha demo/tests/index.spec.js --compilers js:babel-register", "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", "demo:deploy": "gh-pages -d demo/dist", - "postpublish": "npm run demo:deploy" + "postpublish": "npm run demo:deploy", + "prettier": "prettier --no-semi --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"" }, "repository": { "type": "git", @@ -75,6 +76,7 @@ "mocha": "2.5.3", "npm-run-all": "2.3.0", "nyc": "7.0.0", + "prettier": "1.10.2", "react": "^15.6.1", "react-addons-test-utils": "^15.6.0", "react-dom": "^15.6.1", From 70eae87f8f0ac5639c7be8727b0f103ea4b42867 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 11 Jan 2018 20:36:54 -0800 Subject: [PATCH 081/165] style(formatting): Format code with perttier script --- demo/Demo.js | 83 +++++++++----- demo/index.js | 5 +- demo/tests/index.spec.js | 12 ++- demo/webpack.config.js | 81 +++++++------- src/PlacesAutocomplete.js | 109 ++++++++++++------- src/defaultStyles.js | 2 +- src/index.js | 6 +- src/tests/index.spec.js | 221 +++++++++++++++++++++++++++----------- src/tests/setup.js | 22 ++-- src/tests/testHelper.js | 8 +- src/utils.js | 22 ++-- 11 files changed, 365 insertions(+), 206 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index 3a04de24..f7d6f4b0 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -7,7 +7,7 @@ class Demo extends React.Component { this.state = { address: '', geocodeResults: null, - loading: false + loading: false, } this.handleSelect = this.handleSelect.bind(this) this.handleChange = this.handleChange.bind(this) @@ -18,23 +18,23 @@ class Demo extends React.Component { handleSelect(address) { this.setState({ address, - loading: true + loading: true, }) geocodeByAddress(address) - .then((results) => getLatLng(results[0])) + .then(results => getLatLng(results[0])) .then(({ lat, lng }) => { console.log('Success Yay', { lat, lng }) this.setState({ geocodeResults: this.renderGeocodeSuccess(lat, lng), - loading: false + loading: false, }) }) - .catch((error) => { + .catch(error => { console.log('Oh no!', error) this.setState({ geocodeResults: this.renderGeocodeFailure(error), - loading: false + loading: false, }) }) @@ -58,7 +58,7 @@ class Demo extends React.Component { handleChange(address) { this.setState({ address, - geocodeResults: null + geocodeResults: null, }) } @@ -73,7 +73,10 @@ class Demo extends React.Component { renderGeocodeSuccess(lat, lng) { return (
- Success! Geocoder found latitude and longitude: {lat}, {lng} + Success! Geocoder found latitude and longitude:{' '} + + {lat}, {lng} +
) } @@ -87,11 +90,13 @@ class Demo extends React.Component { const AutocompleteItem = ({ formattedSuggestion }) => (
- + {formattedSuggestion.mainText}{' '} - {formattedSuggestion.secondaryText} -
) - + + {formattedSuggestion.secondaryText} + +
+ ) const Footer = () => (
@@ -105,36 +110,52 @@ class Demo extends React.Component { ) const inputProps = { - type: "text", + type: 'text', value: this.state.address, onChange: this.handleChange, - onBlur: () => { console.log('Blur event!'); }, - onFocus: () => { console.log('Focused!'); }, + onBlur: () => { + console.log('Blur event!') + }, + onFocus: () => { + console.log('Focused!') + }, autoFocus: true, - placeholder: "Search Places", + placeholder: 'Search Places', name: 'Demo__input', - id: "my-input-id", + id: 'my-input-id', } const shouldFetchSuggestions = ({ value }) => value.length > 2 const onError = (status, clearSuggestions) => { - console.log('Error happened while fetching suggestions from Google Maps API', status) + console.log( + 'Error happened while fetching suggestions from Google Maps API', + status + ) clearSuggestions() } return ( -
-
-

react-places-autocomplete

-

A React component to build a customized UI for Google Maps Places Autocomplete

+
+
+

+ react-places-autocomplete +

+

+ A React component to build a customized UI for Google Maps Places + Autocomplete +


- - + +  View on GitHub
-
+
- {this.state.loading ?
: null} - {!this.state.loading && this.state.geocodeResults ? -
{this.state.geocodeResults}
: - null} + {this.state.loading ? ( +
+ +
+ ) : null} + {!this.state.loading && this.state.geocodeResults ? ( +
{this.state.geocodeResults}
+ ) : null}
) diff --git a/demo/index.js b/demo/index.js index 1238a2fb..ceed2391 100644 --- a/demo/index.js +++ b/demo/index.js @@ -2,7 +2,4 @@ import React from 'react' import ReactDOM from 'react-dom' import Demo from './Demo' -ReactDOM.render( - React.createElement(Demo, {}), - document.getElementById('app') -) +ReactDOM.render(React.createElement(Demo, {}), document.getElementById('app')) diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js index 74ff2092..875bd5b5 100644 --- a/demo/tests/index.spec.js +++ b/demo/tests/index.spec.js @@ -5,7 +5,7 @@ import PlacesAutocomplete, { geocodeByAddress } from '../../src' import Demo from '../Demo' describe('', () => { - let wrapper; + let wrapper beforeEach(() => { wrapper = shallow() }) @@ -17,7 +17,9 @@ describe('', () => { it('sets the value prop of the input element to state.address', () => { const wrapper = mount() wrapper.setState({ address: '123 Fake St' }) - expect(wrapper.find(PlacesAutocomplete).props().value).to.equal('123 Fake St') + expect(wrapper.find(PlacesAutocomplete).props().value).to.equal( + '123 Fake St' + ) }) it('renders loading animation when state.loading is true', () => { @@ -25,12 +27,14 @@ describe('', () => { expect(wrapper.find('.loader')).to.exist }) - it('doesn\'t initially render geocoding results', () => { + it("doesn't initially render geocoding results", () => { expect(wrapper.find('.geocoding-results')).to.not.exist }) it('renders geocoding results when state.geocodeResults has value', () => { - wrapper.setState({ geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456) }) + wrapper.setState({ + geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456), + }) expect(wrapper.find('.geocoding-results')).to.exist }) }) diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 96adf4d6..6b0a5882 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -7,7 +7,7 @@ module.exports = { entry: './demo/index.js', output: { path: __dirname + '/dist', - filename: 'index.min.js' + filename: 'index.min.js', }, devtool: 'source-map', module: { @@ -17,48 +17,51 @@ module.exports = { exclude: /node_modules/, loader: 'babel', query: { - presets:['es2015', 'react'] - } + presets: ['es2015', 'react'], + }, }, - {test: /\.json$/, loader: 'json'}, + { test: /\.json$/, loader: 'json' }, { test: /\.(jpe?g|png|gif|svg)$/i, loaders: [ 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', - 'image-webpack-loader' - ] - } - ] - }, - plugins: process.argv.indexOf('-p') !== -1 ? [ - new CopyWebpackPlugin([ - { from: './demo/app.css' }, - { from: './demo/favicon.ico' }, - { from: './demo/index.html' } - ]), - new webpack.DefinePlugin({ - 'process.env':{ - 'NODE_ENV': JSON.stringify('production') - } - }), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurrenceOrderPlugin(), - new webpack.optimize.UglifyJsPlugin(), - new webpack.optimize.UglifyJsPlugin({ - mangle: true, - compress: { - warnings: false, - pure_getters: true, - unsafe: true, - unsafe_comps: true, - screw_ie8: true - }, - output: { - comments: false, + 'image-webpack-loader', + ], }, - exclude: [/\.min\.js$/gi] - }), - new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), - ] : [] + ], + }, + plugins: + process.argv.indexOf('-p') !== -1 + ? [ + new CopyWebpackPlugin([ + { from: './demo/app.css' }, + { from: './demo/favicon.ico' }, + { from: './demo/index.html' }, + ]), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify('production'), + }, + }), + new webpack.optimize.AggressiveMergingPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurrenceOrderPlugin(), + new webpack.optimize.UglifyJsPlugin(), + new webpack.optimize.UglifyJsPlugin({ + mangle: true, + compress: { + warnings: false, + pure_getters: true, + unsafe: true, + unsafe_comps: true, + screw_ie8: true, + }, + output: { + comments: false, + }, + exclude: [/\.min\.js$/gi], + }), + new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), + ] + : [], } diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 30b1581b..61bf76ac 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -18,17 +18,24 @@ class PlacesAutocomplete extends Component { this.autocompleteCallback = this.autocompleteCallback.bind(this) this.handleInputKeyDown = this.handleInputKeyDown.bind(this) this.handleInputChange = this.handleInputChange.bind(this) - this.debouncedFetchPredictions = debounce(this.fetchPredictions, this.props.debounce) + this.debouncedFetchPredictions = debounce( + this.fetchPredictions, + this.props.debounce + ) this.clearSuggestions = this.clearSuggestions.bind(this) } componentDidMount() { if (!window.google) { - throw new Error('Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library') + throw new Error( + 'Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' + ) } if (!window.google.maps.places) { - throw new Error('Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library') + throw new Error( + 'Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' + ) } this.autocompleteService = new google.maps.places.AutocompleteService() @@ -42,7 +49,7 @@ class PlacesAutocomplete extends Component { } // transform snake_case to camelCase - const formattedSuggestion = (structured_formatting) => ({ + const formattedSuggestion = structured_formatting => ({ mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text, }) @@ -53,20 +60,23 @@ class PlacesAutocomplete extends Component { autocompleteItems: predictions.map((p, idx) => ({ suggestion: p.description, placeId: p.place_id, - active: (highlightFirstSuggestion && idx === 0 ? true : false), + active: highlightFirstSuggestion && idx === 0 ? true : false, index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), - })) + })), }) } fetchPredictions() { const { value } = this.props.inputProps if (value.length) { - this.autocompleteService.getPlacePredictions({ - ...this.props.options, - input: value - }, this.autocompleteCallback) + this.autocompleteService.getPlacePredictions( + { + ...this.props.options, + input: value, + }, + this.autocompleteCallback + ) } } @@ -80,7 +90,9 @@ class PlacesAutocomplete extends Component { } handleSelect(address, placeId) { - this.props.onSelect ? this.props.onSelect(address, placeId) : this.props.inputProps.onChange(address) + this.props.onSelect + ? this.props.onSelect(address, placeId) + : this.props.inputProps.onChange(address) } getActiveItem() { @@ -88,7 +100,9 @@ class PlacesAutocomplete extends Component { } selectActiveItemAtIndex(index) { - const activeName = this.state.autocompleteItems.find(item => item.index === index).suggestion + const activeName = this.state.autocompleteItems.find( + item => item.index === index + ).suggestion this.setActiveItemAtIndex(index) this.props.inputProps.onChange(activeName) } @@ -120,7 +134,8 @@ class PlacesAutocomplete extends Component { if (activeItem === undefined) { this.selectActiveItemAtIndex(0) } else { - const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length + const nextIndex = + (activeItem.index + 1) % this.state.autocompleteItems.length this.selectActiveItemAtIndex(nextIndex) } } @@ -227,20 +242,20 @@ class PlacesAutocomplete extends Component { getInputProps() { const defaultInputProps = { - type: "text", - autoComplete: "off", + type: 'text', + autoComplete: 'off', } return { ...defaultInputProps, ...this.props.inputProps, - onChange: (event) => { + onChange: event => { this.handleInputChange(event) }, - onKeyDown: (event) => { + onKeyDown: event => { this.handleInputKeyDown(event) }, - onBlur: (event) => { + onBlur: event => { this.handleInputOnBlur(event) }, style: this.inlineStyleFor('input'), @@ -256,13 +271,15 @@ class PlacesAutocomplete extends Component {
+ className={this.classNameFor('root')} + > {autocompleteItems.length > 0 && (
+ className={this.classNameFor('autocompleteContainer')} + > {autocompleteItems.map((p, idx) => (
this.selectAddress(p.suggestion, p.placeId)} onTouchStart={() => this.setActiveItemAtIndex(p.index)} onTouchEnd={() => this.selectAddress(p.suggestion, p.placeId)} - style={ p.active ? this.inlineStyleFor('autocompleteItem', 'autocompleteItemActive') :this.inlineStyleFor('autocompleteItem') } - className={ p.active ? this.classNameFor('autocompleteItem', 'autocompleteItemActive') : this.classNameFor('autocompleteItem') }> - {this.props.renderSuggestion({ suggestion: p.suggestion, formattedSuggestion: p.formattedSuggestion })} + style={ + p.active + ? this.inlineStyleFor( + 'autocompleteItem', + 'autocompleteItemActive' + ) + : this.inlineStyleFor('autocompleteItem') + } + className={ + p.active + ? this.classNameFor( + 'autocompleteItem', + 'autocompleteItemActive' + ) + : this.classNameFor('autocompleteItem') + } + > + {this.props.renderSuggestion({ + suggestion: p.suggestion, + formattedSuggestion: p.formattedSuggestion, + })}
))} {this.props.renderFooter && this.props.renderFooter()} @@ -285,14 +320,14 @@ class PlacesAutocomplete extends Component { PlacesAutocomplete.propTypes = { inputProps: (props, propName) => { - const inputProps = props[propName]; + const inputProps = props[propName] if (!inputProps.hasOwnProperty('value')) { - throw new Error('\'inputProps\' must have \'value\'.') + throw new Error("'inputProps' must have 'value'.") } if (!inputProps.hasOwnProperty('onChange')) { - throw new Error('\'inputProps\' must have \'onChange\'.') + throw new Error("'inputProps' must have 'onChange'.") } }, onError: PropTypes.func, @@ -310,21 +345,15 @@ PlacesAutocomplete.propTypes = { input: PropTypes.object, autocompleteContainer: PropTypes.object, autocompleteItem: PropTypes.object, - autocompleteItemActive: PropTypes.object + autocompleteItemActive: PropTypes.object, }), options: PropTypes.shape({ bounds: PropTypes.object, componentRestrictions: PropTypes.object, location: PropTypes.object, - offset: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string - ]), - radius: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string - ]), - types: PropTypes.array + offset: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + radius: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + types: PropTypes.array, }), debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, @@ -333,9 +362,13 @@ PlacesAutocomplete.propTypes = { } PlacesAutocomplete.defaultProps = { - onError: (status, _clearSuggestions) => console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status), + onError: (status, _clearSuggestions) => + console.error( + '[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', + status + ), classNames: {}, - renderSuggestion: ({ suggestion }) => (
{suggestion}
), + renderSuggestion: ({ suggestion }) =>
{suggestion}
, styles: {}, options: {}, debounce: 200, diff --git a/src/defaultStyles.js b/src/defaultStyles.js index c330355a..faeef3d4 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -22,7 +22,7 @@ const defaultStyles = { cursor: 'pointer', }, autocompleteItemActive: { - backgroundColor: '#fafafa' + backgroundColor: '#fafafa', }, } diff --git a/src/index.js b/src/index.js index 24de300c..0968ecf0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,6 @@ import PlacesAutocomplete from './PlacesAutocomplete' import { geocodeByAddress, geocodeByPlaceId, getLatLng } from './utils' -export { - geocodeByAddress, - geocodeByPlaceId, - getLatLng, -} +export { geocodeByAddress, geocodeByPlaceId, getLatLng } export default PlacesAutocomplete diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index f48ed234..d5de213a 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -6,13 +6,13 @@ import { expect } from './testHelper' import PlacesAutocomplete, { geocodeByAddress } from '../index.js' const testInputProps = { - value: "San Francisco, CA", + value: 'San Francisco, CA', onChange: () => {}, } /*** Enzyme Rocks ***/ describe('', () => { - let wrapper; + let wrapper beforeEach(() => { wrapper = shallow() }) @@ -20,13 +20,15 @@ describe('', () => { it('renders an input element', () => { expect(wrapper.find('input')).to.have.length(1) }) -}); +}) // TODO: What's the value of this test? describe('PlacesAutocomplete callbacks', () => { it('executes onError callback passed in as prop when status is not OK', () => { const spy = sinon.spy() - const wrapper = mount() + const wrapper = mount( + + ) wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(spy.calledOnce).to.equal(true) expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) @@ -38,24 +40,28 @@ describe('PlacesAutocomplete callbacks', () => { wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(console.error.calledOnce).to.equal(true) }) -}); +}) describe('PlacesAutocomplete props', () => { it('allows user to set the value of the input through prop', () => { const inputProps = { ...testInputProps, - value: "New York, NY", + value: 'New York, NY', } const wrapper = mount() - expect(wrapper.find('input').props().value).to.equal("New York, NY") + expect(wrapper.find('input').props().value).to.equal('New York, NY') }) -}); +}) describe('autocomplete dropdown', () => { - let wrapper; - const renderSuggestion = ({ suggestion }) => (
{suggestion}
) - const renderFooter = () => (
Footer element
) + let wrapper + const renderSuggestion = ({ suggestion }) => ( +
{suggestion}
+ ) + const renderFooter = () => ( +
Footer element
+ ) beforeEach(() => { wrapper = shallow( { }) it('initially does not have an autocomplete dropdown', () => { - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(0) + expect( + wrapper.find('#PlacesAutocomplete__autocomplete-container') + ).to.have.length(0) }) it('renders autocomplete dropdown once it receives data from google maps', () => { @@ -76,47 +84,58 @@ describe('autocomplete dropdown', () => { suggestion: 'San Francisco, CA', placeId: 1, active: false, - index: 0 + index: 0, }, { suggestion: 'San Jose, CA', placeId: 2, active: false, - index: 1 + index: 1, }, { suggestion: 'San Diego, CA', placeId: 3, active: false, - index: 2 - } + index: 2, + }, ] wrapper.setState({ autocompleteItems: data }) - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.length(1) + expect( + wrapper.find('#PlacesAutocomplete__autocomplete-container') + ).to.have.length(1) expect(wrapper.find('.autocomplete-item')).to.have.length(3) expect(wrapper.find('.my-dropdown-footer')).to.have.length(1) }) it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { - const initialItems = [{ + const initialItems = [ + { suggestion: 'San Francisco, CA', placeId: 1, active: false, - index: 0 - }] - const wrapper = shallow() + index: 0, + }, + ] + const wrapper = shallow( + + ) wrapper.setState({ autocompleteItems: initialItems }) wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(wrapper.find('.autocomplete-item')).to.have.length(0) }) it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { - const initialItems = [{ + const initialItems = [ + { suggestion: 'San Francisco, CA', placeId: 1, active: false, - index: 0 - }] + index: 0, + }, + ] wrapper.setState({ autocompleteItems: initialItems }) wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') expect(wrapper.find('.autocomplete-item')).to.have.length(1) @@ -126,19 +145,21 @@ describe('autocomplete dropdown', () => { describe('custom classNames, placeholder', () => { const inputProps = { ...testInputProps, - placeholder: "Your Address", + placeholder: 'Your Address', } const classNames = { root: 'my-container', input: 'my-input', - autocompleteContainer: 'my-autocomplete-container' + autocompleteContainer: 'my-autocomplete-container', } - let wrapper; + let wrapper beforeEach(() => { - wrapper = shallow() + wrapper = shallow( + + ) }) it('lets you set a custom className for the container', () => { @@ -150,23 +171,54 @@ describe('custom classNames, placeholder', () => { }) it('lets you set a custom className for autocomplete container', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container')).to.have.className('my-autocomplete-container') + wrapper.setState({ + autocompleteItems: [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0, + }, + ], + }) + expect( + wrapper.find('#PlacesAutocomplete__autocomplete-container') + ).to.have.className('my-autocomplete-container') }) it('lets you set a custom placeholder for the input', () => { expect(wrapper.find('input').props().placeholder).to.equal('Your Address') }) -}); +}) // TODO: test formattedSuggestion describe('customizable autocompleteItem', () => { it('lets you provide a custom autocomplete item', () => { - const renderSuggestion = ({ suggestion }) => (
) - const wrapper = shallow() - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) + const renderSuggestion = ({ suggestion }) => ( +
+ +
+ ) + const wrapper = shallow( + + ) + wrapper.setState({ + autocompleteItems: [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0, + }, + ], + }) expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) - expect(wrapper.find('.my-autocomplete-item')).to.contain() + expect(wrapper.find('.my-autocomplete-item')).to.contain( + + ) }) }) @@ -176,17 +228,20 @@ describe('custom inline styles', () => { input: { width: '100%' }, autocompleteContainer: { backgroundColor: 'green' }, autocompleteItem: { color: 'black' }, - autocompleteItemActive: { color: 'blue' } + autocompleteItemActive: { color: 'blue' }, } - let wrapper; + let wrapper beforeEach(() => { - - wrapper = shallow() + wrapper = shallow( + + ) }) it('lets you set custom styles for the root element', () => { - expect(wrapper.find('#PlacesAutocomplete__root').props().style.position).to.equal('absolute') + expect( + wrapper.find('#PlacesAutocomplete__root').props().style.position + ).to.equal('absolute') }) it('lets you set custom styles for the input element', () => { @@ -194,40 +249,80 @@ describe('custom inline styles', () => { }) it('lets you set custom styles for the autocomplete container element', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - expect(wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style.backgroundColor).to.equal('green') + wrapper.setState({ + autocompleteItems: [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0, + }, + ], + }) + expect( + wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style + .backgroundColor + ).to.equal('green') }) it('lets you set custom styles for autocomplete items', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] }) - const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) + wrapper.setState({ + autocompleteItems: [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0, + }, + ], + }) + const item = wrapper + .find('#PlacesAutocomplete__autocomplete-container') + .childAt(0) expect(item.props().style.color).to.equal('black') }) it('lets you set custom styles for active autocomplete items', () => { - wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] }) - const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0) + wrapper.setState({ + autocompleteItems: [ + { suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }, + ], + }) + const item = wrapper + .find('#PlacesAutocomplete__autocomplete-container') + .childAt(0) expect(item.props().style.color).to.equal('blue') }) }) - describe('AutocompletionRequest options', () => { - const inputProps = { - ...testInputProps, - value: 'Boston, MA', - } - it('calls getPlacePredictions with the correct options', (done) => { - global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = (request, callback) => {} - const spy = sinon.spy(global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions') - const options = { radius: 2000, types: ['address'] } - const wrapper = mount() - wrapper.find('input').simulate('change', { target: { value: 'Los Angeles, CA' } }) - setTimeout(() => { - done() - expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be.true - }, 0) - }) - }) +describe('AutocompletionRequest options', () => { + const inputProps = { + ...testInputProps, + value: 'Boston, MA', + } + it('calls getPlacePredictions with the correct options', done => { + global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = ( + request, + callback + ) => {} + const spy = sinon.spy( + global.google.maps.places.AutocompleteService.prototype, + 'getPlacePredictions' + ) + const options = { radius: 2000, types: ['address'] } + const wrapper = mount( + + ) + wrapper + .find('input') + .simulate('change', { target: { value: 'Los Angeles, CA' } }) + setTimeout(() => { + done() + expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be + .true + }, 0) + }) +}) describe('autoFocus prop', () => { const inputProps = { diff --git a/src/tests/setup.js b/src/tests/setup.js index 8037327c..1ef28bc9 100644 --- a/src/tests/setup.js +++ b/src/tests/setup.js @@ -5,20 +5,20 @@ // 3. Registers babel for transpiling our code for testing. // This assures the .babelrc dev config doesn't apply for tests. -process.env.NODE_ENV = 'production'; +process.env.NODE_ENV = 'production' // Disable webpack-specific features for tests since // Mocha doesn't know what to do with them. -require.extensions['.css'] = function () { - return null; -}; -require.extensions['.png'] = function () { - return null; -}; -require.extensions['.jpg'] = function () { - return null; -}; +require.extensions['.css'] = function() { + return null +} +require.extensions['.png'] = function() { + return null +} +require.extensions['.jpg'] = function() { + return null +} // Register babel so that it will transpile ES6 to ES5 // before our tests run. -require('babel-register')(); +require('babel-register')() diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js index 5b14d5a6..e4cb004a 100644 --- a/src/tests/testHelper.js +++ b/src/tests/testHelper.js @@ -12,10 +12,10 @@ const google = { places: { AutocompleteService: () => {}, PlacesServiceStatus: { - OK: 'OK' - } - } - } + OK: 'OK', + }, + }, + }, } global.google = google global.window.google = google diff --git a/src/utils.js b/src/utils.js index cc5d2b9a..5f91416a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,10 +5,11 @@ export const geocodeByAddress = (address, callback) => { return new Promise((resolve, reject) => { geocoder.geocode({ address }, (results, status) => { if (status !== OK) { - // TODO: Remove callback support in the next major version. if (callback) { - console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"') + console.warn( + 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' + ) callback({ status }, null, results) return } @@ -22,7 +23,9 @@ export const geocodeByAddress = (address, callback) => { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), } - console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"') + console.warn( + 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' + ) callback(null, latLng, results) } @@ -31,8 +34,8 @@ export const geocodeByAddress = (address, callback) => { }) } -export const getLatLng = (result) => { - return new Promise((resolve, reject) =>{ +export const getLatLng = result => { + return new Promise((resolve, reject) => { try { const latLng = { lat: result.geometry.location.lat(), @@ -52,10 +55,11 @@ export const geocodeByPlaceId = (placeId, callback) => { return new Promise((resolve, reject) => { geocoder.geocode({ placeId }, (results, status) => { if (status !== OK) { - // TODO: Remove callback support in the next major version. if (callback) { - console.warn('Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') + console.warn( + 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' + ) callback({ status }, null, results) return } @@ -69,7 +73,9 @@ export const geocodeByPlaceId = (placeId, callback) => { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), } - console.warn('Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"') + console.warn( + 'Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' + ) callback(null, latLng, results) } From df481fc388155d4eda6bd1deab2b1a4dba595f8e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 15 Jan 2018 17:47:43 -0800 Subject: [PATCH 082/165] docs(readme): Update README --- README.md | 62 +++++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 48141de0..8ac281f8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,17 @@ -# react-places-autocomplete - -A React component to build a customized UI for Google Maps Places Autocomplete ([Demo](https://kenny-hibino.github.io/react-places-autocomplete/)) - - [![travis build](https://img.shields.io/travis/kenny-hibino/react-places-autocomplete.svg?style=flat-square)](https://travis-ci.org/kenny-hibino/react-places-autocomplete) [![MIT-License](https://img.shields.io/npm/l/react-places-autocomplete.svg?style=flat-square)]() [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/react-places-autocomplete/Lobby) + +# React Places Autocomplete + +A React component to build a customized UI for Google Maps Places Autocomplete + + +### Demo +Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hibino.github.io/react-places-autocomplete/) + + ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) 2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) @@ -25,7 +30,7 @@ or npm install react-places-autocomplete --save ``` -The React component is exported as a default export +React component is exported as a default export ```js import PlacesAutocomplete from 'react-places-autocomplete' @@ -37,15 +42,6 @@ import PlacesAutocomplete from 'react-places-autocomplete' import { geocodeByAddress, geocodeByPlaceId } from 'react-places-autocomplete' ``` -### Demo -See live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hibino.github.io/react-places-autocomplete/) - -To build the example locally, clone this repo and then run: - -```sh -npm run demo -``` - ### Getting Started @@ -57,7 +53,7 @@ Load the library in your project ``` -Declare your PlacesAutocomplete component using React component +Create your component ```js import React from 'react' @@ -97,25 +93,23 @@ class SimpleForm extends React.Component { export default SimpleForm ``` -### Props for `PlacesAutocomplete` - -#### Required Props: - -* [`inputProps`](#inputProps) - -#### Optional Props: +## Props + +| Prop | Type | Required | Description | +| ------------- |:-------------:| :-----: |-------| +| [`inputProps`](#inputProps) | object | :white_check_mark: | Arbitrary props to input element, `value` and `onChange` are required keys | +| [`renderSuggestion`](#renderSuggestion) | function | | Functional react component to render dropdown list item | +| [`renderFooter`](#renderFooter) | function | | Functional react component to render footer at the bottom of the dropdown list | +| [`classNames`](#classNames) | object | | Pass CSS classes to rendered elements | +| [`styles`](#styles) | object | | Pass CSS styles to rendered elements | +| [`onSelect`](#onSelect) | function | | Event handler to handle user's select event | +| [`onEnterKeyDown`](#onEnterKeyDown) | function || Event handler that gets called when user presses Enter key while input is focused | +| [`onError`](#onError) | function | | Error handler function that gets called when Google Maps API responds with an error | +| [`options`](#options) | object | | Options to Google Maps API (i.e. bounds, radius) | +|[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | +| [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | +|[`shouldFetchSuggestions`](#shouldFetchSuggestions)| function | | Component will fetch suggestions from Google Maps API only when this function returns `true` | -* [`renderSuggestion`](#renderSuggestion) -* [`renderFooter`](#renderFooter) -* [`classNames`](#classNames) -* [`styles`](#styles) -* [`onSelect`](#onSelect) -* [`onEnterKeyDown`](#onEnterKeyDown) -* [`onError`](#onError) -* [`options`](#options) -* [`debounce`](#debounce) -* [`highlightFirstSuggestion`](#highlightFirstSuggestion) -* [`shouldFetchSuggestions`](#shouldFetchSuggestions) #### inputProps From 94ab3d0502a92f5b598e8a726799e93b15d9a2fa Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 15 Jan 2018 17:52:56 -0800 Subject: [PATCH 083/165] v6.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bf01c8f0..01d59f74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.0.0-beta.1", + "version": "6.0.0", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From ef4dc4629bbc9fa3245bc30aadcd1c05d29a1baa Mon Sep 17 00:00:00 2001 From: Darcy Glennen Date: Tue, 19 Sep 2017 04:07:32 +1000 Subject: [PATCH 084/165] fix($browser): Added e.preventDefault() to AutoCompleteItem touch event Fixed a bug where touching a suggested address would trigger any clickable elements beneath it Closed issue #123 --- src/PlacesAutocomplete.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 61bf76ac..1de68018 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -84,7 +84,10 @@ class PlacesAutocomplete extends Component { this.setState({ autocompleteItems: [] }) } - selectAddress(address, placeId) { + selectAddress(address, placeId, e) { + if (e !== undefined) { + e.preventDefault() + } this.clearSuggestions() this.handleSelect(address, placeId) } @@ -284,9 +287,11 @@ class PlacesAutocomplete extends Component {
this.setActiveItemAtIndex(p.index)} - onMouseDown={() => this.selectAddress(p.suggestion, p.placeId)} + onMouseDown={e => + this.selectAddress(p.suggestion, p.placeId, e) + } onTouchStart={() => this.setActiveItemAtIndex(p.index)} - onTouchEnd={() => this.selectAddress(p.suggestion, p.placeId)} + onTouchEnd={e => this.selectAddress(p.suggestion, p.placeId, e)} style={ p.active ? this.inlineStyleFor( From 900c28f2dd8573b7cd69150c3d4215da32934477 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 17 Jan 2018 09:59:11 -0800 Subject: [PATCH 085/165] v6.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01d59f74..00c7fc17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.0.0", + "version": "6.0.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 1ead2c3ef51ec010bb850f03f22b6806c5515cb8 Mon Sep 17 00:00:00 2001 From: Jon Abrams Date: Wed, 17 Jan 2018 14:06:28 -0800 Subject: [PATCH 086/165] Add closing tags to renderFooter example --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ac281f8..507dc5c6 100644 --- a/README.md +++ b/README.md @@ -191,8 +191,8 @@ const renderFooter = () => (
-
-
+
+
) // In render function From 6e73b11e17ed76d9cddd964916f903002803f8bd Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 17 Jan 2018 16:24:44 -0800 Subject: [PATCH 087/165] v6.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 00c7fc17..4eb3a289 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.0.1", + "version": "6.0.2", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 1e261c7d070118e508c19203d1e9e8322444a871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Pierzcha=C5=82a?= Date: Fri, 8 Dec 2017 20:52:44 +0100 Subject: [PATCH 088/165] save and include later in autocomplete original input value After filling input with some value and selecting one of the entries from autocomplete, we save previous/original value (before selecting any of the entries) to local state to preserve for later use. We use when are about to wrap around autocomplete entries, for example when we're at last autocomplete entry and we press arrow down key. Instead of focusing top entry, we populate input value with the original one stored in local state. That way original entry is treated kinda like another item in autocomplete. --- src/PlacesAutocomplete.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 1de68018..b8a73dec 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -13,7 +13,7 @@ class PlacesAutocomplete extends Component { constructor(props) { super(props) - this.state = { autocompleteItems: [] } + this.state = { autocompleteItems: [], originalInputValue: '' } this.autocompleteCallback = this.autocompleteCallback.bind(this) this.handleInputKeyDown = this.handleInputKeyDown.bind(this) @@ -135,7 +135,18 @@ class PlacesAutocomplete extends Component { const activeItem = this.getActiveItem() if (activeItem === undefined) { + this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(0) + } else if ( + this.props.saveOriginalValue && + activeItem.index === this.state.autocompleteItems.length - 1 + ) { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + return activeItem.index === idx ? { ...item, active: false } : item + }), + }) + this.props.inputProps.onChange(this.state.originalInputValue) } else { const nextIndex = (activeItem.index + 1) % this.state.autocompleteItems.length @@ -150,7 +161,15 @@ class PlacesAutocomplete extends Component { const activeItem = this.getActiveItem() if (activeItem === undefined) { + this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + } else if (this.props.saveOriginalValue && activeItem.index === 0) { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + return activeItem.index === idx ? { ...item, active: false } : item + }), + }) + this.props.inputProps.onChange(this.state.originalInputValue) } else { let prevIndex if (activeItem.index === 0) { @@ -364,6 +383,7 @@ PlacesAutocomplete.propTypes = { highlightFirstSuggestion: PropTypes.bool, renderFooter: PropTypes.func, shouldFetchSuggestions: PropTypes.func.isRequired, + saveOriginalValue: PropTypes.bool, } PlacesAutocomplete.defaultProps = { @@ -379,6 +399,7 @@ PlacesAutocomplete.defaultProps = { debounce: 200, highlightFirstSuggestion: false, shouldFetchSuggestions: () => true, + saveOriginalValue: false, } export default PlacesAutocomplete From f7a88adb1891983686d0fa93fe26c23fbf113534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Pierzcha=C5=82a?= Date: Fri, 8 Dec 2017 21:01:48 +0100 Subject: [PATCH 089/165] add test cases for saveOriginalValue prop Last test case uses `onChange` function to check if during changing input's value it was called with appropriate value. Checking directly for input value yields default (passed by inputProps) text even after selecting another entry from autocomplete. --- src/tests/index.spec.js | 102 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index d5de213a..f85b0be7 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -341,5 +341,107 @@ describe('autoFocus prop', () => { }) }) +describe('saveOriginalValue prop', () => { + const data = [ + { + suggestion: 'San Francisco, CA', + placeId: 1, + active: false, + index: 0, + }, + { + suggestion: 'San Jose, CA', + placeId: 2, + active: false, + index: 1, + }, + { + suggestion: 'San Diego, CA', + placeId: 3, + active: false, + index: 2, + }, + ] + const spy = sinon.spy() + const inputProps = { + value: 'san', + onChange: spy, + } + let wrapper + + beforeEach(() => { + wrapper = shallow( + + ) + spy.reset() + }) + + it('save value of input when pressing arrow down key and none of autocomplete entries is being focused', () => { + wrapper.setState({ autocompleteItems: data }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + expect(wrapper.state().originalInputValue).to.equal('san') + }) + + it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { + wrapper.setState({ autocompleteItems: data }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }) + expect(wrapper.state().originalInputValue).to.equal('san') + }) + + it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { + const lastItemActive = data.map((item, idx) => { + return idx === data.length - 1 ? { ...item, active: true } : item + }) + wrapper.setState({ autocompleteItems: lastItemActive }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + wrapper.state().autocompleteItems.forEach(item => { + expect(item.active).to.be.false + }) + }) + + it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { + const firstItemActive = data.map((item, idx) => { + return idx === 0 ? { ...item, active: true } : item + }) + wrapper.setState({ autocompleteItems: firstItemActive }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }) + wrapper.state().autocompleteItems.forEach(item => { + expect(item.active).to.be.false + }) + }) + + it('onChange function is called with appropriate value', () => { + // Amount of entries is 3 for this test case, so when we press arrow down fourth time + // we expect onChange function to be called with original input value + // being stored in `originalInputValue` state entry + // rest of calls should be called with appropraite entries from autocomplete items + wrapper.setState({ autocompleteItems: data }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + wrapper + .instance() + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion) + expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion) + expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion) + expect(spy.getCall(3).args[0]).to.equal(wrapper.state().originalInputValue) + }) +}) + // TODOs: // * Test geocodeByAddress function From c64f3ab03420fd5c54f920bd1c8b5fa643d2683c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Pierzcha=C5=82a?= Date: Fri, 8 Dec 2017 21:10:26 +0100 Subject: [PATCH 090/165] add description in readme for saveOriginalValue prop --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 507dc5c6..e6a5dc9f 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ export default SimpleForm |[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | | [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | |[`shouldFetchSuggestions`](#shouldFetchSuggestions)| function | | Component will fetch suggestions from Google Maps API only when this function returns `true` | - +| [`saveOriginalValue`](#saveOriginalValue) | boolean | | Original entry in input will be included when iterating over autocomplete's entries | #### inputProps @@ -183,7 +183,7 @@ render() { Type: `Functional React Component` Required: `false` -You can provide a component that will get rendered at the bottom of dropdown. +You can provide a component that will get rendered at the bottom of dropdown. For example, you can provide a component to show "Powered by Google" logo. ```js @@ -236,7 +236,7 @@ Now you can easily apply custom CSS styles using the classNames! Type `Object`, Required: `false` -You can provide custom inline styles to elements. +You can provide custom inline styles to elements. Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. ```js @@ -323,7 +323,7 @@ Type: `Function` Required: `false` Deafult: `noop` -You can pass a callback function that gets called when pressing down Enter key when no item in the dropdown is selected. +You can pass a callback function that gets called when pressing down Enter key when no item in the dropdown is selected. The function takes one argument, the value in the input field. ```js @@ -413,7 +413,7 @@ Type: `Function` Required: `false` Default: `() => true` -You can pass a function to tell when to fetch suggestions from Google Maps API. +You can pass a function to tell when to fetch suggestions from Google Maps API. It takes an input `{ value }` and should return a boolean. ```js @@ -427,6 +427,16 @@ const shouldFetchSuggestions = ({ value }) => value.length > 3 /> ``` + +#### saveOriginalValue +Type: `Boolean` +Required: `false` +Default: `false` + +Enables using original input's value as it was another entry in autocomplete. Original value is saved when no entry is chosen and we select one of them. +When last/first entry is focused and you're about to press arrow down/up, instead of wrapping up (choosing first/last entry) input is being populated with original value. +That way it looks like as if original input value was just another entry in autocomplete, albeit hidden. + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) From fac72e04f19725015ad662d37348e825c5395153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Pierzcha=C5=82a?= Date: Sat, 3 Feb 2018 17:44:52 +0100 Subject: [PATCH 091/165] make `saveOriginal` prop default behaviour --- README.md | 11 ----------- src/PlacesAutocomplete.js | 9 ++------- src/tests/index.spec.js | 4 ++-- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e6a5dc9f..99f2b3df 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,6 @@ export default SimpleForm |[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | | [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | |[`shouldFetchSuggestions`](#shouldFetchSuggestions)| function | | Component will fetch suggestions from Google Maps API only when this function returns `true` | -| [`saveOriginalValue`](#saveOriginalValue) | boolean | | Original entry in input will be included when iterating over autocomplete's entries | #### inputProps @@ -427,16 +426,6 @@ const shouldFetchSuggestions = ({ value }) => value.length > 3 /> ``` - -#### saveOriginalValue -Type: `Boolean` -Required: `false` -Default: `false` - -Enables using original input's value as it was another entry in autocomplete. Original value is saved when no entry is chosen and we select one of them. -When last/first entry is focused and you're about to press arrow down/up, instead of wrapping up (choosing first/last entry) input is being populated with original value. -That way it looks like as if original input value was just another entry in autocomplete, albeit hidden. - ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index b8a73dec..9ca2b0ca 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -137,10 +137,7 @@ class PlacesAutocomplete extends Component { if (activeItem === undefined) { this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(0) - } else if ( - this.props.saveOriginalValue && - activeItem.index === this.state.autocompleteItems.length - 1 - ) { + } else if (activeItem.index === this.state.autocompleteItems.length - 1) { this.setState({ autocompleteItems: this.state.autocompleteItems.map((item, idx) => { return activeItem.index === idx ? { ...item, active: false } : item @@ -163,7 +160,7 @@ class PlacesAutocomplete extends Component { if (activeItem === undefined) { this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) - } else if (this.props.saveOriginalValue && activeItem.index === 0) { + } else if (activeItem.index === 0) { this.setState({ autocompleteItems: this.state.autocompleteItems.map((item, idx) => { return activeItem.index === idx ? { ...item, active: false } : item @@ -383,7 +380,6 @@ PlacesAutocomplete.propTypes = { highlightFirstSuggestion: PropTypes.bool, renderFooter: PropTypes.func, shouldFetchSuggestions: PropTypes.func.isRequired, - saveOriginalValue: PropTypes.bool, } PlacesAutocomplete.defaultProps = { @@ -399,7 +395,6 @@ PlacesAutocomplete.defaultProps = { debounce: 200, highlightFirstSuggestion: false, shouldFetchSuggestions: () => true, - saveOriginalValue: false, } export default PlacesAutocomplete diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index f85b0be7..15690541 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -341,7 +341,7 @@ describe('autoFocus prop', () => { }) }) -describe('saveOriginalValue prop', () => { +describe('Enables using original input\'s value as it was another entry in autocomplete', () => { const data = [ { suggestion: 'San Francisco, CA', @@ -371,7 +371,7 @@ describe('saveOriginalValue prop', () => { beforeEach(() => { wrapper = shallow( - + ) spy.reset() }) From c9b98f8cb903b5ea795ff9649c39e9ddfed16955 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 4 Feb 2018 12:44:27 -0800 Subject: [PATCH 092/165] feat(inputValue): Save user input value and display it when no items in the dropdown is selected --- src/PlacesAutocomplete.js | 48 +++++++++++++++++++-------------------- src/tests/index.spec.js | 8 +++---- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 9ca2b0ca..d962a490 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -13,7 +13,10 @@ class PlacesAutocomplete extends Component { constructor(props) { super(props) - this.state = { autocompleteItems: [], originalInputValue: '' } + this.state = { + autocompleteItems: [], + userInputValue: props.inputProps.value, + } this.autocompleteCallback = this.autocompleteCallback.bind(this) this.handleInputKeyDown = this.handleInputKeyDown.bind(this) @@ -84,6 +87,15 @@ class PlacesAutocomplete extends Component { this.setState({ autocompleteItems: [] }) } + clearActive() { + this.setState({ + autocompleteItems: this.state.autocompleteItems.map(item => ({ + ...item, + active: false, + })), + }) + } + selectAddress(address, placeId, e) { if (e !== undefined) { e.preventDefault() @@ -110,6 +122,11 @@ class PlacesAutocomplete extends Component { this.props.inputProps.onChange(activeName) } + selectUserInputValue() { + this.clearActive() + this.props.inputProps.onChange(this.state.userInputValue) + } + handleEnterKey() { const activeItem = this.getActiveItem() if (activeItem === undefined) { @@ -135,19 +152,11 @@ class PlacesAutocomplete extends Component { const activeItem = this.getActiveItem() if (activeItem === undefined) { - this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(0) } else if (activeItem.index === this.state.autocompleteItems.length - 1) { - this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { - return activeItem.index === idx ? { ...item, active: false } : item - }), - }) - this.props.inputProps.onChange(this.state.originalInputValue) + this.selectUserInputValue() } else { - const nextIndex = - (activeItem.index + 1) % this.state.autocompleteItems.length - this.selectActiveItemAtIndex(nextIndex) + this.selectActiveItemAtIndex(activeItem.index + 1) } } @@ -158,23 +167,11 @@ class PlacesAutocomplete extends Component { const activeItem = this.getActiveItem() if (activeItem === undefined) { - this.setState({ originalInputValue: this.props.inputProps.value }) this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) } else if (activeItem.index === 0) { - this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { - return activeItem.index === idx ? { ...item, active: false } : item - }), - }) - this.props.inputProps.onChange(this.state.originalInputValue) + this.selectUserInputValue() } else { - let prevIndex - if (activeItem.index === 0) { - prevIndex = this.state.autocompleteItems.length - 1 - } else { - prevIndex = (activeItem.index - 1) % this.state.autocompleteItems.length - } - this.selectActiveItemAtIndex(prevIndex) + this.selectActiveItemAtIndex(activeItem.index - 1) } } @@ -217,6 +214,7 @@ class PlacesAutocomplete extends Component { handleInputChange(event) { const { value } = event.target this.props.inputProps.onChange(value) + this.setState({ userInputValue: value }) if (!value) { this.clearSuggestions() return diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 15690541..947025a2 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -381,7 +381,7 @@ describe('Enables using original input\'s value as it was another entry in autoc wrapper .instance() .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) - expect(wrapper.state().originalInputValue).to.equal('san') + expect(wrapper.state().userInputValue).to.equal('san') }) it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { @@ -389,7 +389,7 @@ describe('Enables using original input\'s value as it was another entry in autoc wrapper .instance() .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }) - expect(wrapper.state().originalInputValue).to.equal('san') + expect(wrapper.state().userInputValue).to.equal('san') }) it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { @@ -421,7 +421,7 @@ describe('Enables using original input\'s value as it was another entry in autoc it('onChange function is called with appropriate value', () => { // Amount of entries is 3 for this test case, so when we press arrow down fourth time // we expect onChange function to be called with original input value - // being stored in `originalInputValue` state entry + // being stored in `userInputValue` state entry // rest of calls should be called with appropraite entries from autocomplete items wrapper.setState({ autocompleteItems: data }) wrapper @@ -439,7 +439,7 @@ describe('Enables using original input\'s value as it was another entry in autoc expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion) expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion) expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion) - expect(spy.getCall(3).args[0]).to.equal(wrapper.state().originalInputValue) + expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue) }) }) From c01274722e86e684d939daf5795f393aa5d91305 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 4 Feb 2018 12:47:19 -0800 Subject: [PATCH 093/165] chore(prettier): Run code formatter --- src/tests/index.spec.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 947025a2..5e931494 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -341,7 +341,7 @@ describe('autoFocus prop', () => { }) }) -describe('Enables using original input\'s value as it was another entry in autocomplete', () => { +describe("Enables using original input's value as it was another entry in autocomplete", () => { const data = [ { suggestion: 'San Francisco, CA', @@ -370,9 +370,7 @@ describe('Enables using original input\'s value as it was another entry in autoc let wrapper beforeEach(() => { - wrapper = shallow( - - ) + wrapper = shallow() spy.reset() }) From a6415615e527116c2923c86fe19aa29f8ad7ebe8 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 4 Feb 2018 12:52:48 -0800 Subject: [PATCH 094/165] v6.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4eb3a289..76fdf06a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.0.2", + "version": "6.1.0", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From ed5e2d9d059011db748ef6c546124ca1aa0ae852 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 7 Feb 2018 21:16:21 -0800 Subject: [PATCH 095/165] chore(demo): Refactor Demo --- demo/Demo.js | 207 +++++------------------------------ demo/components/SearchBar.js | 144 ++++++++++++++++++++++++ demo/index.js | 2 +- 3 files changed, 172 insertions(+), 181 deletions(-) create mode 100644 demo/components/SearchBar.js diff --git a/demo/Demo.js b/demo/Demo.js index f7d6f4b0..e0675377 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -1,183 +1,30 @@ import React from 'react' -import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../src' - -class Demo extends React.Component { - constructor(props) { - super(props) - this.state = { - address: '', - geocodeResults: null, - loading: false, - } - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) - this.renderGeocodeFailure = this.renderGeocodeFailure.bind(this) - this.renderGeocodeSuccess = this.renderGeocodeSuccess.bind(this) - } - - handleSelect(address) { - this.setState({ - address, - loading: true, - }) - - geocodeByAddress(address) - .then(results => getLatLng(results[0])) - .then(({ lat, lng }) => { - console.log('Success Yay', { lat, lng }) - this.setState({ - geocodeResults: this.renderGeocodeSuccess(lat, lng), - loading: false, - }) - }) - .catch(error => { - console.log('Oh no!', error) - this.setState({ - geocodeResults: this.renderGeocodeFailure(error), - loading: false, - }) - }) - - /* NOTE: Using callback (Deprecated version) */ - // geocodeByAddress(address, (err, { lat, lng }) => { - // if (err) { - // console.log('Oh no!', err) - // this.setState({ - // geocodeResults: this.renderGeocodeFailure(err), - // loading: false - // }) - // } - // console.log(`Yay! got latitude and longitude for ${address}`, { lat, lng }) - // this.setState({ - // geocodeResults: this.renderGeocodeSuccess(lat, lng), - // loading: false - // }) - // }) - } - - handleChange(address) { - this.setState({ - address, - geocodeResults: null, - }) - } - - renderGeocodeFailure(err) { - return ( -
- Error! {err} -
- ) - } - - renderGeocodeSuccess(lat, lng) { - return ( -
- Success! Geocoder found latitude and longitude:{' '} - - {lat}, {lng} - -
- ) - } - - render() { - const cssClasses = { - root: 'form-group', - input: 'Demo__search-input', - autocompleteContainer: 'Demo__autocomplete-container', - } - - const AutocompleteItem = ({ formattedSuggestion }) => ( -
- - {formattedSuggestion.mainText}{' '} - - {formattedSuggestion.secondaryText} - -
- ) - - const Footer = () => ( -
-
- -
-
- ) - - const inputProps = { - type: 'text', - value: this.state.address, - onChange: this.handleChange, - onBlur: () => { - console.log('Blur event!') - }, - onFocus: () => { - console.log('Focused!') - }, - autoFocus: true, - placeholder: 'Search Places', - name: 'Demo__input', - id: 'my-input-id', - } - - const shouldFetchSuggestions = ({ value }) => value.length > 2 - - const onError = (status, clearSuggestions) => { - console.log( - 'Error happened while fetching suggestions from Google Maps API', - status - ) - clearSuggestions() - } - - return ( -
-
-

- react-places-autocomplete -

-

- A React component to build a customized UI for Google Maps Places - Autocomplete -

-
- - -  View on GitHub - -
-
- - {this.state.loading ? ( -
- -
- ) : null} - {!this.state.loading && this.state.geocodeResults ? ( -
{this.state.geocodeResults}
- ) : null} -
-
- ) - } -} +import SearchBar from './components/SearchBar' + +const Demo = () => ( +
+
+

+ react-places-autocomplete +

+

+ A React component to build a customized UI for Google Maps Places + Autocomplete +

+
+ + +  View on GitHub + +
+
+ +
+
+) export default Demo diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js new file mode 100644 index 00000000..bc0e8c9f --- /dev/null +++ b/demo/components/SearchBar.js @@ -0,0 +1,144 @@ +import React, { Component } from 'react' +import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src' + +const renderSuggestion = ({ formattedSuggestion }) => ( +
+ + {formattedSuggestion.mainText}{' '} + {formattedSuggestion.secondaryText} +
+) + +const renderFooter = () => ( +
+
+ +
+
+) + +const cssClasses = { + root: 'form-group', + input: 'Demo__search-input', + autocompleteContainer: 'Demo__autocomplete-container', +} + +const shouldFetchSuggestions = ({ value }) => value.length > 2 + +const onError = (status, clearSuggestions) => { + console.log( + 'Error happened while fetching suggestions from Google Maps API', + status + ) + clearSuggestions() +} + +class SearchBar extends Component { + constructor(props) { + super(props) + this.state = { + address: '', + geocodeResults: null, + loading: false, + } + + this.handleSelect = this.handleSelect.bind(this) + this.handleChange = this.handleChange.bind(this) + } + + handleSelect(address) { + this.setState({ + address, + loading: true, + }) + + geocodeByAddress(address) + .then(results => getLatLng(results[0])) + .then(({ lat, lng }) => { + console.log('Geocode Success', { lat, lng }) + this.setState({ + geocodeResults: this.renderGeocodeSuccess(lat, lng), + loading: false, + }) + }) + .catch(error => { + console.log('Geocode Error', error) + this.setState({ + geocodeResults: this.renderGeocodeFailure(error), + loading: false, + }) + }) + } + + handleChange(address) { + this.setState({ + address, + geocodeResults: null, + }) + } + + renderGeocodeFailure(err) { + return ( +
+ Error! {err} +
+ ) + } + + renderGeocodeSuccess(lat, lng) { + return ( +
+ Success! Geocoder found latitude and longitude:{' '} + + {lat}, {lng} + +
+ ) + } + + render() { + const inputProps = { + type: 'text', + value: this.state.address, + onChange: this.handleChange, + onBlur: () => { + console.log('Blur event!') + }, + onFocus: () => { + console.log('Focused!') + }, + autoFocus: true, + placeholder: 'Search Places', + name: 'Demo__input', + id: 'my-input-id', + } + + return ( +
+ + {this.state.loading && ( +
+ +
+ )} + {this.state.geocodeResults && ( +
{this.state.geocodeResults}
+ )} +
+ ) + } +} + +export default SearchBar diff --git a/demo/index.js b/demo/index.js index ceed2391..25a60d85 100644 --- a/demo/index.js +++ b/demo/index.js @@ -2,4 +2,4 @@ import React from 'react' import ReactDOM from 'react-dom' import Demo from './Demo' -ReactDOM.render(React.createElement(Demo, {}), document.getElementById('app')) +ReactDOM.render(, document.getElementById('app')) From 193a44963e83341131911c51afcd12b386d79662 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 10 Feb 2018 13:45:15 -0800 Subject: [PATCH 096/165] fix(mobile): Fix mobile scroll touch event handler --- src/PlacesAutocomplete.js | 41 ++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d962a490..da15f2e8 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -225,7 +225,9 @@ class PlacesAutocomplete extends Component { } handleInputOnBlur(event) { - this.clearSuggestions() + if (!this.mousedownOnSuggestion) { + this.clearSuggestions() + } if (this.props.inputProps.onBlur) { this.props.inputProps.onBlur(event) @@ -280,6 +282,30 @@ class PlacesAutocomplete extends Component { } } + handleSuggestionMouseEnter(index) { + this.setActiveItemAtIndex(index) + } + + handleSuggestionMouseLeave() { + this.clearActive() + } + + handleSuggestionMouseDown() { + this.mousedownOnSuggestion = true + } + + handleSuggestionMouseUp() { + this.mousedownOnSuggestion = false + } + + handleSuggestionClick(prediction, event) { + const { suggestion, placeId } = prediction + this.selectAddress(suggestion, placeId, event) + setTimeout(() => { + this.mousedownOnSuggestion = false + }) + } + render() { const { autocompleteItems } = this.state const inputProps = this.getInputProps() @@ -300,12 +326,13 @@ class PlacesAutocomplete extends Component { {autocompleteItems.map((p, idx) => (
this.setActiveItemAtIndex(p.index)} - onMouseDown={e => - this.selectAddress(p.suggestion, p.placeId, e) - } - onTouchStart={() => this.setActiveItemAtIndex(p.index)} - onTouchEnd={e => this.selectAddress(p.suggestion, p.placeId, e)} + onMouseEnter={this.handleSuggestionMouseEnter.bind(this, idx)} + onMouseLeave={this.handleSuggestionMouseLeave.bind(this)} + onMouseDown={this.handleSuggestionMouseDown.bind(this)} + onMouseUp={this.handleSuggestionMouseUp.bind(this)} + onTouchStart={this.handleSuggestionMouseDown.bind(this)} // iOS doesn't trigger 'onMouseDown' + onTouchEnd={this.handleSuggestionMouseUp.bind(this)} + onClick={this.handleSuggestionClick.bind(this, p)} style={ p.active ? this.inlineStyleFor( From e42bed1961a90d2a279510dfdf9000a0180dbd4b Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 10 Feb 2018 14:00:22 -0800 Subject: [PATCH 097/165] v6.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 76fdf06a..c4d53759 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.1.0", + "version": "6.1.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 14f8c90a1f46c20fbf20e83cbc6466656a6f2d78 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Feb 2018 19:00:10 -0800 Subject: [PATCH 098/165] fix(browser): Fix issue with dragging suggestion --- src/PlacesAutocomplete.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index da15f2e8..c00a4140 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -287,10 +287,16 @@ class PlacesAutocomplete extends Component { } handleSuggestionMouseLeave() { + this.mousedownOnSuggestion = false this.clearActive() } - handleSuggestionMouseDown() { + handleSuggestionMouseDown(event) { + event.preventDefault() + this.mousedownOnSuggestion = true + } + + handleSuggestionTouchStart() { this.mousedownOnSuggestion = true } @@ -330,7 +336,7 @@ class PlacesAutocomplete extends Component { onMouseLeave={this.handleSuggestionMouseLeave.bind(this)} onMouseDown={this.handleSuggestionMouseDown.bind(this)} onMouseUp={this.handleSuggestionMouseUp.bind(this)} - onTouchStart={this.handleSuggestionMouseDown.bind(this)} // iOS doesn't trigger 'onMouseDown' + onTouchStart={this.handleSuggestionTouchStart.bind(this)} onTouchEnd={this.handleSuggestionMouseUp.bind(this)} onClick={this.handleSuggestionClick.bind(this, p)} style={ From 6b421bea546ddf5005e305ee57e984cdebad11b2 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Feb 2018 19:57:08 -0800 Subject: [PATCH 099/165] v6.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4d53759..2c99c335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.1.1", + "version": "6.1.2", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From ef5a2221481f7710c03fc1e962bcd886f949a481 Mon Sep 17 00:00:00 2001 From: codetriage-readme-bot Date: Mon, 12 Feb 2018 15:06:38 -0600 Subject: [PATCH 100/165] Add CodeTriage badge to kenny-hibino/react-places-autocomplete Adds a badge showing the number of people helping this repo on CodeTriage. [![Open Source Helpers](https://www.codetriage.com/kenny-hibino/react-places-autocomplete/badges/users.svg)](https://www.codetriage.com/kenny-hibino/react-places-autocomplete) ## What is CodeTriage? CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed [Read more about the CodeTriage project](https://www.codetriage.com/what). ## Why am I getting this PR? Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 7 months ago, [kenny-hibino](https://github.com/kenny-hibino) added this project to CodeTriage in order to start contributing. Since then, 2 people have subscribed to help this repo. ## What does adding a badge accomplish? Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project. You can see an example of a CodeTriage badge on these popular OSS READMEs: - [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails - [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal ## Have a question or comment? While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics. If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again. Thanks for making your project Open Source! Any feedback is greatly appreciated. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 99f2b3df..ebf9530f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![travis build](https://img.shields.io/travis/kenny-hibino/react-places-autocomplete.svg?style=flat-square)](https://travis-ci.org/kenny-hibino/react-places-autocomplete) [![MIT-License](https://img.shields.io/npm/l/react-places-autocomplete.svg?style=flat-square)]() [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/react-places-autocomplete/Lobby) +[![Open Source Helpers](https://www.codetriage.com/kenny-hibino/react-places-autocomplete/badges/users.svg)](https://www.codetriage.com/kenny-hibino/react-places-autocomplete) # React Places Autocomplete From 5e96eb78ab62fca1a1987fd2f5c940f851239f25 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 3 Mar 2018 16:38:00 -0800 Subject: [PATCH 101/165] fix(wai-aria): Make sure WAI-ARIA complicance --- src/PlacesAutocomplete.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index c00a4140..d2f72588 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -259,10 +259,23 @@ class PlacesAutocomplete extends Component { }, '') } + shouldRenderDropdown() { + return this.state.autocompleteItems.length > 0 + } + getInputProps() { + const isExpanded = this.shouldRenderDropdown() + const activeItem = this.getActiveItem() + const activeItemId = activeItem ? `PlacesAutocomplete__autocomplete-item-${activeItem.placeId}` : null const defaultInputProps = { type: 'text', autoComplete: 'off', + role: 'combobox', + 'aria-autocomplete': 'list', + 'aria-controls': "PlacesAutocomplete__autocomplete-container", + 'aria-expanded': isExpanded, + 'aria-haspopup': isExpanded, + 'aria-activedescendant': activeItemId, } return { @@ -323,8 +336,9 @@ class PlacesAutocomplete extends Component { className={this.classNameFor('root')} > - {autocompleteItems.length > 0 && ( + {this.shouldRenderDropdown() && (
(
From 142a872e30ccaca2a4796a511732508114e7e115 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 3 Mar 2018 16:42:31 -0800 Subject: [PATCH 102/165] docs(readme): Update readme features section --- README.md | 4 +++- src/PlacesAutocomplete.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99f2b3df..9b674ede 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) 2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) -3. Pass through arbitrary props to the input element to integrate well with other libraries (e.g. Redux-Form) +3. Pass through arbitrary props to the input element to integrate well with other libraries (e.g. Redux-Form) +4. Mobile friendly UX +5. WAI-ARIA compliant ### Installation To install the stable version diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d2f72588..4a5e51f1 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017 Ken Hibino. +* Copyright (c) 2016-present, Ken Hibino. * Licensed under the MIT License (MIT). * See https://kenny-hibino.github.io/react-places-autocomplete */ From 437113dcb523aecacc3241bfbb64c4feef996a2e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 3 Mar 2018 16:47:05 -0800 Subject: [PATCH 103/165] v6.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2c99c335..f8f2cc03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.1.2", + "version": "6.1.3", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From d7f7bb5e33a7773c362592bdb72a17e764588493 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 4 Mar 2018 09:24:26 -0800 Subject: [PATCH 104/165] Create ISSUE_TEMPLATE.md --- ISSUE_TEMPLATE.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..853d8f8e --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,9 @@ +**Do you want to request a *feature* or report a *bug*?** + +**What is the current behavior?** + +**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.** + +**What is the expected behavior?** + +**Which versions of ReactPlacesAutocomplete, and which browser / OS are affected by this issue?** From 8189652e5eaf47a7e1894650253c1f8ed2a47120 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 4 Mar 2018 09:30:57 -0800 Subject: [PATCH 105/165] docs(github): Add templates for Github issues and pull requests --- ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md | 0 .github/PULL_REQUEST_TEMPLATE.md | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+) rename ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md (100%) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..faa85d8c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +*Before* submitting a pull request, please make sure the following is done... + +1. Fork the repo and create your branch from `master`. +2. If you've added code that should be tested, add tests! +3. If you've changed APIs, update the documentation. +4. Ensure that: + * The test suite passes (`npm test`) + * Write formatted git commits by using `npm run commit` + +Please use the simple form below as a guideline for describing your pull request. + +Thanks for contributing! + +- + +**Summary** + +[...] From 4eef2bb52cf293f8375b839578b4d1f4905b8f4c Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 14:29:43 -0700 Subject: [PATCH 106/165] chore(eslint): Add eslint as a dev dependency --- .eslintrc.json | 36 ++++++++++++++++++++++++++++++++++++ package.json | 5 ++++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..f0731c89 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "env": { + "browser": true, + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + }, + "sourceType": "module" + }, + "plugins": [ + "react" + ], + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + } +} \ No newline at end of file diff --git a/package.json b/package.json index f8f2cc03..72afd898 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", "demo:deploy": "gh-pages -d demo/dist", "postpublish": "npm run demo:deploy", - "prettier": "prettier --no-semi --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"" + "prettier": "prettier --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"", + "lint": "eslint src/**/*.js demo/**/*.js" }, "repository": { "type": "git", @@ -67,6 +68,8 @@ "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", "enzyme": "2.4.1", + "eslint": "4.18.2", + "eslint-plugin-react": "7.7.0", "file-loader": "0.11.2", "gh-pages": "^0.12.0", "ghooks": "1.3.2", From b8f0305a8c253fae72a22667cbe587069c3a32d1 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 14:30:16 -0700 Subject: [PATCH 107/165] chore(lockfile): Add package-lock.json --- package-lock.json | 15986 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 15986 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..87827751 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,15986 @@ +{ + "name": "react-places-autocomplete", + "version": "6.1.3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@semantic-release/commit-analyzer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-2.0.0.tgz", + "integrity": "sha1-kk0eLDAWfGpHK+2fZu6Pjgd0ibI=", + "dev": true, + "requires": { + "conventional-changelog": "0.0.17" + } + }, + "@semantic-release/condition-travis": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@semantic-release/condition-travis/-/condition-travis-4.1.4.tgz", + "integrity": "sha1-1d5qyheBlCDfwy7VQilal/l3+WM=", + "dev": true, + "requires": { + "@semantic-release/error": "1.0.0", + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "@semantic-release/error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-1.0.0.tgz", + "integrity": "sha1-u4+O7t1cf4xG+Ws37znhuMN2wcw=", + "dev": true + }, + "@semantic-release/last-release-npm": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@semantic-release/last-release-npm/-/last-release-npm-1.2.1.tgz", + "integrity": "sha1-/3SBQuzxU1S4M6hroYIF9/zllO4=", + "dev": true, + "requires": { + "@semantic-release/error": "1.0.0", + "npm-registry-client": "7.5.0", + "npmlog": "1.2.1" + } + }, + "@semantic-release/release-notes-generator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-2.0.0.tgz", + "integrity": "sha1-fF2mVolGbVNqU/36n01io70TwW4=", + "dev": true, + "requires": { + "conventional-changelog": "0.0.17", + "github-url-from-git": "1.5.0" + } + }, + "abab": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", + "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", + "dev": true + }, + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true + }, + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", + "dev": true, + "requires": { + "mime-types": "2.1.11", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "dev": true, + "optional": true + }, + "acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "dev": true, + "requires": { + "acorn": "2.7.0" + }, + "dependencies": { + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + }, + "dependencies": { + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + } + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.0.3", + "longest": "1.0.1", + "repeat-string": "1.5.4" + } + }, + "amdefine": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz", + "integrity": "sha1-/RdHRwDLXMnCtwnwvp0jzjwZjDM=", + "dev": true + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "any-shell-escape": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/any-shell-escape/-/any-shell-escape-0.1.1.tgz", + "integrity": "sha1-1Vq5ciRMcaml4asIefML8RCAaVk=", + "dev": true + }, + "anymatch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz", + "integrity": "sha1-o+Uvo5FoyCX/V7AkgSbOWo/5VQc=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11" + } + }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", + "dev": true, + "optional": true + }, + "archive-type": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", + "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", + "dev": true, + "requires": { + "file-type": "3.9.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + } + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.1.4" + } + }, + "argparse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz", + "integrity": "sha1-wolQZIBVeBDxSovGLXoG9j7X+VE=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.0.1" + } + }, + "arr-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz", + "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.1.tgz", + "integrity": "sha1-C8Jd2slB7IpJauJY/UrBiAA+868=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + } + } + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.4.tgz", + "integrity": "sha1-s5G/f2v7xlcGAi/sj0nEsH/s9Yk=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-each-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", + "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz", + "integrity": "sha1-/efVKSRm0jDl7g9OA42d+qsI/GE=", + "dev": true + }, + "babel-cli": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.24.1.tgz", + "integrity": "sha1-IHzXBbumFImy6kG1MSNBz2rKIoM=", + "dev": true, + "requires": { + "babel-core": "6.24.1", + "babel-polyfill": "6.23.0", + "babel-register": "6.24.1", + "babel-runtime": "6.23.0", + "chokidar": "1.6.1", + "commander": "2.9.0", + "convert-source-map": "1.5.0", + "fs-readdir-recursive": "1.0.0", + "glob": "7.1.1", + "lodash": "4.17.4", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.0", + "slash": "1.0.0", + "source-map": "0.5.6", + "v8flags": "2.0.11" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + } + } + }, + "babel-core": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", + "integrity": "sha1-jEKFZNzh4fQfszfsNPTDsCK1rYM=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-generator": "6.24.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "convert-source-map": "1.5.0", + "debug": "2.2.0", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.2", + "path-is-absolute": "1.0.0", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.6" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", + "integrity": "sha1-5xX0hsWN7SVknYiJRNUqoHxdlJc=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.6", + "trim-right": "1.0.1" + }, + "dependencies": { + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", + "integrity": "sha1-CteRfjPI11HmRtrKTnfMGTd9LLw=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "esutils": "2.0.2" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-define-map": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", + "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "lodash": "4.17.4" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", + "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "lodash": "4.17.4" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-loader": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.4.1.tgz", + "integrity": "sha1-CzQRLVsHSKjc2/Uaz2+b1C1QuMo=", + "dev": true, + "requires": { + "find-cache-dir": "0.1.1", + "loader-utils": "0.2.17", + "mkdirp": "0.5.1", + "object-assign": "4.1.0" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.0.1", + "json5": "0.5.1", + "object-assign": "4.1.0" + } + } + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-react-transform": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz", + "integrity": "sha1-UVu/qZaJOYEULZCx+bFjXeKZUQk=", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.8.0.tgz", + "integrity": "sha1-2HLKNQhjNVt4QqtHyAlK/xLb68g=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.8.0.tgz", + "integrity": "sha1-LUKKhczx+1GHNidZoSIXueS0v3w=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", + "dev": true + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.8.0.tgz", + "integrity": "sha1-kbPads9BObh5wBuXLvfIjXrXqYA=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "dev": true, + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", + "dev": true, + "requires": { + "babel-plugin-syntax-do-expressions": "6.13.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", + "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "lodash": "4.17.4" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.24.1", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", + "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.24.1", + "babel-runtime": "6.23.0", + "regexpu-core": "2.0.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "dev": true, + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", + "dev": true, + "requires": { + "babel-plugin-syntax-function-bind": "6.13.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz", + "integrity": "sha1-Q5iRDDWEQdxM7xh4cmTQQS7Tazc=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.24.1", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.23.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.3.3.tgz", + "integrity": "sha1-0J9IualQOmnBztObOCXC9F0pMzw=", + "dev": true + }, + "babel-plugin-transform-regenerator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", + "integrity": "sha1-uNowWtQ8PJm0hI5P5AN7dw0jxBg=", + "dev": true, + "requires": { + "regenerator-transform": "0.9.11" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.24.1", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.24.1" + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-react-display-name": "6.23.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-self": "6.22.0", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-preset-flow": "6.23.0" + } + }, + "babel-preset-stage-0": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha1-VkLRUEL5E4TX5a+LyIsduVsDnmo=", + "dev": true, + "requires": { + "babel-plugin-transform-do-expressions": "6.22.0", + "babel-plugin-transform-function-bind": "6.22.0", + "babel-preset-stage-1": "6.24.1" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "dev": true, + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + }, + "dependencies": { + "babel-code-frame": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", + "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "esutils": "2.0.2", + "js-tokens": "3.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.23.0", + "babel-template": "6.24.1", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.8.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.8.0", + "babel-runtime": "6.23.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz", + "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.8.0", + "babel-runtime": "6.23.0" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.23.0" + } + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-template": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", + "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-traverse": "6.24.1", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", + "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", + "dev": true, + "requires": { + "babel-code-frame": "6.22.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "babylon": "6.16.1", + "debug": "2.2.0", + "globals": "9.17.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.16.1", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.16.1.tgz", + "integrity": "sha1-MMWiL0gZeKnn+M399JaxHZS0BNM=", + "dev": true + }, + "globals": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.17.0.tgz", + "integrity": "sha1-DAymltm5u2lNLlRwvTd3fKrVAoY=", + "dev": true + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-register": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", + "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", + "dev": true, + "requires": { + "babel-core": "6.24.1", + "babel-runtime": "6.23.0", + "core-js": "2.4.0", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.14" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz", + "integrity": "sha1-1/45G8LMKbgIfB2bOYeJEun8/Vk=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.9.5" + } + }, + "balanced-match": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz", + "integrity": "sha1-GQU+LgdI6ts3nabAnUVc9eEDkzU=", + "dev": true + }, + "base64-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", + "dev": true + }, + "batch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.5.3.tgz", + "integrity": "sha1-PzQU84AyF0O/wQQvmoP/HVgk1GQ=", + "dev": true + }, + "beeper": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.0.tgz", + "integrity": "sha1-nub8HOf1T+qs585zWIsFYDeGaiw=", + "dev": true + }, + "big.js": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz", + "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=", + "dev": true + }, + "bin-build": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", + "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", + "dev": true, + "requires": { + "archive-type": "3.2.0", + "decompress": "3.0.0", + "download": "4.4.3", + "exec-series": "1.0.3", + "rimraf": "2.5.3", + "tempfile": "1.1.1", + "url-regex": "3.2.0" + }, + "dependencies": { + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.1", + "uuid": "2.0.3" + } + } + } + }, + "bin-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", + "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", + "dev": true, + "requires": { + "executable": "1.1.0" + } + }, + "bin-version": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "dev": true, + "requires": { + "find-versions": "1.2.1" + } + }, + "bin-version-check": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "dev": true, + "requires": { + "bin-version": "1.0.4", + "minimist": "1.2.0", + "semver": "4.3.6", + "semver-truncate": "1.1.2" + } + }, + "bin-wrapper": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", + "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", + "dev": true, + "requires": { + "bin-check": "2.0.0", + "bin-version-check": "2.1.0", + "download": "4.4.3", + "each-async": "1.1.1", + "lazy-req": "1.1.0", + "os-filter-obj": "1.0.3" + } + }, + "binary-extensions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz", + "integrity": "sha1-SOyNFt9Dd+rl+liEaCSAr02Vx3Q=", + "dev": true + }, + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "requires": { + "readable-stream": "2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "integrity": "sha1-9bStV04st8zB64Pm/nm47K33pSY=", + "dev": true, + "requires": { + "balanced-match": "0.4.1", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browserify-aes": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", + "integrity": "sha1-BnFJtmjfMcS1hTPgLQHoBthgjiw=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.0", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "buffer-to-vinyl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", + "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", + "dev": true, + "requires": { + "file-type": "3.9.0", + "readable-stream": "2.1.4", + "uuid": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.3.0.tgz", + "integrity": "sha1-1baAoWW2IBc5rLYRVCqrwtjOsHA=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "caw": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", + "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", + "dev": true, + "requires": { + "get-proxy": "1.1.0", + "is-obj": "1.0.1", + "object-assign": "3.0.0", + "tunnel-agent": "0.4.3" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "deep-eql": "0.1.3", + "type-detect": "1.0.0" + } + }, + "chai-enzyme": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/chai-enzyme/-/chai-enzyme-0.5.0.tgz", + "integrity": "sha1-HvI2eWE0zuWoSDQgFph8j/dhXT8=", + "dev": true, + "requires": { + "html": "0.0.10", + "react-element-to-jsx-string": "3.1.0" + } + }, + "chalk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", + "integrity": "sha1-UJr7ZwZudJn36zU1x3RFdyri0Bk=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "cheerio": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", + "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.8.3", + "jsdom": "7.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "jsdom": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", + "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", + "dev": true, + "optional": true, + "requires": { + "abab": "1.0.3", + "acorn": "2.7.0", + "acorn-globals": "1.0.9", + "cssom": "0.3.1", + "cssstyle": "0.2.36", + "escodegen": "1.8.0", + "nwmatcher": "1.3.8", + "parse5": "1.5.1", + "request": "2.73.0", + "sax": "1.2.1", + "symbol-tree": "3.1.4", + "tough-cookie": "2.2.2", + "webidl-conversions": "2.0.1", + "whatwg-url-compat": "0.6.5", + "xml-name-validator": "2.0.1" + } + }, + "webidl-conversions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", + "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", + "dev": true, + "optional": true + } + } + }, + "chokidar": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", + "integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=", + "dev": true, + "requires": { + "anymatch": "1.3.0", + "async-each": "1.0.1", + "fsevents": "1.1.1", + "glob-parent": "2.0.0", + "inherits": "2.0.1", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.0", + "readdirp": "2.1.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "clap": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz", + "integrity": "sha1-WckP4+E3EEdG/xlGmiemNP9oyFc=", + "dev": true, + "requires": { + "chalk": "1.1.3" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + } + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", + "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.4.1" + } + }, + "code-point-at": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", + "integrity": "sha1-9psZLT99keOC5Lcb3bd4eGGasMY=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "collapse-white-space": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.0.tgz", + "integrity": "sha1-lMgJZgxWYYdPu1K8dNw1Ga/KkCM=", + "dev": true + }, + "collections": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "integrity": "sha1-HyMCay7zb5J+7MkB6ZxfDUj6M04=", + "dev": true, + "requires": { + "weak-map": "1.0.0" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "commitizen": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-2.8.2.tgz", + "integrity": "sha1-Kocr2tq0Q5jcQm1jKigjHTTNBdI=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cz-conventional-changelog": "1.1.6", + "dedent": "0.6.0", + "detect-indent": "4.0.0", + "find-node-modules": "1.0.1", + "find-root": "1.0.0", + "glob": "7.0.3", + "gulp": "3.9.1", + "gulp-git": "1.7.2", + "home-or-tmp": "2.0.0", + "inquirer": "1.0.3", + "lodash": "4.11.1", + "minimist": "1.2.0", + "shelljs": "0.5.3", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "glob": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", + "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "dev": true, + "requires": { + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.1", + "os-tmpdir": "1.0.1" + } + }, + "lodash": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.1.tgz", + "integrity": "sha1-oyEG644uyOgsJBYRQUdzyd8V+Lw=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.1" + } + } + } + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compressible": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.9.tgz", + "integrity": "sha1-baq04rWZwncN2eIeeokbHFp1VCU=", + "dev": true, + "requires": { + "mime-db": "1.25.0" + }, + "dependencies": { + "mime-db": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz", + "integrity": "sha1-wY29fHOl2/b0SgJNwNFloeexw5I=", + "dev": true + } + } + }, + "compression": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.6.2.tgz", + "integrity": "sha1-zOsSHsydCcUtetDDNQ6pPd1AK8M=", + "dev": true, + "requires": { + "accepts": "1.3.3", + "bytes": "2.3.0", + "compressible": "2.0.9", + "debug": "2.2.0", + "on-headers": "1.0.1", + "vary": "1.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.1.tgz", + "integrity": "sha1-87gKz54fSOOHXAaItBtsMWAu6hw=", + "dev": true, + "requires": { + "inherits": "2.0.1", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "dev": true, + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "connect-history-api-fallback": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz", + "integrity": "sha1-5R0X+PDvDbkKZP20feMFFVbp8Wk=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "console-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", + "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", + "integrity": "sha1-h0dsamfI2qh+Muh2Ft+IO6f7Bxs=", + "dev": true + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "conventional-changelog": { + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-0.0.17.tgz", + "integrity": "sha1-XgIWYA9GhhkPDILvuws90RtJzjQ=", + "dev": true, + "requires": { + "dateformat": "1.0.12", + "event-stream": "3.3.3", + "github-url-from-git": "1.5.0", + "lodash": "3.10.1", + "normalize-package-data": "1.0.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "normalize-package-data": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-1.0.3.tgz", + "integrity": "sha1-i+lVuJB6+XXxpFhOqLubQUkjEvU=", + "dev": true, + "requires": { + "github-url-from-git": "1.5.0", + "github-url-from-username-repo": "1.0.2", + "semver": "4.3.6" + } + } + } + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.0.1.tgz", + "integrity": "sha1-lyjjg7lDFgUNDHRjlY8rhcCqggA=", + "dev": true, + "requires": { + "bluebird": "2.11.0", + "fs-extra": "0.26.7", + "glob": "6.0.4", + "is-glob": "3.1.0", + "loader-utils": "0.2.15", + "lodash": "4.17.4", + "minimatch": "3.0.2", + "node-dir": "0.1.16" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "core-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz", + "integrity": "sha1-30CKtG0Br/kcAcPnlxk11CLFT4E=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "create-react-class": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz", + "integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ=", + "dev": true, + "requires": { + "fbjs": "0.8.14", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "cross-spawn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz", + "integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=", + "dev": true, + "requires": { + "lru-cache": "4.0.1", + "which": "1.2.10" + }, + "dependencies": { + "lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.0.0" + } + } + } + }, + "cross-spawn-async": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.4.tgz", + "integrity": "sha1-yajY6aBlAsekYpbjOhoFS10vGBI=", + "dev": true, + "requires": { + "lru-cache": "4.0.1", + "which": "1.2.10" + }, + "dependencies": { + "lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.0.0" + } + } + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-browserify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.3.0.tgz", + "integrity": "sha1-ufx1u0oO1h3PHNXa6W6zDJw+UGw=", + "dev": true, + "requires": { + "browserify-aes": "0.4.0", + "pbkdf2-compat": "2.0.1", + "ripemd160": "0.2.0", + "sha.js": "2.2.6" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "dev": true, + "requires": { + "clap": "1.2.0", + "source-map": "0.5.6" + } + }, + "cssom": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.1.tgz", + "integrity": "sha1-yeN+8kkOZPbRuqEP2oUiVwgsJdM=", + "dev": true + }, + "cssstyle": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.36.tgz", + "integrity": "sha1-XP7WsaRSa1jXdnPVGzUghW+2rz4=", + "dev": true, + "requires": { + "cssom": "0.3.1" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.1" + } + }, + "cz-conventional-changelog": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-1.1.6.tgz", + "integrity": "sha1-a0MQH59Jbi/lPiQ6ZYCSCqw5X6s=", + "dev": true, + "requires": { + "word-wrap": "1.1.0" + } + }, + "dashdash": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decompress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", + "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", + "dev": true, + "requires": { + "buffer-to-vinyl": "1.1.0", + "concat-stream": "1.5.1", + "decompress-tar": "3.1.0", + "decompress-tarbz2": "3.1.0", + "decompress-targz": "3.1.0", + "decompress-unzip": "3.4.0", + "stream-combiner2": "1.1.1", + "vinyl-assign": "1.2.1", + "vinyl-fs": "2.4.4" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.0", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.1.4" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.4", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.0", + "readable-stream": "2.1.4", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.1", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + } + } + } + }, + "decompress-tar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", + "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", + "dev": true, + "requires": { + "is-tar": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.4", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-tarbz2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", + "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", + "dev": true, + "requires": { + "is-bzip2": "1.0.0", + "object-assign": "2.1.1", + "seek-bzip": "1.0.5", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.4", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-targz": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", + "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", + "dev": true, + "requires": { + "is-gzip": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.4", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-unzip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", + "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", + "dev": true, + "requires": { + "is-zip": "1.0.0", + "read-all-stream": "3.1.0", + "stat-mode": "0.2.2", + "strip-dirs": "1.1.1", + "through2": "2.0.1", + "vinyl": "1.2.0", + "yauzl": "2.8.0" + }, + "dependencies": { + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "dedent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.6.0.tgz", + "integrity": "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=", + "dev": true + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + }, + "dependencies": { + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + } + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.2" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.5.3" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dev": true, + "requires": { + "asap": "2.0.4", + "wrappy": "1.0.2" + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "download": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", + "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", + "dev": true, + "requires": { + "caw": "1.2.0", + "concat-stream": "1.5.1", + "each-async": "1.1.1", + "filenamify": "1.2.1", + "got": "5.7.1", + "gulp-decompress": "1.2.0", + "gulp-rename": "1.2.2", + "is-url": "1.2.2", + "object-assign": "4.1.0", + "read-all-stream": "3.1.0", + "readable-stream": "2.1.4", + "stream-combiner2": "1.1.1", + "vinyl": "1.2.0", + "vinyl-fs": "2.4.4", + "ware": "1.3.0" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.0", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.1.4" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.4", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.0", + "readable-stream": "2.1.4", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.1", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + } + } + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.1", + "readable-stream": "2.1.4", + "stream-shift": "1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "1.1.0", + "set-immediate-shim": "1.0.1" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.0" + } + }, + "editions": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.1.2.tgz", + "integrity": "sha1-jN8Ms56vxWQUkYHKN8gnLpixbqs=", + "dev": true + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "emojis-list": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.0.1.tgz", + "integrity": "sha1-oXTZ0IOOs2rz0FkLttPo3NlPT70=", + "dev": true + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.13" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "enhanced-resolve": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz", + "integrity": "sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "memory-fs": "0.2.0", + "tapable": "0.1.10" + }, + "dependencies": { + "memory-fs": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", + "integrity": "sha1-8rslNovBIeORwlIN6Slpyu4KApA=", + "dev": true + } + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "enzyme": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.4.1.tgz", + "integrity": "sha1-kPqYYdmC0M65Kp/VfjhCai9007E=", + "dev": true, + "requires": { + "cheerio": "0.20.0", + "is-subset": "0.1.1", + "lodash": "4.17.4", + "object-is": "1.0.1", + "object.assign": "4.0.4", + "object.values": "1.0.4" + } + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", + "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.5.1.tgz", + "integrity": "sha1-8L+Wvqdha7lAvOpPUn4x+y7h8io=", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.0", + "is-callable": "1.1.3", + "is-regex": "1.0.3" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.0.tgz", + "integrity": "sha1-skaq6CnOc9WeLFVyc1nt0cEwqBs=", + "dev": true, + "requires": { + "esprima": "2.7.2", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.1", + "source-map": "0.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.0" + } + } + } + }, + "eslint": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", + "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "babel-code-frame": "6.26.0", + "chalk": "2.3.2", + "concat-stream": "1.6.1", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.1.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.4", + "esquery": "1.0.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.3.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.1.0", + "js-yaml": "3.11.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.2", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.5.0", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "concat-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz", + "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.2.10" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.2", + "cli-cursor": "2.1.0", + "cli-width": "2.1.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.2.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "eslint-plugin-react": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", + "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==", + "dev": true, + "requires": { + "doctrine": "2.1.0", + "has": "1.0.1", + "jsx-ast-utils": "2.0.1", + "prop-types": "15.6.1" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + }, + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.1.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.12" + } + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "5.5.3", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true + } + } + }, + "esprima": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.2.tgz", + "integrity": "sha1-9DvlQ2CZhOrkTJM6xjNSpq818zk=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", + "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", + "dev": true + }, + "event-stream": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.3.tgz", + "integrity": "sha1-99Q3qY+cBxX0tkOpe2ZCVUlHm5s=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "from": "0.1.3", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": "1.0.0" + } + }, + "exec-buffer": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "p-finally": "1.0.0", + "pify": "3.0.0", + "rimraf": "2.6.1", + "tempfile": "2.0.0" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.2.10" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.0", + "strip-eof": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "exec-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", + "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", + "dev": true, + "requires": { + "async-each-series": "1.1.0", + "object-assign": "4.1.0" + } + }, + "execa": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", + "integrity": "sha1-TrZGejaglfq7KXD/nV4/t7zm68M=", + "dev": true, + "requires": { + "cross-spawn-async": "2.2.4", + "is-stream": "1.1.0", + "npm-run-path": "1.0.0", + "object-assign": "4.1.0", + "path-key": "1.0.0", + "strip-eof": "1.0.0" + } + }, + "executable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", + "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", + "dev": true, + "requires": { + "meow": "3.7.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "express": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "integrity": "sha1-we4/Qs3Ikfs9xlCoki1R7IR9DWY=", + "dev": true, + "requires": { + "accepts": "1.3.3", + "array-flatten": "1.1.1", + "content-disposition": "0.5.1", + "content-type": "1.0.2", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.2.0", + "depd": "1.1.0", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.7.0", + "finalhandler": "0.5.0", + "fresh": "0.3.0", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.1", + "path-to-regexp": "0.1.7", + "proxy-addr": "1.1.2", + "qs": "6.2.0", + "range-parser": "1.2.0", + "send": "0.14.1", + "serve-static": "1.11.1", + "type-is": "1.6.14", + "utils-merge": "1.0.0", + "vary": "1.1.0" + } + }, + "extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "fancy-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.2.0.tgz", + "integrity": "sha1-1aUbU+mrIsoH1VjytnrlX9tfy9g=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "time-stamp": "1.0.1" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.3.tgz", + "integrity": "sha1-KuezKrweYS2kik4ThJuIii9h5+k=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.6.5" + } + }, + "fbjs": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", + "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.2.0", + "object-assign": "4.1.0", + "promise": "7.1.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.12" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.0" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.0" + } + }, + "file-loader": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.11.2.tgz", + "integrity": "sha512-N+uhF3mswIFeziHQjGScJ/yHXYt3DiLBeC+9vWW+WjUBiClMSOlV1YrXQi+7KM2aA3Rn4Bybgv+uXFQbfkzpvg==", + "dev": true, + "requires": { + "loader-utils": "1.1.0" + }, + "dependencies": { + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.0.1", + "json5": "0.5.1" + } + } + } + }, + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + }, + "filename-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz", + "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=", + "dev": true + }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", + "dev": true + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "dev": true, + "requires": { + "filename-reserved-regex": "1.0.0", + "strip-outer": "1.0.0", + "trim-repeated": "1.0.0" + } + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.5", + "repeat-element": "1.1.2", + "repeat-string": "1.5.4" + } + }, + "finalhandler": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "integrity": "sha1-6VCKvs6bbbqHGmlCodeRG5GRGsc=", + "dev": true, + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-node-modules": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-1.0.1.tgz", + "integrity": "sha1-RllijsW14vEmRermBYma4u5paVk=", + "dev": true, + "requires": { + "findup-sync": "0.2.1", + "merge": "1.2.0" + } + }, + "find-root": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.0.0.tgz", + "integrity": "sha1-li/yEaqyXGUg/u641ih/j26VgHo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "find-versions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "dev": true, + "requires": { + "array-uniq": "1.0.3", + "get-stdin": "4.0.1", + "meow": "3.7.0", + "semver-regex": "1.0.0" + } + }, + "findup": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/findup/-/findup-0.1.5.tgz", + "integrity": "sha1-itkpozk7rGJ5V6fl3kYjsGsOLOs=", + "dev": true, + "requires": { + "colors": "0.6.2", + "commander": "2.1.0" + }, + "dependencies": { + "commander": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.1.0.tgz", + "integrity": "sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=", + "dev": true + } + } + }, + "findup-sync": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.2.1.tgz", + "integrity": "sha1-4KkKRQB1xJRm7lE3MgV1FLgeh4w=", + "dev": true, + "requires": { + "glob": "4.3.5" + }, + "dependencies": { + "glob": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.3.5.tgz", + "integrity": "sha1-gPuwjKVA8jiszl0R0em8QedRc9M=", + "dev": true, + "requires": { + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "2.0.10", + "once": "1.3.3" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.5" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.4", + "write": "0.2.1" + } + }, + "for-in": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.5.tgz", + "integrity": "sha1-AHN04rbVxnQgoUeb23WgSHK3OMQ=", + "dev": true + }, + "for-own": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz", + "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=", + "dev": true, + "requires": { + "for-in": "0.1.5" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "foreachasync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", + "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "1.0.0-rc4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", + "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", + "dev": true, + "requires": { + "async": "1.5.2", + "combined-stream": "1.0.5", + "mime-types": "2.1.11" + } + }, + "formatio": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", + "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "dev": true, + "requires": { + "samsam": "1.1.2" + } + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", + "dev": true + }, + "fresh": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", + "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", + "dev": true + }, + "from": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.3.tgz", + "integrity": "sha1-72OsIGKsMqz3hi4NQLRLiW8i87w=", + "dev": true + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.0", + "rimraf": "2.5.3" + } + }, + "fs-readdir-recursive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz", + "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.1.tgz", + "integrity": "sha1-8Z/Sj0Pur3YWgOUZogPE0LPTGv8=", + "dev": true, + "optional": true, + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.33" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.1.tgz", + "integrity": "sha1-ldNgDwdxCqDpKYxyatXs8urLq6s=", + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz", + "integrity": "sha1-gORw6VoIR5T+GJkmLFZnxuiN4bM=", + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", + "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "optional": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "optional": true, + "requires": { + "ms": "0.7.1" + } + }, + "deep-extend": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.1.tgz", + "integrity": "sha1-7+QRPQgIX05vlod1mBD4B0aeIlM=", + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "optional": true + }, + "extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", + "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz", + "integrity": "sha1-icNTQAi5fq2ky7FX1Y9vXfAl6uQ=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.14" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz", + "integrity": "sha1-YE6Kkv4m/9n2+uMDmdSYThqyKCI=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.5.4" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.10", + "inherits": "2.0.3", + "minimatch": "3.0.3" + } + }, + "gauge": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.3.tgz", + "integrity": "sha1-HCOFX5YvF7OtPQ3HRD8wRULt/gk=", + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true, + "optional": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "optional": true, + "requires": { + "is-property": "1.0.2" + } + }, + "getpass": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.3", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.9.0", + "is-my-json-valid": "2.15.0", + "pinkie-promise": "2.0.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.3.1", + "sshpk": "1.10.2" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-my-json-valid": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz", + "integrity": "sha1-k27do8o8IR/ZjzstPgjaQ/eykVs=", + "dev": true, + "optional": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true, + "optional": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true, + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "optional": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.1.tgz", + "integrity": "sha1-KnJW9wQSop7jZwqspiWZTE3P8lI=", + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + } + }, + "mime-db": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz", + "integrity": "sha1-6v/NDk/Gk1z4E02iRuLmw1MFrf8=", + "dev": true + }, + "mime-types": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz", + "integrity": "sha1-9+99l1g/yvO30oK2+LVnnaselO4=", + "dev": true, + "requires": { + "mime-db": "1.26.0" + } + }, + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true, + "requires": { + "brace-expansion": "1.1.6" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.33", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.33.tgz", + "integrity": "sha1-ZArFUZj2qSWXLgwWxKwmoDTV7Mk=", + "dev": true, + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.0.2", + "rc": "1.1.7", + "request": "2.79.0", + "rimraf": "2.5.4", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.3.0" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "npmlog": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz", + "integrity": "sha1-0DlQ4OeM4VJ7om0qdZLpNIrD518=", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.2", + "console-control-strings": "1.1.0", + "gauge": "2.7.3", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "optional": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "optional": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.1.tgz", + "integrity": "sha1-kYwLO802Z5dyuvE1say0wWUe150=", + "dev": true, + "optional": true + }, + "rc": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.1.7.tgz", + "integrity": "sha1-xepWS7B6/5/TpbMukGwdOmWUD+o=", + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.1", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz", + "integrity": "sha1-qeb+w8fdqF+LsbO6cChgRVb8gl4=", + "dev": true, + "optional": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.0", + "forever-agent": "0.6.1", + "form-data": "2.1.2", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.14", + "oauth-sign": "0.8.2", + "qs": "6.3.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.4.3", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "7.1.1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.2.tgz", + "integrity": "sha1-1agEziJpVRVjjnmNviMnPeBwpfo=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.6", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "optional": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.10", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.3.0.tgz", + "integrity": "sha1-MJMYFkGPVa/E0hd1r91nIM7kXa4=", + "dev": true, + "optional": true, + "requires": { + "debug": "2.2.0", + "fstream": "1.0.10", + "fstream-ignore": "1.0.5", + "once": "1.3.3", + "readable-stream": "2.1.5", + "rimraf": "2.5.4", + "tar": "2.2.1", + "uid-number": "0.0.6" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "optional": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "dev": true, + "optional": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true, + "optional": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", + "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz", + "integrity": "sha1-QO3egCpx/qHwcNo+YtzaLnrdlq0=", + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", + "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.2", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.0", + "signal-exit": "3.0.0", + "string-width": "1.0.1", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-proxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", + "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", + "dev": true, + "requires": { + "rc": "1.2.1" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "gh-pages": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-0.12.0.tgz", + "integrity": "sha1-2VHj7Zi4VpnUsEGOsaFbGgSYjcE=", + "dev": true, + "requires": { + "async": "2.1.2", + "commander": "2.9.0", + "globby": "6.1.0", + "graceful-fs": "4.1.10", + "q": "1.4.1", + "q-io": "1.13.2", + "rimraf": "2.5.4" + }, + "dependencies": { + "async": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.1.2.tgz", + "integrity": "sha1-YSpKtF70KnDN6Aa62G7m2wR+g4U=", + "dev": true, + "requires": { + "lodash": "4.17.3" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz", + "integrity": "sha1-8tcgwiCS90Mih3XHXjYSYyUB8TE=", + "dev": true + }, + "lodash": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.3.tgz", + "integrity": "sha1-VX7X0qlDjKxf1aQwQ8pgy0VeAfc=", + "dev": true + }, + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "7.1.1" + } + } + } + }, + "ghooks": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ghooks/-/ghooks-1.3.2.tgz", + "integrity": "sha1-vuKd7sQoPiPrH/N9lKgSCs1DMuk=", + "dev": true, + "requires": { + "execa": "0.4.0", + "findup": "0.1.5", + "lodash.clone": "4.3.2", + "manage-path": "2.0.0", + "opt-cli": "1.5.1", + "path-exists": "2.1.0", + "spawn-command": "0.0.2" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "gifsicle": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", + "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "git-head": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/git-head/-/git-head-1.20.1.tgz", + "integrity": "sha1-A20WpLN0lJ5OPa8VgnkDaG08zVI=", + "dev": true, + "requires": { + "git-refs": "1.1.3" + } + }, + "git-refs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/git-refs/-/git-refs-1.1.3.tgz", + "integrity": "sha1-gwl8s6klhcSkkm7FTiGC354g6J0=", + "dev": true, + "requires": { + "path-object": "2.3.0", + "slash": "1.0.0", + "walk": "2.3.9" + } + }, + "github": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/github/-/github-0.2.4.tgz", + "integrity": "sha1-JPp/DhP6EblGr5ETTFGYKpHOU4s=", + "dev": true, + "requires": { + "mime": "1.3.4" + } + }, + "github-url-from-git": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-url-from-git/-/github-url-from-git-1.5.0.tgz", + "integrity": "sha1-+YX+3MCpqledyI16/waNVcxiUaA=", + "dev": true + }, + "github-url-from-username-repo": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/github-url-from-username-repo/-/github-url-from-username-repo-1.0.2.tgz", + "integrity": "sha1-fdeTMNKr5pwQws73lxTJchV5Hfo=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "2.0.10", + "once": "1.3.3" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.5" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "globals": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.1", + "object-assign": "4.1.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + } + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer2": "0.1.4", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "node-status-codes": "1.0.0", + "object-assign": "4.1.0", + "parse-json": "2.2.0", + "pinkie-promise": "2.0.1", + "read-all-stream": "3.1.0", + "readable-stream": "2.1.4", + "timed-out": "3.1.3", + "unzip-response": "1.0.2", + "url-parse-lax": "1.0.0" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.1.4" + } + } + } + }, + "graceful-fs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", + "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.1", + "deprecated": "0.0.1", + "gulp-util": "3.0.7", + "interpret": "1.0.1", + "liftoff": "2.2.4", + "minimist": "1.2.0", + "orchestrator": "0.3.7", + "pretty-hrtime": "1.0.2", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.0.11", + "vinyl-fs": "0.3.14" + } + }, + "gulp-decompress": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", + "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", + "dev": true, + "requires": { + "archive-type": "3.2.0", + "decompress": "3.0.0", + "gulp-util": "3.0.7", + "readable-stream": "2.1.4" + } + }, + "gulp-git": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/gulp-git/-/gulp-git-1.7.2.tgz", + "integrity": "sha1-uvBj7wTwKzw0Tg8dimyNbQJhBQc=", + "dev": true, + "requires": { + "any-shell-escape": "0.1.1", + "gulp-util": "3.0.7", + "require-dir": "0.1.0", + "through2": "0.6.5" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-rename": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "dev": true + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "graceful-fs": "4.1.4", + "strip-bom": "2.0.0", + "through2": "2.0.1", + "vinyl": "1.2.0" + }, + "dependencies": { + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.0", + "chalk": "1.1.1", + "dateformat": "1.0.12", + "fancy-log": "1.2.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.1", + "vinyl": "0.5.3" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "commander": "2.9.0", + "is-my-json-valid": "2.13.1", + "pinkie-promise": "2.0.1" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.1", + "os-tmpdir": "1.0.1" + } + }, + "hosted-git-info": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", + "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=", + "dev": true + }, + "html": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/html/-/html-0.0.10.tgz", + "integrity": "sha1-b9w++GaMCaOhmO46Wqnp8oeLld4=", + "dev": true, + "requires": { + "concat-stream": "1.5.1", + "glob": "3.2.11" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.1", + "minimatch": "0.3.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.5.1", + "entities": "1.0.0", + "readable-stream": "1.1.14" + }, + "dependencies": { + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": "1.3.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.3.tgz", + "integrity": "sha1-lAOCFHFJuFYIT1U0dS1bWoFozR0=", + "dev": true, + "requires": { + "http-proxy": "1.16.2", + "is-glob": "3.1.0", + "lodash": "4.17.3", + "micromatch": "2.3.11" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "lodash": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.3.tgz", + "integrity": "sha1-VX7X0qlDjKxf1aQwQ8pgy0VeAfc=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.0", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.0.3", + "normalize-path": "2.0.1", + "object.omit": "2.0.0", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.3.0", + "sshpk": "1.8.3" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "image-webpack-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/image-webpack-loader/-/image-webpack-loader-3.3.1.tgz", + "integrity": "sha1-0tcr4CT4l15IyYTyQBwMSEiXy9M=", + "dev": true, + "requires": { + "imagemin": "5.3.1", + "imagemin-gifsicle": "5.2.0", + "imagemin-mozjpeg": "6.0.0", + "imagemin-optipng": "5.2.1", + "imagemin-pngquant": "5.0.1", + "imagemin-svgo": "5.2.2", + "loader-utils": "1.1.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.0.1", + "json5": "0.5.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "imagemin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", + "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", + "dev": true, + "requires": { + "file-type": "4.4.0", + "globby": "6.1.0", + "make-dir": "1.0.0", + "p-pipe": "1.2.0", + "pify": "2.3.0", + "replace-ext": "1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "imagemin-gifsicle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", + "integrity": "sha512-K01m5QuPK+0en8oVhiOOAicF7KjrHlCZxS++mfLI2mV/Ksfq/Y9nCXCWDz6jRv13wwlqe5T7hXT+ji2DnLc2yQ==", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "gifsicle": "3.0.4", + "is-gif": "1.0.0" + } + }, + "imagemin-mozjpeg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-6.0.0.tgz", + "integrity": "sha1-caMqRXqhsmEXpo7u8tmxkMLlCR4=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-jpg": "1.0.0", + "mozjpeg": "4.1.1" + } + }, + "imagemin-optipng": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", + "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "optipng-bin": "3.1.4" + } + }, + "imagemin-pngquant": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/imagemin-pngquant/-/imagemin-pngquant-5.0.1.tgz", + "integrity": "sha1-2KMp2lU6+iJrEc5i3r4Lfje0OeY=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "pngquant-bin": "3.1.1" + } + }, + "imagemin-svgo": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-5.2.2.tgz", + "integrity": "sha1-UBaZ9XiXMKV5IrhzbqFcU/e1WDg=", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "svgo": "0.7.2" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + }, + "dependencies": { + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.1" + } + } + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=", + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "inquirer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.0.3.tgz", + "integrity": "sha1-6+OglIVxvMRszMvi+bzsJR6YS9A=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "chalk": "1.1.1", + "cli-cursor": "1.0.2", + "cli-width": "2.1.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "mute-stream": "0.0.6", + "pinkie-promise": "2.0.1", + "run-async": "2.2.0", + "rx": "4.1.0", + "string-width": "1.0.1", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "interpret": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.1.tgz", + "integrity": "sha1-1Xn7f2k7hYAElHrzn6DbSfeVYCw=", + "dev": true + }, + "invariant": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=", + "dev": true, + "requires": { + "loose-envify": "1.2.0" + } + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true + }, + "ipaddr.js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.1.1.tgz", + "integrity": "sha1-x5HZX1KynBJH1d+AraObinNkcjA=", + "dev": true + }, + "is-absolute": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", + "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", + "dev": true, + "requires": { + "is-relative": "0.1.3" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.8.0" + } + }, + "is-buffer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz", + "integrity": "sha1-24l/w/esotUN6UtsjCiWpHcWJ68=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-bzip2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", + "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", + "dev": true + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", + "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", + "integrity": "sha1-ZDhgPq6+J5OUj/SkJi7I2z1iWXs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-gif": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", + "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, + "is-jpg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.0.tgz", + "integrity": "sha1-KVnBfnNDDbOCZNp1uQ3VTy2G2hw=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", + "integrity": "sha1-1Vd4qC/rawlj/0vhEdXRaE6JBwc=", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "2.0.0", + "xtend": "4.0.1" + } + }, + "is-natural-number": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", + "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz", + "integrity": "sha1-TXylObydubc3uKy2EvIxjvkvKU8=", + "dev": true, + "requires": { + "isobject": "1.0.2" + }, + "dependencies": { + "isobject": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz", + "integrity": "sha1-8Pm4zpLdVA+gdAiC44NaLgIux4o=", + "dev": true + } + } + }, + "is-png": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", + "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.3.tgz", + "integrity": "sha1-DVUYK9358v3ieCIK7Dp1ZCyQhjc=", + "dev": true + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-relative": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", + "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dev": true, + "requires": { + "html-comment-regex": "1.1.1" + } + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-tar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", + "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-url": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.2.tgz", + "integrity": "sha1-SYkFpZO/R8wtnn9zg3K792lsfyY=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", + "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.6.3", + "whatwg-fetch": "2.0.1" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "jodid25519": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true, + "requires": { + "argparse": "1.0.7", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "dev": true, + "optional": true + }, + "jsdom": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.4.1.tgz", + "integrity": "sha1-syLJGHJYS+shQnatNfa0dbrPEjg=", + "dev": true, + "requires": { + "abab": "1.0.3", + "acorn": "2.7.0", + "acorn-globals": "1.0.9", + "array-equal": "1.0.0", + "cssom": "0.3.1", + "cssstyle": "0.2.36", + "escodegen": "1.8.0", + "iconv-lite": "0.4.13", + "nwmatcher": "1.3.8", + "parse5": "1.5.1", + "request": "2.73.0", + "sax": "1.2.1", + "symbol-tree": "3.1.4", + "tough-cookie": "2.2.2", + "webidl-conversions": "3.0.1", + "whatwg-url": "3.0.0", + "xml-name-validator": "2.0.1" + }, + "dependencies": { + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "dev": true + } + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-loader": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.4.tgz", + "integrity": "sha1-i6oTZaYy9Yo8RtIBdfxgAsluN94=", + "dev": true + }, + "json-schema": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz", + "integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz", + "integrity": "sha1-OvHdIP6FRjkQ1GmjheMwF9KgMNk=", + "dev": true + }, + "jsprim": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz", + "integrity": "sha1-zi4b74NSBLTzCZkoxgL4tq5hVlA=", + "dev": true, + "requires": { + "extsprintf": "1.0.2", + "json-schema": "0.2.2", + "verror": "1.3.6" + } + }, + "jsx-ast-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", + "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", + "dev": true, + "requires": { + "array-includes": "3.0.3" + } + }, + "kind-of": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.3.tgz", + "integrity": "sha1-xhYIdH2BWwNiVW2zJ2Nip6OK3tM=", + "dev": true, + "requires": { + "is-buffer": "1.1.3" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.1.4" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "liftoff": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.4.tgz", + "integrity": "sha1-RDrfKCcG4q4lU8x+NmD5dojje60=", + "dev": true, + "requires": { + "extend": "3.0.0", + "findup-sync": "0.3.0", + "flagged-respawn": "0.3.2", + "rechoir": "0.6.2", + "resolve": "1.1.7" + }, + "dependencies": { + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-utils": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.15.tgz", + "integrity": "sha1-x98zQqnU4hA93cl9QGDazMJG1qw=", + "dev": true, + "requires": { + "big.js": "3.1.3", + "emojis-list": "2.0.1", + "json5": "0.5.0", + "object-assign": "4.1.0" + }, + "dependencies": { + "json5": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.0.tgz", + "integrity": "sha1-myBxWwJsvjd4/Xae3M2CLYMypbI=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._baseclone": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-4.5.7.tgz", + "integrity": "sha1-zkKt4IOE711i+nfDD2GkbmhvhDQ=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._createassigner": "3.1.1", + "lodash.keys": "3.1.2" + } + }, + "lodash.clone": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.3.2.tgz", + "integrity": "sha1-5WsXa2gjp93jj38r9Y3n1ZcSAOk=", + "dev": true, + "requires": { + "lodash._baseclone": "4.5.7" + } + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.8.tgz", + "integrity": "sha1-W/jaiH8B8qnknAoXXNrrMYoOQ9w=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.0.8", + "lodash.isarray": "3.0.4" + } + }, + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "logalot": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", + "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", + "dev": true, + "requires": { + "figures": "1.7.0", + "squeak": "1.3.0" + } + }, + "lolex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", + "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=", + "requires": { + "js-tokens": "1.0.3" + }, + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", + "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=" + } + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "lpad-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", + "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "indent-string": "2.1.0", + "longest": "1.0.1", + "meow": "3.7.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", + "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "manage-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/manage-path/-/manage-path-2.0.0.tgz", + "integrity": "sha1-9M+EV7km7u4qg7FzUBQUvHbrlZc=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=", + "dev": true, + "requires": { + "errno": "0.1.4", + "readable-stream": "2.1.4" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.3.5", + "object-assign": "4.1.0", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + } + }, + "merge": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", + "dev": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.1.4" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.0", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.0.3", + "normalize-path": "2.0.1", + "object.omit": "2.0.0", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "mime-db": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz", + "integrity": "sha1-oxtAcK2uon1zLqMzdApk0OyaZlk=", + "dev": true + }, + "mime-types": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz", + "integrity": "sha1-wlnEcb2oCKhdbNGTtDCl+uRHOzw=", + "dev": true, + "requires": { + "mime-db": "1.23.0" + } + }, + "mimeparse": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "integrity": "sha1-2vsCdSNw/SJgk64xUsJxrwGsJUo=", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "integrity": "sha1-DzmKcwDqRB6cNIyD2Yq4ydv5xAo=", + "dev": true, + "requires": { + "brace-expansion": "1.1.5" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2.0.1", + "minimatch": "0.3.0" + } + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + } + } + }, + "mozjpeg": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-4.1.1.tgz", + "integrity": "sha1-hZAwsk9omlPbm0DwFg2JGVuI/VA=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz", + "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=", + "dev": true + }, + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=", + "dev": true + }, + "node-dir": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.16.tgz", + "integrity": "sha1-0u9YOqULkNk9uM3Sb86lg1OVf+Q=", + "dev": true, + "requires": { + "minimatch": "3.0.2" + } + }, + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-libs-browser": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", + "integrity": "sha1-PicsCBnjCJNeJmdECNevDhSRuDs=", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.3.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "0.0.1", + "os-browserify": "0.2.1", + "path-browserify": "0.0.0", + "process": "0.11.9", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.1.4", + "stream-browserify": "2.0.1", + "stream-http": "2.7.0", + "string_decoder": "0.10.31", + "timers-browserify": "2.0.2", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + } + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, + "node-uuid": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "normalize-package-data": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", + "dev": true, + "requires": { + "hosted-git-info": "2.1.5", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", + "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=", + "dev": true + }, + "npm-package-arg": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-4.2.1.tgz", + "integrity": "sha1-WTMD/eqF98Qid18X+et2cPaA4+w=", + "dev": true, + "requires": { + "hosted-git-info": "2.1.5", + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "npm-registry-client": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-7.5.0.tgz", + "integrity": "sha1-D23W5dEUJM+pn85bkw/q8JtPfwQ=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "graceful-fs": "4.1.11", + "normalize-package-data": "2.3.5", + "npm-package-arg": "4.2.1", + "npmlog": "4.1.2", + "once": "1.3.3", + "request": "2.81.0", + "retry": "0.10.1", + "semver": "4.3.6", + "slide": "1.1.6" + }, + "dependencies": { + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + }, + "dependencies": { + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.4.1", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.0", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.11", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + } + } + }, + "npm-run-all": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-2.3.0.tgz", + "integrity": "sha1-2po7nGCUK/eKc54eNcfy2+xtNXE=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cross-spawn": "4.0.0", + "minimatch": "3.0.2", + "object-assign": "4.1.0", + "pinkie-promise": "2.0.1", + "ps-tree": "1.1.0", + "read-pkg": "1.1.0", + "read-pkg-up": "1.0.1", + "shell-quote": "1.6.1", + "string.prototype.padend": "3.0.0" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + } + } + }, + "npm-run-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", + "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", + "dev": true, + "requires": { + "path-key": "1.0.0" + } + }, + "npmconf": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/npmconf/-/npmconf-2.1.2.tgz", + "integrity": "sha1-ZmBqSnNvHnegWaoHGnnJSreBhTo=", + "dev": true, + "requires": { + "config-chain": "1.1.11", + "inherits": "2.0.1", + "ini": "1.3.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.3.3", + "osenv": "0.1.4", + "semver": "4.3.6", + "uid-number": "0.0.5" + } + }, + "npmlog": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-1.2.1.tgz", + "integrity": "sha1-KOe+YZYJtT960d0wChDWTXFiaLY=", + "dev": true, + "requires": { + "ansi": "0.3.1", + "are-we-there-yet": "1.0.6", + "gauge": "1.2.7" + }, + "dependencies": { + "are-we-there-yet": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.0.6.tgz", + "integrity": "sha1-otKMkxAqpsyWJFomy5VN4G7FPww=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.1.4" + } + }, + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "dev": true, + "requires": { + "ansi": "0.3.1", + "has-unicode": "2.0.1", + "lodash.pad": "4.5.1", + "lodash.padend": "4.6.1", + "lodash.padstart": "4.6.1" + } + } + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", + "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=", + "dev": true + }, + "nwmatcher": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.3.8.tgz", + "integrity": "sha1-NO25PeGqbLREi1c8nyoFkwAkEVc=", + "dev": true + }, + "nyc": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-7.0.0.tgz", + "integrity": "sha1-GAmUHjmfLM/l4IjNj8R50TcomLA=", + "dev": true, + "requires": { + "append-transform": "0.4.0", + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.2.0", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "1.1.2", + "foreground-child": "1.5.3", + "glob": "7.0.5", + "istanbul-lib-coverage": "1.0.0-alpha.4", + "istanbul-lib-instrument": "1.1.0-alpha.2", + "istanbul-lib-report": "1.0.0-alpha.3", + "istanbul-lib-source-maps": "1.0.0-alpha.10", + "istanbul-reports": "1.0.0-alpha.7", + "md5-hex": "1.3.0", + "micromatch": "2.3.10", + "mkdirp": "0.5.1", + "pkg-up": "1.0.0", + "resolve-from": "2.0.0", + "rimraf": "2.5.3", + "signal-exit": "3.0.0", + "spawn-wrap": "1.2.3", + "test-exclude": "1.1.0", + "yargs": "4.7.1" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.0.3", + "longest": "1.0.1", + "repeat-string": "1.5.4" + } + }, + "amdefine": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz", + "integrity": "sha1-/RdHRwDLXMnCtwnwvp0jzjwZjDM=", + "dev": true + }, + "ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.0.1" + } + }, + "arr-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz", + "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "babel-code-frame": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.11.0.tgz", + "integrity": "sha1-kHLdI1P7D4W2tX0sl/DRNNGIrtg=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "2.0.0" + } + }, + "babel-generator": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.11.0.tgz", + "integrity": "sha1-jFpuOAOqzGxtp9ls112mzG4rMnU=", + "dev": true, + "requires": { + "babel-messages": "6.8.0", + "babel-runtime": "6.9.2", + "babel-types": "6.11.1", + "detect-indent": "3.0.1", + "lodash": "4.13.1", + "source-map": "0.5.6" + } + }, + "babel-messages": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz", + "integrity": "sha1-v1BHNsqWfm1l7wrbWipflHyODrk=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "babel-runtime": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz", + "integrity": "sha1-1/45G8LMKbgIfB2bOYeJEun8/Vk=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.9.5" + } + }, + "babel-template": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.9.0.tgz", + "integrity": "sha1-lwkPz2vBVoW08FvmXAqUOKp+I+M=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "babel-traverse": "6.10.4", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "lodash": "4.13.1" + } + }, + "babel-traverse": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.10.4.tgz", + "integrity": "sha1-289B/x8y62FIWc6tSHEWDx8SDXg=", + "dev": true, + "requires": { + "babel-code-frame": "6.11.0", + "babel-messages": "6.8.0", + "babel-runtime": "6.9.2", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "debug": "2.2.0", + "globals": "8.18.0", + "invariant": "2.2.1", + "lodash": "4.13.1" + } + }, + "babel-types": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.11.1.tgz", + "integrity": "sha1-o981W6uQ3c9mMYZAcXzywVTmZIo=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "babel-traverse": "6.10.4", + "esutils": "2.0.2", + "lodash": "4.13.1", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.8.4", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.8.4.tgz", + "integrity": "sha1-CXMGuNq66VFZIlzymz6lWRIFMYA=", + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "balanced-match": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz", + "integrity": "sha1-GQU+LgdI6ts3nabAnUVc9eEDkzU=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", + "integrity": "sha1-9bStV04st8zB64Pm/nm47K33pSY=", + "dev": true, + "requires": { + "balanced-match": "0.4.1", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caching-transform": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", + "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.1.4" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", + "integrity": "sha1-9psZLT99keOC5Lcb3bd4eGGasMY=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.2.0.tgz", + "integrity": "sha1-RMCMJQbxD7PKb9iI1aNETPjWpmk=", + "dev": true + }, + "core-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz", + "integrity": "sha1-30CKtG0Br/kcAcPnlxk11CLFT4E=", + "dev": true + }, + "cross-spawn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz", + "integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=", + "dev": true, + "requires": { + "lru-cache": "4.0.1", + "which": "1.2.10" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "detect-indent": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", + "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "minimist": "1.2.0", + "repeating": "1.1.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "error-ex": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", + "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz", + "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.5", + "repeat-element": "1.1.2", + "repeat-string": "1.5.4" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "for-in": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.5.tgz", + "integrity": "sha1-AHN04rbVxnQgoUeb23WgSHK3OMQ=", + "dev": true + }, + "for-own": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz", + "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=", + "dev": true, + "requires": { + "for-in": "0.1.5" + } + }, + "foreground-child": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.3.tgz", + "integrity": "sha1-lN1qumcTiYZ96OV+mfHC7PsVwBo=", + "dev": true, + "requires": { + "cross-spawn": "4.0.0", + "signal-exit": "3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "glob": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", + "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", + "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", + "dev": true + }, + "handlebars": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", + "integrity": "sha1-ksbta7FkEQxQ1NjQ+93HCAbG+Oc=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.0" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "hosted-git-info": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", + "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", + "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=", + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "invariant": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", + "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=", + "dev": true, + "requires": { + "loose-envify": "1.2.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz", + "integrity": "sha1-24l/w/esotUN6UtsjCiWpHcWJ68=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", + "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", + "integrity": "sha1-ZDhgPq6+J5OUj/SkJi7I2z1iWXs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.0-alpha.4.tgz", + "integrity": "sha1-Ym9/2c+Am2479+1CqAn44LZK6XY=", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.1.0-alpha.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.1.0-alpha.2.tgz", + "integrity": "sha1-znzcbTrjX9S68QolwGtGHuzxqBU=", + "dev": true, + "requires": { + "babel-generator": "6.11.0", + "babel-template": "6.9.0", + "babel-traverse": "6.10.4", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "istanbul-lib-coverage": "1.0.0-alpha.4" + } + }, + "istanbul-lib-report": { + "version": "1.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.0.0-alpha.3.tgz", + "integrity": "sha1-MtX27H8zyjpgIgnieLLm/xQ0mK8=", + "dev": true, + "requires": { + "async": "1.5.2", + "istanbul-lib-coverage": "1.0.0-alpha.4", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "rimraf": "2.5.3", + "supports-color": "3.1.2" + }, + "dependencies": { + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.0.0-alpha.10.tgz", + "integrity": "sha1-mxWlyLWdG5EBviy33VTHA9hq3vE=", + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.0.0-alpha.4", + "mkdirp": "0.5.1", + "rimraf": "2.5.3", + "source-map": "0.5.6" + } + }, + "istanbul-reports": { + "version": "1.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.0.0-alpha.7.tgz", + "integrity": "sha1-XKML9EpIZmgbYoJRagigiykepsM=", + "dev": true, + "requires": { + "handlebars": "4.0.5" + } + }, + "js-tokens": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz", + "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU=", + "dev": true + }, + "kind-of": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.3.tgz", + "integrity": "sha1-xhYIdH2BWwNiVW2zJ2Nip6OK3tM=", + "dev": true, + "requires": { + "is-buffer": "1.1.3" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", + "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=", + "dev": true + }, + "lodash.assign": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.0.9.tgz", + "integrity": "sha1-Cgcx2TWQ3dm6RYn61lqvbuCSF+M=", + "dev": true, + "requires": { + "lodash.keys": "4.0.7", + "lodash.rest": "4.0.3" + } + }, + "lodash.keys": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.0.7.tgz", + "integrity": "sha1-MOGzvZjlTWoGEZkYEmhba8R8tjs=", + "dev": true + }, + "lodash.rest": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.3.tgz", + "integrity": "sha1-TBwyxAAoCHJQ+r9w1C4BUVSPSMU=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", + "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=", + "dev": true, + "requires": { + "js-tokens": "1.0.3" + }, + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", + "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=", + "dev": true + } + } + }, + "lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.0.0" + } + }, + "md5-hex": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", + "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", + "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", + "dev": true + }, + "micromatch": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.10.tgz", + "integrity": "sha1-9Psxdb7sYnlae4wk1fdFw2gGYKs=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.0", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.0.3", + "normalize-path": "2.0.1", + "object.omit": "2.0.0", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "minimatch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", + "integrity": "sha1-DzmKcwDqRB6cNIyD2Yq4ydv5xAo=", + "dev": true, + "requires": { + "brace-expansion": "1.1.5" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "normalize-package-data": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", + "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", + "dev": true, + "requires": { + "hosted-git-info": "2.1.5", + "is-builtin-module": "1.0.0", + "semver": "5.2.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", + "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", + "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=", + "dev": true + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", + "dev": true + }, + "object.omit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz", + "integrity": "sha1-hoWXMz1U5gZilAu0WGBd1q4S/pQ=", + "dev": true, + "requires": { + "for-own": "0.1.4", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", + "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.2", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz", + "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "load-json-file": "1.1.0", + "object-assign": "4.1.0", + "symbol": "0.2.3" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "pkg-up": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", + "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "randomatic": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz", + "integrity": "sha1-Xp718tVzxnvSuBJK6QtRVuRXhAs=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "kind-of": "3.0.3" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.3.5", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "regenerator-runtime": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz", + "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw=", + "dev": true + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz", + "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=", + "dev": true + }, + "repeating": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", + "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", + "dev": true, + "requires": { + "is-finite": "1.0.1" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.3.tgz", + "integrity": "sha1-bl792kqi8DQX9rKldK7Cn0tlJwU=", + "dev": true, + "requires": { + "glob": "7.0.5" + } + }, + "semver": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.2.0.tgz", + "integrity": "sha1-KBmVuAwUSCCUFd28TPUMJpzvVcU=", + "dev": true + }, + "set-blocking": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-1.0.0.tgz", + "integrity": "sha1-zV5dk4BI3xrJLf6S4fFq3WVvXsU=", + "dev": true + }, + "signal-exit": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz", + "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g=", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "spawn-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.2.3.tgz", + "integrity": "sha1-3300R/tKAZYZpB9o7mQqcY5gYuk=", + "dev": true, + "requires": { + "foreground-child": "1.5.3", + "mkdirp": "0.5.1", + "os-homedir": "1.0.1", + "rimraf": "2.5.3", + "signal-exit": "2.1.2", + "which": "1.2.10" + }, + "dependencies": { + "signal-exit": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-2.1.2.tgz", + "integrity": "sha1-N1h5sfkuvDszRIDQONxUam1VhWQ=", + "dev": true + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.1" + } + }, + "spdx-exceptions": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz", + "integrity": "sha1-IguEI5EZrpBFqJLbgag/TOFvgP0=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", + "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=", + "dev": true, + "requires": { + "spdx-exceptions": "1.0.4", + "spdx-license-ids": "1.2.1" + } + }, + "spdx-license-ids": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.1.tgz", + "integrity": "sha1-0H6hek0v2TUfnZTi/5zsdBgP6PM=", + "dev": true + }, + "string-width": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz", + "integrity": "sha1-ySEptvHX9SrPmvQkom44ZKBc6wo=", + "dev": true, + "requires": { + "code-point-at": "1.0.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz", + "integrity": "sha1-O5hzuKkB5Hxu/iFSajrDcu8ou8c=", + "dev": true + }, + "test-exclude": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-1.1.0.tgz", + "integrity": "sha1-9d3XGJJ7Ev0C8nCgqpOc627qQVE=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "lodash.assign": "4.0.9", + "micromatch": "2.3.10", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "to-fast-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", + "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", + "dev": true + }, + "uglify-js": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.0.tgz", + "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", + "dev": true, + "optional": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.2" + } + }, + "which": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz", + "integrity": "sha1-kc2b0HUTIkEbZZtA8FSyHelXqy0=", + "dev": true, + "requires": { + "isexe": "1.1.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz", + "integrity": "sha1-fTD4+HP5pbvDpk2ryNF34HGuQm8=", + "dev": true, + "requires": { + "string-width": "1.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.1.4.tgz", + "integrity": "sha1-sfUtwujcDjywTRh6JfdYo4qQyjs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", + "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=", + "dev": true + }, + "yargs": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.7.1.tgz", + "integrity": "sha1-5gQyZYozh/8mnAKOrN5KUS5Djf8=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "lodash.assign": "4.0.9", + "os-locale": "1.4.0", + "pkg-conf": "1.1.3", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1", + "set-blocking": "1.0.0", + "string-width": "1.0.1", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.1", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.0.0" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.0.tgz", + "integrity": "sha1-HzZ9ycbPpWYLaXEjDzsnf8Xjrco=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "lodash.assign": "4.0.9" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + }, + "object-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", + "dev": true + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object.assign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", + "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.0", + "object-keys": "1.0.11" + } + }, + "object.omit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz", + "integrity": "sha1-hoWXMz1U5gZilAu0WGBd1q4S/pQ=", + "dev": true, + "requires": { + "for-own": "0.1.4", + "is-extendable": "0.1.1" + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.7.0", + "function-bind": "1.1.0", + "has": "1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", + "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.0", + "is-callable": "1.1.3", + "is-regex": "1.0.3" + } + } + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "open": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", + "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=", + "dev": true + }, + "opt-cli": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/opt-cli/-/opt-cli-1.5.1.tgz", + "integrity": "sha1-BNtEexPJa5kusxaFJm9O0NlzbcI=", + "dev": true, + "requires": { + "commander": "2.9.0", + "lodash.clone": "4.3.2", + "manage-path": "2.0.0", + "spawn-command": "0.0.2-1" + }, + "dependencies": { + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + } + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz", + "integrity": "sha1-4xtJMs3V+4Yqiw0QvGPT7h7H14s=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "1.1.3", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "optipng-bin": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", + "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "orchestrator": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.7.tgz", + "integrity": "sha1-xFBk4ixaKnuZc09AmpX/7cfTw98=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "original": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "dev": true, + "requires": { + "url-parse": "1.0.5" + }, + "dependencies": { + "url-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + } + } + }, + "os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", + "dev": true + }, + "os-filter-obj": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", + "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", + "dev": true + }, + "os-homedir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", + "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz", + "integrity": "sha1-6bQjoe2vR5iCVi6S7XHXdDoHG24=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "requires": { + "os-homedir": "1.0.1", + "os-tmpdir": "1.0.1" + } + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "mkdirp": "0.5.1", + "object-assign": "4.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parse-github-repo-url": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", + "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.2", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.0" + } + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "dev": true + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", + "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", + "dev": true + }, + "path-object": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/path-object/-/path-object-2.3.0.tgz", + "integrity": "sha1-A+RmU+XDdcYK8cq92UvGRIpdkRA=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "lodash.assign": "3.2.0" + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "pbkdf2-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz", + "integrity": "sha1-tuDI+plJTZTgURV1gCpZpcFC8og=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "pngquant-bin": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-3.1.1.tgz", + "integrity": "sha1-0STZinWpSH9AwWQLTb/Lsr1aH9E=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz", + "integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", + "integrity": "sha1-cMqW9NBiikQ7kYdY95QWqae8n6g=", + "dev": true + }, + "private": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", + "dev": true + }, + "process": { + "version": "0.11.9", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.9.tgz", + "integrity": "sha1-e9WtIapiU+fahoImTx4R0RwDGME=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "promise": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz", + "integrity": "sha1-SJZUxpJha4qlWwck+oCbt9tJxb8=", + "requires": { + "asap": "2.0.4" + } + }, + "prop-types": { + "version": "15.5.8", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.8.tgz", + "integrity": "sha1-a3suFBCDvjjIWVqlH8VXdccZk5Q=", + "requires": { + "fbjs": "0.8.12" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "fbjs": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", + "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.2.0", + "object-assign": "4.1.0", + "promise": "7.1.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.12" + } + } + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "proxy-addr": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.2.tgz", + "integrity": "sha1-tMxfImENlTWCTBI675089zxAujc=", + "dev": true, + "requires": { + "forwarded": "0.1.0", + "ipaddr.js": "1.1.1" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, + "ps-tree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", + "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", + "dev": true, + "requires": { + "event-stream": "3.3.3" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "q-io": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.13.2.tgz", + "integrity": "sha1-7qEw1IHdteGqG8WmaFX3OR0G8AM=", + "dev": true, + "requires": { + "collections": "0.2.2", + "mime": "1.3.4", + "mimeparse": "0.1.4", + "q": "1.4.1", + "qs": "1.2.2", + "url2": "0.0.0" + }, + "dependencies": { + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=", + "dev": true + } + } + }, + "qs": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", + "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "dev": true + }, + "randomatic": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz", + "integrity": "sha1-Xp718tVzxnvSuBJK6QtRVuRXhAs=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "kind-of": "3.0.3" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "react": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/react/-/react-15.6.1.tgz", + "integrity": "sha1-uqhDTsZ4C96ZfNw4C3nNM7ljk98=", + "dev": true, + "requires": { + "create-react-class": "15.6.0", + "fbjs": "0.8.14", + "loose-envify": "1.2.0", + "object-assign": "4.1.0", + "prop-types": "15.5.10" + }, + "dependencies": { + "prop-types": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "dev": true, + "requires": { + "fbjs": "0.8.14", + "loose-envify": "1.3.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + } + } + } + } + }, + "react-addons-test-utils": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.0.tgz", + "integrity": "sha1-Bi02EX/o0Y87peBuszODsLhepbk=", + "dev": true + }, + "react-dom": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz", + "integrity": "sha1-LLDtQZEDjlPCCes6eaI+Kkz5lHA=", + "dev": true, + "requires": { + "fbjs": "0.8.14", + "loose-envify": "1.2.0", + "object-assign": "4.1.0", + "prop-types": "15.5.10" + }, + "dependencies": { + "prop-types": { + "version": "15.5.10", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "dev": true, + "requires": { + "fbjs": "0.8.14", + "loose-envify": "1.3.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + } + } + } + } + }, + "react-element-to-jsx-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-3.1.0.tgz", + "integrity": "sha1-8pgaRns6bJizRyelxDMWhs9Aagg=", + "dev": true, + "requires": { + "collapse-white-space": "1.0.0", + "is-plain-object": "2.0.1", + "lodash": "3.10.1", + "react-addons-test-utils": "15.6.0", + "sortobject": "1.1.1", + "stringify-object": "2.4.0", + "traverse": "0.6.6" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1", + "readable-stream": "2.1.4" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.3.5", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz", + "integrity": "sha1-cLl5HG/LhIDbRL0VWg9rtY8XJGg=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "minimatch": "3.0.2", + "readable-stream": "2.1.4", + "set-immediate-shim": "1.0.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regenerate": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", + "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz", + "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw=", + "dev": true + }, + "regenerator-transform": { + "version": "0.9.11", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", + "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "babel-types": "6.24.1", + "private": "0.1.7" + }, + "dependencies": { + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.10.3" + } + }, + "babel-types": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", + "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", + "dev": true, + "requires": { + "babel-runtime": "6.23.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.2" + } + }, + "regenerator-runtime": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", + "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "dev": true + } + } + }, + "regex-cache": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", + "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.2", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz", + "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.1" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.73.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.73.0.tgz", + "integrity": "sha1-X3ip/eQ3CryP9kedeoSnGhS4eKI=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.4.1", + "bl": "1.1.2", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.0", + "forever-agent": "0.6.1", + "form-data": "1.0.0-rc4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.11", + "node-uuid": "1.4.7", + "oauth-sign": "0.8.2", + "qs": "6.2.0", + "stringstream": "0.0.5", + "tough-cookie": "2.2.2", + "tunnel-agent": "0.4.3" + } + }, + "require-dir": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/require-dir/-/require-dir-0.1.0.tgz", + "integrity": "sha1-geAeKZ+vW3TDS2WU+OWt1Zhd3sU=", + "dev": true + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.3.tgz", + "integrity": "sha1-bl792kqi8DQX9rKldK7Cn0tlJwU=", + "dev": true, + "requires": { + "glob": "7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", + "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + } + } + }, + "ripemd160": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "run-async": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz", + "integrity": "sha1-h4Or2Dx7uG9B7gYC/IJASzvW6Lk=", + "dev": true, + "requires": { + "is-promise": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "run-auto": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/run-auto/-/run-auto-1.1.3.tgz", + "integrity": "sha1-wtUWP+wat4tjRc3TmS/OAy9nH4g=", + "dev": true, + "requires": { + "dezalgo": "1.0.3" + } + }, + "run-series": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.4.tgz", + "integrity": "sha1-iac93F51ye+KtjIMChYA1qQRebk=", + "dev": true + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "samsam": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", + "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "dev": true + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", + "dev": true + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "semantic-release": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-4.3.5.tgz", + "integrity": "sha1-33MZ57GMuYCCnpSS540ZYq9uORE=", + "dev": true, + "requires": { + "@semantic-release/commit-analyzer": "2.0.0", + "@semantic-release/condition-travis": "4.1.4", + "@semantic-release/error": "1.0.0", + "@semantic-release/last-release-npm": "1.2.1", + "@semantic-release/release-notes-generator": "2.0.0", + "git-head": "1.20.1", + "github": "0.2.4", + "lodash": "3.10.1", + "nerf-dart": "1.0.0", + "nopt": "3.0.6", + "npmconf": "2.1.2", + "npmlog": "1.2.1", + "parse-github-repo-url": "1.4.1", + "require-relative": "0.8.7", + "run-auto": "1.1.3", + "run-series": "1.1.4", + "semver": "5.4.1" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", + "dev": true + }, + "semver-truncate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", + "dev": true, + "requires": { + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + } + } + }, + "send": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "integrity": "sha1-qVSYQyU5L1FTKndgdg5FlZjIn3o=", + "dev": true, + "requires": { + "debug": "2.2.0", + "depd": "1.1.0", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.7.0", + "fresh": "0.3.0", + "http-errors": "1.5.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "serve-index": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.8.0.tgz", + "integrity": "sha1-fF2WwT+xMRAfk8HFd0+FFqHnjTs=", + "dev": true, + "requires": { + "accepts": "1.3.3", + "batch": "0.5.3", + "debug": "2.2.0", + "escape-html": "1.0.3", + "http-errors": "1.5.1", + "mime-types": "2.1.11", + "parseurl": "1.3.1" + } + }, + "serve-static": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz", + "integrity": "sha1-1sznaTUF9zPHWd5Xvvwa92wPCAU=", + "dev": true, + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.1", + "send": "0.14.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true, + "optional": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=", + "dev": true + }, + "sha.js": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz", + "integrity": "sha1-F93t3F9yL7ZlAWWIlUYZd4ZzFbo=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz", + "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g=", + "dev": true + }, + "sinon": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.4.tgz", + "integrity": "sha1-Tk/02Esgre4TE482rLEyyhzXLIM=", + "dev": true, + "requires": { + "formatio": "1.1.1", + "lolex": "1.3.2", + "samsam": "1.1.2", + "util": "0.10.3" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sockjs": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", + "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "dev": true, + "requires": { + "faye-websocket": "0.10.0", + "uuid": "2.0.3" + } + }, + "sockjs-client": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.1.tgz", + "integrity": "sha1-KEhD6al4TXxHSxVxsyQPyp3aS7A=", + "dev": true, + "requires": { + "debug": "2.2.0", + "eventsource": "0.1.6", + "faye-websocket": "0.11.0", + "inherits": "2.0.1", + "json3": "3.3.2", + "url-parse": "1.1.7" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.0.tgz", + "integrity": "sha1-2czw54nn23JddLxId9I6pClyrFA=", + "dev": true, + "requires": { + "websocket-driver": "0.6.5" + } + } + } + }, + "sortobject": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sortobject/-/sortobject-1.1.1.tgz", + "integrity": "sha1-T2ldTUTtCkwGSCw0wlgqLc3CqzQ=", + "dev": true, + "requires": { + "editions": "1.1.2" + } + }, + "source-list-map": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + "dev": true + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "source-map-support": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz", + "integrity": "sha1-nURjdyWYuGJxtPUj9sH04Cp9au8=", + "dev": true, + "requires": { + "source-map": "0.5.6" + } + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha1-lUThpDygRfhTGqwaSMspva5iM44=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.1" + } + }, + "spdx-exceptions": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz", + "integrity": "sha1-IguEI5EZrpBFqJLbgag/TOFvgP0=", + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", + "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=", + "dev": true, + "requires": { + "spdx-exceptions": "1.0.4", + "spdx-license-ids": "1.2.1" + } + }, + "spdx-license-ids": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.1.tgz", + "integrity": "sha1-0H6hek0v2TUfnZTi/5zsdBgP6PM=", + "dev": true + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2.3.8" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "squeak": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", + "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "console-stream": "0.1.1", + "lpad-align": "1.1.2" + } + }, + "sshpk": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz", + "integrity": "sha1-iQzJ1hTcUpLlyxpUOwPJq6pcN04=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "dashdash": "1.14.0", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.6", + "jodid25519": "1.0.2", + "jsbn": "0.1.0", + "tweetnacl": "0.13.3" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.1", + "readable-stream": "2.1.4" + } + }, + "stream-cache": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stream-cache/-/stream-cache-0.0.2.tgz", + "integrity": "sha1-GsWtaDJCjKVWZ9ve45Xa1ObbEY8=", + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "0.1.1" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.1.4" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.1.4" + } + } + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-http": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.0.tgz", + "integrity": "sha1-zsH047SUvEqBtFGAiXD4sgtO1fY=", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.1", + "readable-stream": "2.2.9", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz", + "integrity": "sha1-z3jsb0ptHrQ9JkiMrJfwQudLf8g=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.0", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.0.tgz", + "integrity": "sha1-8G9BFXtmTYYGn4S9vcmw2KsoFmc=", + "dev": true, + "requires": { + "buffer-shims": "1.0.0" + } + } + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string-width": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz", + "integrity": "sha1-ySEptvHX9SrPmvQkom44ZKBc6wo=", + "dev": true, + "requires": { + "code-point-at": "1.0.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string.prototype.padend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", + "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.5.1", + "function-bind": "1.1.0" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringify-object": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-2.4.0.tgz", + "integrity": "sha1-xi0RAj6yH+LZsIe+A5om3zsioJ0=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0", + "is-regexp": "1.0.0" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-dirs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", + "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", + "dev": true, + "requires": { + "chalk": "1.1.1", + "get-stdin": "4.0.1", + "is-absolute": "0.1.7", + "is-natural-number": "2.1.1", + "minimist": "1.2.0", + "sum-up": "1.0.3" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz", + "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "sum-up": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", + "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", + "dev": true, + "requires": { + "chalk": "1.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "dev": true, + "requires": { + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.1", + "whet.extend": "0.9.9" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "requires": { + "argparse": "1.0.7", + "esprima": "2.7.2" + } + } + } + }, + "symbol-tree": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.1.4.tgz", + "integrity": "sha1-ArJ5NI0zfevDlpTFyV+ILUSKMSo=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.2", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tapable": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz", + "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", + "dev": true + }, + "tar-stream": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", + "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", + "dev": true, + "requires": { + "bl": "1.1.2", + "end-of-stream": "1.4.0", + "readable-stream": "2.1.4", + "xtend": "4.0.1" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", + "dev": true, + "requires": { + "temp-dir": "1.0.0", + "uuid": "3.1.0" + }, + "dependencies": { + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", + "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", + "dev": true, + "requires": { + "readable-stream": "2.0.6", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + } + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.1", + "xtend": "4.0.1" + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.1" + } + }, + "time-stamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.0.1.tgz", + "integrity": "sha1-n0vSNVnJNllm8zAtu6KwfGuZsVE=", + "dev": true + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.2.tgz", + "integrity": "sha1-q0iDz1l9zVCvIRNJoA+8pWrIa4Y=", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + }, + "dependencies": { + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + } + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", + "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", + "dev": true + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + }, + "tough-cookie": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", + "integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc=", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz", + "integrity": "sha1-1ii1bzvMPVrnS6nUwacE3vWrS1Y=", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", + "dev": true + }, + "type-is": { + "version": "1.6.14", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz", + "integrity": "sha1-4hljnBfe0coHiQkt1UoDgmuBfLI=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.13" + }, + "dependencies": { + "mime-db": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz", + "integrity": "sha1-wY29fHOl2/b0SgJNwNFloeexw5I=", + "dev": true + }, + "mime-types": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.13.tgz", + "integrity": "sha1-4HqqnGxrmnyjASxpADrSWjnpKog=", + "dev": true, + "requires": { + "mime-db": "1.25.0" + } + } + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.12", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz", + "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=" + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "uid-number": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.5.tgz", + "integrity": "sha1-Wj2yPvXb1VuB/ODsmirG/M3ruB4=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.1.7.tgz", + "integrity": "sha1-Alz/mZZTpFmrNCMhR9iVFMyH10o=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "requires": { + "ip-regex": "1.0.3" + } + }, + "url2": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "v8flags": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.0.11.tgz", + "integrity": "sha1-vKjzDw1tYGEswsAGQeaWLUKuaIE=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.2" + } + }, + "vary": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz", + "integrity": "sha1-4eWv+70WrnaN0mdDlLmtMCJlMUA=", + "dev": true + }, + "verror": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", + "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", + "dev": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.2", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-assign": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", + "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", + "dev": true, + "requires": { + "object-assign": "4.1.0", + "readable-stream": "2.1.4" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.8", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz", + "integrity": "sha1-zoE+cl+oL35hR9UcmlymgnBVHCI=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.1", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "walk": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", + "integrity": "sha1-MbTbZnjyrgHDnqn7hyWpAx5Vins=", + "dev": true, + "requires": { + "foreachasync": "3.0.0" + } + }, + "ware": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", + "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", + "dev": true, + "requires": { + "wrap-fn": "0.1.5" + } + }, + "watchpack": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", + "integrity": "sha1-Yuqkq15bo1/fwBgnVibjwPXj+ws=", + "dev": true, + "requires": { + "async": "0.9.2", + "chokidar": "1.6.1", + "graceful-fs": "4.1.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, + "weak-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "integrity": "sha1-tm5Wqd8L0lp2u/G1FNsSkIBhSjc=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "webpack": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.15.0.tgz", + "integrity": "sha1-T/MfU9sDM55VFkqdRo7gMklo/pg=", + "dev": true, + "requires": { + "acorn": "3.3.0", + "async": "1.5.2", + "clone": "1.0.2", + "enhanced-resolve": "0.9.1", + "interpret": "0.6.6", + "loader-utils": "0.2.15", + "memory-fs": "0.3.0", + "mkdirp": "0.5.1", + "node-libs-browser": "0.7.0", + "optimist": "0.6.1", + "supports-color": "3.2.3", + "tapable": "0.1.10", + "uglify-js": "2.7.5", + "watchpack": "0.2.9", + "webpack-core": "0.6.9" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + }, + "uglify-js": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", + "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + } + } + }, + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "dev": true, + "requires": { + "source-list-map": "0.1.8", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.9.0.tgz", + "integrity": "sha1-ocZ6Pf2KXF1idAqgur5hdYtMhKo=", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.3.4", + "path-is-absolute": "1.0.0", + "range-parser": "1.2.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.4", + "readable-stream": "2.1.4" + } + } + } + }, + "webpack-dev-server": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-1.16.2.tgz", + "integrity": "sha1-i+vCxM4cRaFcct12nZugjbMGp5M=", + "dev": true, + "requires": { + "compression": "1.6.2", + "connect-history-api-fallback": "1.3.0", + "express": "4.14.0", + "http-proxy-middleware": "0.17.3", + "open": "0.0.5", + "optimist": "0.6.1", + "serve-index": "1.8.0", + "sockjs": "0.3.18", + "sockjs-client": "1.1.1", + "stream-cache": "0.0.2", + "strip-ansi": "3.0.1", + "supports-color": "3.1.2", + "webpack-dev-middleware": "1.9.0" + }, + "dependencies": { + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "requires": { + "websocket-extensions": "0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "dev": true + }, + "whatwg-fetch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz", + "integrity": "sha1-B4uUYbvpHOpzy86LsSKgX56St3I=" + }, + "whatwg-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-3.0.0.tgz", + "integrity": "sha1-uQM8UMfOdj6R14d3zoJabX9W2sU=", + "dev": true, + "requires": { + "tr46": "0.0.3", + "webidl-conversions": "3.0.1" + } + }, + "whatwg-url-compat": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", + "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", + "dev": true, + "optional": true, + "requires": { + "tr46": "0.0.3" + } + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz", + "integrity": "sha1-kc2b0HUTIkEbZZtA8FSyHelXqy0=", + "dev": true, + "requires": { + "isexe": "1.1.2" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "optional": true, + "requires": { + "code-point-at": "1.0.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "word-wrap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.1.0.tgz", + "integrity": "sha1-NWFT1h0QYQ1gB4XF1wEojgrnZKY=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-fn": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", + "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", + "dev": true, + "requires": { + "co": "3.1.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xml-name-validator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", + "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", + "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", + "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } + } + } +} From 1bb0f36fa36eadc0475c2dc02964f50cdf21c732 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 14:31:23 -0700 Subject: [PATCH 108/165] chore(-format): Use semicolons --- demo/Demo.js | 8 +- demo/components/SearchBar.js | 54 +++--- demo/index.js | 8 +- demo/tests/index.spec.js | 46 +++--- demo/webpack.config.js | 10 +- src/PlacesAutocomplete.js | 234 +++++++++++++------------- src/defaultStyles.js | 4 +- src/index.js | 8 +- src/tests/index.spec.js | 312 +++++++++++++++++------------------ src/tests/setup.js | 16 +- src/tests/testHelper.js | 20 +-- src/utils.js | 62 +++---- 12 files changed, 395 insertions(+), 387 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index e0675377..8e2cf36d 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -1,5 +1,5 @@ -import React from 'react' -import SearchBar from './components/SearchBar' +import React from 'react'; +import SearchBar from './components/SearchBar'; const Demo = () => (
@@ -25,6 +25,6 @@ const Demo = () => (
-) +); -export default Demo +export default Demo; diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index bc0e8c9f..e9875027 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,5 +1,5 @@ -import React, { Component } from 'react' -import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src' +import React, { Component } from 'react'; +import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src'; const renderSuggestion = ({ formattedSuggestion }) => (
@@ -7,7 +7,7 @@ const renderSuggestion = ({ formattedSuggestion }) => ( {formattedSuggestion.mainText}{' '} {formattedSuggestion.secondaryText}
-) +); const renderFooter = () => (
@@ -18,66 +18,66 @@ const renderFooter = () => ( />
-) +); const cssClasses = { root: 'form-group', input: 'Demo__search-input', autocompleteContainer: 'Demo__autocomplete-container', -} +}; -const shouldFetchSuggestions = ({ value }) => value.length > 2 +const shouldFetchSuggestions = ({ value }) => value.length > 2; const onError = (status, clearSuggestions) => { console.log( 'Error happened while fetching suggestions from Google Maps API', status - ) - clearSuggestions() -} + ); + clearSuggestions(); +}; class SearchBar extends Component { constructor(props) { - super(props) + super(props); this.state = { address: '', geocodeResults: null, loading: false, - } + }; - this.handleSelect = this.handleSelect.bind(this) - this.handleChange = this.handleChange.bind(this) + this.handleSelect = this.handleSelect.bind(this); + this.handleChange = this.handleChange.bind(this); } handleSelect(address) { this.setState({ address, loading: true, - }) + }); geocodeByAddress(address) .then(results => getLatLng(results[0])) .then(({ lat, lng }) => { - console.log('Geocode Success', { lat, lng }) + console.log('Geocode Success', { lat, lng }); this.setState({ geocodeResults: this.renderGeocodeSuccess(lat, lng), loading: false, - }) + }); }) .catch(error => { - console.log('Geocode Error', error) + console.log('Geocode Error', error); this.setState({ geocodeResults: this.renderGeocodeFailure(error), loading: false, - }) - }) + }); + }); } handleChange(address) { this.setState({ address, geocodeResults: null, - }) + }); } renderGeocodeFailure(err) { @@ -85,7 +85,7 @@ class SearchBar extends Component {
Error! {err}
- ) + ); } renderGeocodeSuccess(lat, lng) { @@ -96,7 +96,7 @@ class SearchBar extends Component { {lat}, {lng}
- ) + ); } render() { @@ -105,16 +105,16 @@ class SearchBar extends Component { value: this.state.address, onChange: this.handleChange, onBlur: () => { - console.log('Blur event!') + console.log('Blur event!'); }, onFocus: () => { - console.log('Focused!') + console.log('Focused!'); }, autoFocus: true, placeholder: 'Search Places', name: 'Demo__input', id: 'my-input-id', - } + }; return (
@@ -137,8 +137,8 @@ class SearchBar extends Component {
{this.state.geocodeResults}
)}
- ) + ); } } -export default SearchBar +export default SearchBar; diff --git a/demo/index.js b/demo/index.js index 25a60d85..95dbc279 100644 --- a/demo/index.js +++ b/demo/index.js @@ -1,5 +1,5 @@ -import React from 'react' -import ReactDOM from 'react-dom' -import Demo from './Demo' +import React from 'react'; +import ReactDOM from 'react-dom'; +import Demo from './Demo'; -ReactDOM.render(, document.getElementById('app')) +ReactDOM.render(, document.getElementById('app')); diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js index 875bd5b5..77172cd1 100644 --- a/demo/tests/index.spec.js +++ b/demo/tests/index.spec.js @@ -1,40 +1,40 @@ -import React from 'react' -import { mount, shallow } from 'enzyme' -import { expect } from '../../src/tests/testHelper' -import PlacesAutocomplete, { geocodeByAddress } from '../../src' -import Demo from '../Demo' +import React from 'react'; +import { mount, shallow } from 'enzyme'; +import { expect } from '../../src/tests/testHelper'; +import PlacesAutocomplete, { geocodeByAddress } from '../../src'; +import Demo from '../Demo'; describe('', () => { - let wrapper + let wrapper; beforeEach(() => { - wrapper = shallow() - }) + wrapper = shallow(); + }); it('renders a PlacesAutocomplete component', () => { - expect(wrapper.find(PlacesAutocomplete)).to.exist - }) + expect(wrapper.find(PlacesAutocomplete)).to.exist; + }); it('sets the value prop of the input element to state.address', () => { - const wrapper = mount() - wrapper.setState({ address: '123 Fake St' }) + const wrapper = mount(); + wrapper.setState({ address: '123 Fake St' }); expect(wrapper.find(PlacesAutocomplete).props().value).to.equal( '123 Fake St' - ) - }) + ); + }); it('renders loading animation when state.loading is true', () => { - wrapper.setState({ loading: true }) - expect(wrapper.find('.loader')).to.exist - }) + wrapper.setState({ loading: true }); + expect(wrapper.find('.loader')).to.exist; + }); it("doesn't initially render geocoding results", () => { - expect(wrapper.find('.geocoding-results')).to.not.exist - }) + expect(wrapper.find('.geocoding-results')).to.not.exist; + }); it('renders geocoding results when state.geocodeResults has value', () => { wrapper.setState({ geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456), - }) - expect(wrapper.find('.geocoding-results')).to.exist - }) -}) + }); + expect(wrapper.find('.geocoding-results')).to.exist; + }); +}); diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 6b0a5882..67928795 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -1,7 +1,7 @@ -var debug = process.env.NODE_ENV !== 'production' -var webpack = require('webpack') -var path = require('path') -var CopyWebpackPlugin = require('copy-webpack-plugin') +var debug = process.env.NODE_ENV !== 'production'; +var webpack = require('webpack'); +var path = require('path'); +var CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { entry: './demo/index.js', @@ -64,4 +64,4 @@ module.exports = { new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), ] : [], -} +}; diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 4a5e51f1..53c2cfa8 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -4,60 +4,60 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import debounce from 'lodash.debounce' -import defaultStyles from './defaultStyles' +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import debounce from 'lodash.debounce'; +import defaultStyles from './defaultStyles'; class PlacesAutocomplete extends Component { constructor(props) { - super(props) + super(props); this.state = { autocompleteItems: [], userInputValue: props.inputProps.value, - } + }; - this.autocompleteCallback = this.autocompleteCallback.bind(this) - this.handleInputKeyDown = this.handleInputKeyDown.bind(this) - this.handleInputChange = this.handleInputChange.bind(this) + this.autocompleteCallback = this.autocompleteCallback.bind(this); + this.handleInputKeyDown = this.handleInputKeyDown.bind(this); + this.handleInputChange = this.handleInputChange.bind(this); this.debouncedFetchPredictions = debounce( this.fetchPredictions, this.props.debounce - ) - this.clearSuggestions = this.clearSuggestions.bind(this) + ); + this.clearSuggestions = this.clearSuggestions.bind(this); } componentDidMount() { if (!window.google) { throw new Error( 'Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' - ) + ); } if (!window.google.maps.places) { throw new Error( 'Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' - ) + ); } - this.autocompleteService = new google.maps.places.AutocompleteService() - this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK + this.autocompleteService = new google.maps.places.AutocompleteService(); + this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK; } autocompleteCallback(predictions, status) { if (status !== this.autocompleteOK) { - this.props.onError(status, this.clearSuggestions) - return + this.props.onError(status, this.clearSuggestions); + return; } // transform snake_case to camelCase const formattedSuggestion = structured_formatting => ({ mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text, - }) + }); - const { highlightFirstSuggestion } = this.props + const { highlightFirstSuggestion } = this.props; this.setState({ autocompleteItems: predictions.map((p, idx) => ({ @@ -67,11 +67,11 @@ class PlacesAutocomplete extends Component { index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), })), - }) + }); } fetchPredictions() { - const { value } = this.props.inputProps + const { value } = this.props.inputProps; if (value.length) { this.autocompleteService.getPlacePredictions( { @@ -79,12 +79,12 @@ class PlacesAutocomplete extends Component { input: value, }, this.autocompleteCallback - ) + ); } } clearSuggestions() { - this.setState({ autocompleteItems: [] }) + this.setState({ autocompleteItems: [] }); } clearActive() { @@ -93,109 +93,109 @@ class PlacesAutocomplete extends Component { ...item, active: false, })), - }) + }); } selectAddress(address, placeId, e) { if (e !== undefined) { - e.preventDefault() + e.preventDefault(); } - this.clearSuggestions() - this.handleSelect(address, placeId) + this.clearSuggestions(); + this.handleSelect(address, placeId); } handleSelect(address, placeId) { this.props.onSelect ? this.props.onSelect(address, placeId) - : this.props.inputProps.onChange(address) + : this.props.inputProps.onChange(address); } getActiveItem() { - return this.state.autocompleteItems.find(item => item.active) + return this.state.autocompleteItems.find(item => item.active); } selectActiveItemAtIndex(index) { const activeName = this.state.autocompleteItems.find( item => item.index === index - ).suggestion - this.setActiveItemAtIndex(index) - this.props.inputProps.onChange(activeName) + ).suggestion; + this.setActiveItemAtIndex(index); + this.props.inputProps.onChange(activeName); } selectUserInputValue() { - this.clearActive() - this.props.inputProps.onChange(this.state.userInputValue) + this.clearActive(); + this.props.inputProps.onChange(this.state.userInputValue); } handleEnterKey() { - const activeItem = this.getActiveItem() + const activeItem = this.getActiveItem(); if (activeItem === undefined) { - this.handleEnterKeyWithoutActiveItem() + this.handleEnterKeyWithoutActiveItem(); } else { - this.selectAddress(activeItem.suggestion, activeItem.placeId) + this.selectAddress(activeItem.suggestion, activeItem.placeId); } } handleEnterKeyWithoutActiveItem() { if (this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(this.props.inputProps.value) - this.clearSuggestions() + this.props.onEnterKeyDown(this.props.inputProps.value); + this.clearSuggestions(); } else { - return //noop + return; //noop } } handleDownKey() { if (this.state.autocompleteItems.length === 0) { - return + return; } - const activeItem = this.getActiveItem() + const activeItem = this.getActiveItem(); if (activeItem === undefined) { - this.selectActiveItemAtIndex(0) + this.selectActiveItemAtIndex(0); } else if (activeItem.index === this.state.autocompleteItems.length - 1) { - this.selectUserInputValue() + this.selectUserInputValue(); } else { - this.selectActiveItemAtIndex(activeItem.index + 1) + this.selectActiveItemAtIndex(activeItem.index + 1); } } handleUpKey() { if (this.state.autocompleteItems.length === 0) { - return + return; } - const activeItem = this.getActiveItem() + const activeItem = this.getActiveItem(); if (activeItem === undefined) { - this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1) + this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1); } else if (activeItem.index === 0) { - this.selectUserInputValue() + this.selectUserInputValue(); } else { - this.selectActiveItemAtIndex(activeItem.index - 1) + this.selectActiveItemAtIndex(activeItem.index - 1); } } handleInputKeyDown(event) { switch (event.key) { case 'Enter': - event.preventDefault() - this.handleEnterKey() - break + event.preventDefault(); + this.handleEnterKey(); + break; case 'ArrowDown': - event.preventDefault() // prevent the cursor from moving - this.handleDownKey() - break + event.preventDefault(); // prevent the cursor from moving + this.handleDownKey(); + break; case 'ArrowUp': - event.preventDefault() // prevent the cursor from moving - this.handleUpKey() - break + event.preventDefault(); // prevent the cursor from moving + this.handleUpKey(); + break; case 'Escape': - this.clearSuggestions() - break + this.clearSuggestions(); + break; } if (this.props.inputProps.onKeyDown) { - this.props.inputProps.onKeyDown(event) + this.props.inputProps.onKeyDown(event); } } @@ -203,42 +203,42 @@ class PlacesAutocomplete extends Component { this.setState({ autocompleteItems: this.state.autocompleteItems.map((item, idx) => { if (idx === index) { - return { ...item, active: true } + return { ...item, active: true }; } else { - return { ...item, active: false } + return { ...item, active: false }; } }), - }) + }); } handleInputChange(event) { - const { value } = event.target - this.props.inputProps.onChange(value) - this.setState({ userInputValue: value }) + const { value } = event.target; + this.props.inputProps.onChange(value); + this.setState({ userInputValue: value }); if (!value) { - this.clearSuggestions() - return + this.clearSuggestions(); + return; } if (this.props.shouldFetchSuggestions({ value })) { - this.debouncedFetchPredictions() + this.debouncedFetchPredictions(); } } handleInputOnBlur(event) { if (!this.mousedownOnSuggestion) { - this.clearSuggestions() + this.clearSuggestions(); } if (this.props.inputProps.onBlur) { - this.props.inputProps.onBlur(event) + this.props.inputProps.onBlur(event); } } inlineStyleFor(...props) { - const { classNames, styles } = this.props + const { classNames, styles } = this.props; // No inline style if className is passed via props for the element. if (props.some(prop => classNames.hasOwnProperty(prop))) { - return {} + return {}; } return props.reduce((acc, prop) => { @@ -246,88 +246,90 @@ class PlacesAutocomplete extends Component { ...acc, ...defaultStyles[prop], ...styles[prop], - } - }, {}) + }; + }, {}); } classNameFor(...props) { - const { classNames } = this.props + const { classNames } = this.props; return props.reduce((acc, prop) => { - const name = classNames[prop] || '' - return name ? `${acc} ${name}` : acc - }, '') + const name = classNames[prop] || ''; + return name ? `${acc} ${name}` : acc; + }, ''); } shouldRenderDropdown() { - return this.state.autocompleteItems.length > 0 + return this.state.autocompleteItems.length > 0; } getInputProps() { - const isExpanded = this.shouldRenderDropdown() - const activeItem = this.getActiveItem() - const activeItemId = activeItem ? `PlacesAutocomplete__autocomplete-item-${activeItem.placeId}` : null + const isExpanded = this.shouldRenderDropdown(); + const activeItem = this.getActiveItem(); + const activeItemId = activeItem + ? `PlacesAutocomplete__autocomplete-item-${activeItem.placeId}` + : null; const defaultInputProps = { type: 'text', autoComplete: 'off', role: 'combobox', 'aria-autocomplete': 'list', - 'aria-controls': "PlacesAutocomplete__autocomplete-container", + 'aria-controls': 'PlacesAutocomplete__autocomplete-container', 'aria-expanded': isExpanded, 'aria-haspopup': isExpanded, 'aria-activedescendant': activeItemId, - } + }; return { ...defaultInputProps, ...this.props.inputProps, onChange: event => { - this.handleInputChange(event) + this.handleInputChange(event); }, onKeyDown: event => { - this.handleInputKeyDown(event) + this.handleInputKeyDown(event); }, onBlur: event => { - this.handleInputOnBlur(event) + this.handleInputOnBlur(event); }, style: this.inlineStyleFor('input'), className: this.classNameFor('input'), - } + }; } handleSuggestionMouseEnter(index) { - this.setActiveItemAtIndex(index) + this.setActiveItemAtIndex(index); } handleSuggestionMouseLeave() { - this.mousedownOnSuggestion = false - this.clearActive() + this.mousedownOnSuggestion = false; + this.clearActive(); } handleSuggestionMouseDown(event) { - event.preventDefault() - this.mousedownOnSuggestion = true + event.preventDefault(); + this.mousedownOnSuggestion = true; } handleSuggestionTouchStart() { - this.mousedownOnSuggestion = true + this.mousedownOnSuggestion = true; } handleSuggestionMouseUp() { - this.mousedownOnSuggestion = false + this.mousedownOnSuggestion = false; } handleSuggestionClick(prediction, event) { - const { suggestion, placeId } = prediction - this.selectAddress(suggestion, placeId, event) + const { suggestion, placeId } = prediction; + this.selectAddress(suggestion, placeId, event); setTimeout(() => { - this.mousedownOnSuggestion = false - }) + this.mousedownOnSuggestion = false; + }); } render() { - const { autocompleteItems } = this.state - const inputProps = this.getInputProps() + const { autocompleteItems } = this.state; + const inputProps = this.getInputProps(); return (
@@ -376,20 +384,20 @@ class PlacesAutocomplete extends Component {
)}
- ) + ); } } PlacesAutocomplete.propTypes = { inputProps: (props, propName) => { - const inputProps = props[propName] + const inputProps = props[propName]; if (!inputProps.hasOwnProperty('value')) { - throw new Error("'inputProps' must have 'value'.") + throw new Error("'inputProps' must have 'value'."); } if (!inputProps.hasOwnProperty('onChange')) { - throw new Error("'inputProps' must have 'onChange'.") + throw new Error("'inputProps' must have 'onChange'."); } }, onError: PropTypes.func, @@ -421,7 +429,7 @@ PlacesAutocomplete.propTypes = { highlightFirstSuggestion: PropTypes.bool, renderFooter: PropTypes.func, shouldFetchSuggestions: PropTypes.func.isRequired, -} +}; PlacesAutocomplete.defaultProps = { onError: (status, _clearSuggestions) => @@ -436,6 +444,6 @@ PlacesAutocomplete.defaultProps = { debounce: 200, highlightFirstSuggestion: false, shouldFetchSuggestions: () => true, -} +}; -export default PlacesAutocomplete +export default PlacesAutocomplete; diff --git a/src/defaultStyles.js b/src/defaultStyles.js index faeef3d4..d70ebff6 100644 --- a/src/defaultStyles.js +++ b/src/defaultStyles.js @@ -24,6 +24,6 @@ const defaultStyles = { autocompleteItemActive: { backgroundColor: '#fafafa', }, -} +}; -export default defaultStyles +export default defaultStyles; diff --git a/src/index.js b/src/index.js index 0968ecf0..5b16b731 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ -import PlacesAutocomplete from './PlacesAutocomplete' -import { geocodeByAddress, geocodeByPlaceId, getLatLng } from './utils' +import PlacesAutocomplete from './PlacesAutocomplete'; +import { geocodeByAddress, geocodeByPlaceId, getLatLng } from './utils'; -export { geocodeByAddress, geocodeByPlaceId, getLatLng } +export { geocodeByAddress, geocodeByPlaceId, getLatLng }; -export default PlacesAutocomplete +export default PlacesAutocomplete; diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 5e931494..ab290386 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,67 +1,67 @@ -import React from 'react' -import TestUtils from 'react-addons-test-utils' -import { mount, shallow } from 'enzyme' -import sinon from 'sinon' -import { expect } from './testHelper' -import PlacesAutocomplete, { geocodeByAddress } from '../index.js' +import React from 'react'; +import TestUtils from 'react-addons-test-utils'; +import { mount, shallow } from 'enzyme'; +import sinon from 'sinon'; +import { expect } from './testHelper'; +import PlacesAutocomplete, { geocodeByAddress } from '../index.js'; const testInputProps = { value: 'San Francisco, CA', onChange: () => {}, -} +}; /*** Enzyme Rocks ***/ describe('', () => { - let wrapper + let wrapper; beforeEach(() => { - wrapper = shallow() - }) + wrapper = shallow(); + }); it('renders an input element', () => { - expect(wrapper.find('input')).to.have.length(1) - }) -}) + expect(wrapper.find('input')).to.have.length(1); + }); +}); // TODO: What's the value of this test? describe('PlacesAutocomplete callbacks', () => { it('executes onError callback passed in as prop when status is not OK', () => { - const spy = sinon.spy() + const spy = sinon.spy(); const wrapper = mount( - ) - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(spy.calledOnce).to.equal(true) - expect(spy.calledWith('ZERO_RESULTS')).to.equal(true) - }) + ); + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); + expect(spy.calledOnce).to.equal(true); + expect(spy.calledWith('ZERO_RESULTS')).to.equal(true); + }); it('executes default onError function when there is no custom prop and status is not OK', () => { - sinon.stub(console, 'error') - const wrapper = mount() - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(console.error.calledOnce).to.equal(true) - }) -}) + sinon.stub(console, 'error'); + const wrapper = mount(); + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); + expect(console.error.calledOnce).to.equal(true); + }); +}); describe('PlacesAutocomplete props', () => { it('allows user to set the value of the input through prop', () => { const inputProps = { ...testInputProps, value: 'New York, NY', - } + }; - const wrapper = mount() - expect(wrapper.find('input').props().value).to.equal('New York, NY') - }) -}) + const wrapper = mount(); + expect(wrapper.find('input').props().value).to.equal('New York, NY'); + }); +}); describe('autocomplete dropdown', () => { - let wrapper + let wrapper; const renderSuggestion = ({ suggestion }) => (
{suggestion}
- ) + ); const renderFooter = () => (
Footer element
- ) + ); beforeEach(() => { wrapper = shallow( { renderSuggestion={renderSuggestion} renderFooter={renderFooter} /> - ) - }) + ); + }); it('initially does not have an autocomplete dropdown', () => { expect( wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.length(0) - }) + ).to.have.length(0); + }); it('renders autocomplete dropdown once it receives data from google maps', () => { const data = [ @@ -98,14 +98,14 @@ describe('autocomplete dropdown', () => { active: false, index: 2, }, - ] - wrapper.setState({ autocompleteItems: data }) + ]; + wrapper.setState({ autocompleteItems: data }); expect( wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.length(1) - expect(wrapper.find('.autocomplete-item')).to.have.length(3) - expect(wrapper.find('.my-dropdown-footer')).to.have.length(1) - }) + ).to.have.length(1); + expect(wrapper.find('.autocomplete-item')).to.have.length(3); + expect(wrapper.find('.my-dropdown-footer')).to.have.length(1); + }); it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { const initialItems = [ @@ -115,17 +115,17 @@ describe('autocomplete dropdown', () => { active: false, index: 0, }, - ] + ]; const wrapper = shallow( - ) - wrapper.setState({ autocompleteItems: initialItems }) - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(wrapper.find('.autocomplete-item')).to.have.length(0) - }) + ); + wrapper.setState({ autocompleteItems: initialItems }); + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); + expect(wrapper.find('.autocomplete-item')).to.have.length(0); + }); it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { const initialItems = [ @@ -135,40 +135,40 @@ describe('autocomplete dropdown', () => { active: false, index: 0, }, - ] - wrapper.setState({ autocompleteItems: initialItems }) - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS') - expect(wrapper.find('.autocomplete-item')).to.have.length(1) - }) -}) + ]; + wrapper.setState({ autocompleteItems: initialItems }); + wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); + expect(wrapper.find('.autocomplete-item')).to.have.length(1); + }); +}); describe('custom classNames, placeholder', () => { const inputProps = { ...testInputProps, placeholder: 'Your Address', - } + }; const classNames = { root: 'my-container', input: 'my-input', autocompleteContainer: 'my-autocomplete-container', - } + }; - let wrapper + let wrapper; beforeEach(() => { wrapper = shallow( - ) - }) + ); + }); it('lets you set a custom className for the container', () => { - expect(wrapper.find('.my-container')).to.have.length(1) - }) + expect(wrapper.find('.my-container')).to.have.length(1); + }); it('lets you set a custom className for the input', () => { - expect(wrapper.find('input')).to.have.className('my-input') - }) + expect(wrapper.find('input')).to.have.className('my-input'); + }); it('lets you set a custom className for autocomplete container', () => { wrapper.setState({ @@ -180,16 +180,16 @@ describe('custom classNames, placeholder', () => { index: 0, }, ], - }) + }); expect( wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.className('my-autocomplete-container') - }) + ).to.have.className('my-autocomplete-container'); + }); it('lets you set a custom placeholder for the input', () => { - expect(wrapper.find('input').props().placeholder).to.equal('Your Address') - }) -}) + expect(wrapper.find('input').props().placeholder).to.equal('Your Address'); + }); +}); // TODO: test formattedSuggestion describe('customizable autocompleteItem', () => { @@ -198,13 +198,13 @@ describe('customizable autocompleteItem', () => {
- ) + ); const wrapper = shallow( - ) + ); wrapper.setState({ autocompleteItems: [ { @@ -214,13 +214,13 @@ describe('customizable autocompleteItem', () => { index: 0, }, ], - }) - expect(wrapper.find('.my-autocomplete-item')).to.have.length(1) + }); + expect(wrapper.find('.my-autocomplete-item')).to.have.length(1); expect(wrapper.find('.my-autocomplete-item')).to.contain( - ) - }) -}) + ); + }); +}); describe('custom inline styles', () => { const styles = { @@ -229,24 +229,24 @@ describe('custom inline styles', () => { autocompleteContainer: { backgroundColor: 'green' }, autocompleteItem: { color: 'black' }, autocompleteItemActive: { color: 'blue' }, - } + }; - let wrapper + let wrapper; beforeEach(() => { wrapper = shallow( - ) - }) + ); + }); it('lets you set custom styles for the root element', () => { expect( wrapper.find('#PlacesAutocomplete__root').props().style.position - ).to.equal('absolute') - }) + ).to.equal('absolute'); + }); it('lets you set custom styles for the input element', () => { - expect(wrapper.find('input').props().style.width).to.equal('100%') - }) + expect(wrapper.find('input').props().style.width).to.equal('100%'); + }); it('lets you set custom styles for the autocomplete container element', () => { wrapper.setState({ @@ -258,12 +258,12 @@ describe('custom inline styles', () => { index: 0, }, ], - }) + }); expect( wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style .backgroundColor - ).to.equal('green') - }) + ).to.equal('green'); + }); it('lets you set custom styles for autocomplete items', () => { wrapper.setState({ @@ -275,71 +275,71 @@ describe('custom inline styles', () => { index: 0, }, ], - }) + }); const item = wrapper .find('#PlacesAutocomplete__autocomplete-container') - .childAt(0) - expect(item.props().style.color).to.equal('black') - }) + .childAt(0); + expect(item.props().style.color).to.equal('black'); + }); it('lets you set custom styles for active autocomplete items', () => { wrapper.setState({ autocompleteItems: [ { suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }, ], - }) + }); const item = wrapper .find('#PlacesAutocomplete__autocomplete-container') - .childAt(0) - expect(item.props().style.color).to.equal('blue') - }) -}) + .childAt(0); + expect(item.props().style.color).to.equal('blue'); + }); +}); describe('AutocompletionRequest options', () => { const inputProps = { ...testInputProps, value: 'Boston, MA', - } + }; it('calls getPlacePredictions with the correct options', done => { global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = ( request, callback - ) => {} + ) => {}; const spy = sinon.spy( global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions' - ) - const options = { radius: 2000, types: ['address'] } + ); + const options = { radius: 2000, types: ['address'] }; const wrapper = mount( - ) + ); wrapper .find('input') - .simulate('change', { target: { value: 'Los Angeles, CA' } }) + .simulate('change', { target: { value: 'Los Angeles, CA' } }); setTimeout(() => { - done() + done(); expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be - .true - }, 0) - }) -}) + .true; + }, 0); + }); +}); describe('autoFocus prop', () => { const inputProps = { ...testInputProps, autoFocus: true, - } + }; it('automatically gives focus when set to true', () => { - const wrapper = mount() - expect(wrapper.find('input').node).to.equal(document.activeElement) - }) + const wrapper = mount(); + expect(wrapper.find('input').node).to.equal(document.activeElement); + }); it('does not give the input element a focus by default', () => { - const wrapper = mount() - expect(wrapper.find('input').node).to.not.equal(document.activeElement) - }) -}) + const wrapper = mount(); + expect(wrapper.find('input').node).to.not.equal(document.activeElement); + }); +}); describe("Enables using original input's value as it was another entry in autocomplete", () => { const data = [ @@ -361,85 +361,85 @@ describe("Enables using original input's value as it was another entry in autoco active: false, index: 2, }, - ] - const spy = sinon.spy() + ]; + const spy = sinon.spy(); const inputProps = { value: 'san', onChange: spy, - } - let wrapper + }; + let wrapper; beforeEach(() => { - wrapper = shallow() - spy.reset() - }) + wrapper = shallow(); + spy.reset(); + }); it('save value of input when pressing arrow down key and none of autocomplete entries is being focused', () => { - wrapper.setState({ autocompleteItems: data }) + wrapper.setState({ autocompleteItems: data }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) - expect(wrapper.state().userInputValue).to.equal('san') - }) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); + expect(wrapper.state().userInputValue).to.equal('san'); + }); it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { - wrapper.setState({ autocompleteItems: data }) + wrapper.setState({ autocompleteItems: data }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }) - expect(wrapper.state().userInputValue).to.equal('san') - }) + .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); + expect(wrapper.state().userInputValue).to.equal('san'); + }); it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { const lastItemActive = data.map((item, idx) => { - return idx === data.length - 1 ? { ...item, active: true } : item - }) - wrapper.setState({ autocompleteItems: lastItemActive }) + return idx === data.length - 1 ? { ...item, active: true } : item; + }); + wrapper.setState({ autocompleteItems: lastItemActive }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); wrapper.state().autocompleteItems.forEach(item => { - expect(item.active).to.be.false - }) - }) + expect(item.active).to.be.false; + }); + }); it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { const firstItemActive = data.map((item, idx) => { - return idx === 0 ? { ...item, active: true } : item - }) - wrapper.setState({ autocompleteItems: firstItemActive }) + return idx === 0 ? { ...item, active: true } : item; + }); + wrapper.setState({ autocompleteItems: firstItemActive }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }) + .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); wrapper.state().autocompleteItems.forEach(item => { - expect(item.active).to.be.false - }) - }) + expect(item.active).to.be.false; + }); + }); it('onChange function is called with appropriate value', () => { // Amount of entries is 3 for this test case, so when we press arrow down fourth time // we expect onChange function to be called with original input value // being stored in `userInputValue` state entry // rest of calls should be called with appropraite entries from autocomplete items - wrapper.setState({ autocompleteItems: data }) + wrapper.setState({ autocompleteItems: data }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); wrapper .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }) - expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion) - expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion) - expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion) - expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue) - }) -}) + .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); + expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion); + expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion); + expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion); + expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue); + }); +}); // TODOs: // * Test geocodeByAddress function diff --git a/src/tests/setup.js b/src/tests/setup.js index 1ef28bc9..db0c1eb2 100644 --- a/src/tests/setup.js +++ b/src/tests/setup.js @@ -5,20 +5,20 @@ // 3. Registers babel for transpiling our code for testing. // This assures the .babelrc dev config doesn't apply for tests. -process.env.NODE_ENV = 'production' +process.env.NODE_ENV = 'production'; // Disable webpack-specific features for tests since // Mocha doesn't know what to do with them. require.extensions['.css'] = function() { - return null -} + return null; +}; require.extensions['.png'] = function() { - return null -} + return null; +}; require.extensions['.jpg'] = function() { - return null -} + return null; +}; // Register babel so that it will transpile ES6 to ES5 // before our tests run. -require('babel-register')() +require('babel-register')(); diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js index e4cb004a..7c0292e4 100644 --- a/src/tests/testHelper.js +++ b/src/tests/testHelper.js @@ -1,10 +1,10 @@ -import chai, { expect } from 'chai' -import chaiEnzyme from 'chai-enzyme' -import jsdom from 'jsdom' +import chai, { expect } from 'chai'; +import chaiEnzyme from 'chai-enzyme'; +import jsdom from 'jsdom'; /*** Set up test environment to run in a browser-like environment ***/ -global.document = jsdom.jsdom('') -global.window = global.document.defaultView +global.document = jsdom.jsdom(''); +global.window = global.document.defaultView; /*** Mock Google Maps JavaScript API ***/ const google = { @@ -16,10 +16,10 @@ const google = { }, }, }, -} -global.google = google -global.window.google = google +}; +global.google = google; +global.window.google = google; -chai.use(chaiEnzyme()) +chai.use(chaiEnzyme()); -export { expect } +export { expect }; diff --git a/src/utils.js b/src/utils.js index 5f91416a..25ef3771 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ export const geocodeByAddress = (address, callback) => { - const geocoder = new google.maps.Geocoder() - const OK = google.maps.GeocoderStatus.OK + const geocoder = new google.maps.Geocoder(); + const OK = google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ address }, (results, status) => { @@ -9,12 +9,12 @@ export const geocodeByAddress = (address, callback) => { if (callback) { console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' - ) - callback({ status }, null, results) - return + ); + callback({ status }, null, results); + return; } - reject(status) + reject(status); } // TODO: Remove callback support in the next major version. @@ -22,17 +22,17 @@ export const geocodeByAddress = (address, callback) => { const latLng = { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), - } + }; console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' - ) - callback(null, latLng, results) + ); + callback(null, latLng, results); } - resolve(results) - }) - }) -} + resolve(results); + }); + }); +}; export const getLatLng = result => { return new Promise((resolve, reject) => { @@ -40,17 +40,17 @@ export const getLatLng = result => { const latLng = { lat: result.geometry.location.lat(), lng: result.geometry.location.lng(), - } - resolve(latLng) + }; + resolve(latLng); } catch (e) { - reject(e) + reject(e); } - }) -} + }); +}; export const geocodeByPlaceId = (placeId, callback) => { - const geocoder = new google.maps.Geocoder() - const OK = google.maps.GeocoderStatus.OK + const geocoder = new google.maps.Geocoder(); + const OK = google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ placeId }, (results, status) => { @@ -59,12 +59,12 @@ export const geocodeByPlaceId = (placeId, callback) => { if (callback) { console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' - ) - callback({ status }, null, results) - return + ); + callback({ status }, null, results); + return; } - reject(status) + reject(status); } // TODO: Remove callback support in the next major version. @@ -72,14 +72,14 @@ export const geocodeByPlaceId = (placeId, callback) => { const latLng = { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), - } + }; console.warn( 'Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' - ) - callback(null, latLng, results) + ); + callback(null, latLng, results); } - resolve(results) - }) - }) -} + resolve(results); + }); + }); +}; From e245263ac5c843f2d870648f8a92822845d6ddaa Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 14:42:33 -0700 Subject: [PATCH 109/165] chore(eslint): Add eslint-plugin-react --- .eslintrc.json | 9 ++++++--- package.json | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index f0731c89..fefe9315 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,7 +4,10 @@ "es6": true, "node": true }, - "extends": "eslint:recommended", + "extends": [ + "eslint:recommended", + "plugin:react/recommended" + ], "parserOptions": { "ecmaFeatures": { "experimentalObjectRestSpread": true, @@ -18,7 +21,7 @@ "rules": { "indent": [ "error", - 4 + 2 ], "linebreak-style": [ "error", @@ -33,4 +36,4 @@ "always" ] } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 72afd898..3385a110 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "demo:deploy": "gh-pages -d demo/dist", "postpublish": "npm run demo:deploy", "prettier": "prettier --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"", - "lint": "eslint src/**/*.js demo/**/*.js" + "lint": "eslint src/**/*.js demo/**/*.js", + "lint:fix": "eslint --fix src/**/*.js demo/**/*.js" }, "repository": { "type": "git", From 1688859ab6de651eda52dd2cef41d4a2514f4d28 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 14:43:54 -0700 Subject: [PATCH 110/165] chore(format): Fix ESlint errors --- .eslintignore | 3 + .eslintrc.json | 5 +- demo/Demo.js | 61 ++++++++-------- demo/components/SearchBar.js | 12 ++-- demo/index.js | 10 +-- demo/tests/index.spec.js | 80 ++++++++++----------- demo/webpack.config.js | 132 +++++++++++++++++------------------ package.json | 4 +- src/PlacesAutocomplete.js | 58 +++++++-------- src/SuggestionItem.js | 12 ++++ src/tests/index.spec.js | 18 +++-- src/utils.js | 16 +++-- webpack.config.babel.js | 6 +- 13 files changed, 222 insertions(+), 195 deletions(-) create mode 100644 .eslintignore create mode 100644 src/SuggestionItem.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..1b780ffb --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +dist +node_modules +**/*.min.js diff --git a/.eslintrc.json b/.eslintrc.json index fefe9315..6555b9c8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,11 +2,12 @@ "env": { "browser": true, "es6": true, - "node": true + "node": true, + "mocha": true }, "extends": [ "eslint:recommended", - "plugin:react/recommended" + "plugin:react/recommended" ], "parserOptions": { "ecmaFeatures": { diff --git a/demo/Demo.js b/demo/Demo.js index 8e2cf36d..ed878d50 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -1,30 +1,31 @@ -import React from 'react'; -import SearchBar from './components/SearchBar'; - -const Demo = () => ( -
-
-

- react-places-autocomplete -

-

- A React component to build a customized UI for Google Maps Places - Autocomplete -

-
- - -  View on GitHub - -
-
- -
-
-); - -export default Demo; +import React from 'react'; +import SearchBar from './components/SearchBar'; + +const Demo = () => ( +
+
+

+ react-places-autocomplete +

+

+ A React component to build a customized UI for Google Maps Places + Autocomplete +

+
+ + +  View on GitHub + +
+
+ +
+
+); + +export default Demo; diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index e9875027..2109d21a 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,6 +1,7 @@ import React, { Component } from 'react'; import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src'; +/* eslint-disable react/prop-types */ const renderSuggestion = ({ formattedSuggestion }) => (
@@ -8,6 +9,7 @@ const renderSuggestion = ({ formattedSuggestion }) => ( {formattedSuggestion.secondaryText}
); +/* eslint-enable react/prop-types */ const renderFooter = () => (
@@ -29,10 +31,12 @@ const cssClasses = { const shouldFetchSuggestions = ({ value }) => value.length > 2; const onError = (status, clearSuggestions) => { + /* eslint-disable no-console */ console.log( 'Error happened while fetching suggestions from Google Maps API', status ); + /* eslint-enable no-console */ clearSuggestions(); }; @@ -58,14 +62,14 @@ class SearchBar extends Component { geocodeByAddress(address) .then(results => getLatLng(results[0])) .then(({ lat, lng }) => { - console.log('Geocode Success', { lat, lng }); + console.log('Geocode Success', { lat, lng }); // eslint-disable-line no-console this.setState({ geocodeResults: this.renderGeocodeSuccess(lat, lng), loading: false, }); }) .catch(error => { - console.log('Geocode Error', error); + console.log('Geocode Error', error); // eslint-disable-line no-console this.setState({ geocodeResults: this.renderGeocodeFailure(error), loading: false, @@ -105,10 +109,10 @@ class SearchBar extends Component { value: this.state.address, onChange: this.handleChange, onBlur: () => { - console.log('Blur event!'); + console.log('Blur event!'); // eslint-disable-line no-console }, onFocus: () => { - console.log('Focused!'); + console.log('Focused!'); // eslint-disable-line no-console }, autoFocus: true, placeholder: 'Search Places', diff --git a/demo/index.js b/demo/index.js index 95dbc279..c7d41096 100644 --- a/demo/index.js +++ b/demo/index.js @@ -1,5 +1,5 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import Demo from './Demo'; - -ReactDOM.render(, document.getElementById('app')); +import React from 'react'; +import ReactDOM from 'react-dom'; +import Demo from './Demo'; + +ReactDOM.render(, document.getElementById('app')); diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js index 77172cd1..5c42f917 100644 --- a/demo/tests/index.spec.js +++ b/demo/tests/index.spec.js @@ -1,40 +1,40 @@ -import React from 'react'; -import { mount, shallow } from 'enzyme'; -import { expect } from '../../src/tests/testHelper'; -import PlacesAutocomplete, { geocodeByAddress } from '../../src'; -import Demo from '../Demo'; - -describe('', () => { - let wrapper; - beforeEach(() => { - wrapper = shallow(); - }); - - it('renders a PlacesAutocomplete component', () => { - expect(wrapper.find(PlacesAutocomplete)).to.exist; - }); - - it('sets the value prop of the input element to state.address', () => { - const wrapper = mount(); - wrapper.setState({ address: '123 Fake St' }); - expect(wrapper.find(PlacesAutocomplete).props().value).to.equal( - '123 Fake St' - ); - }); - - it('renders loading animation when state.loading is true', () => { - wrapper.setState({ loading: true }); - expect(wrapper.find('.loader')).to.exist; - }); - - it("doesn't initially render geocoding results", () => { - expect(wrapper.find('.geocoding-results')).to.not.exist; - }); - - it('renders geocoding results when state.geocodeResults has value', () => { - wrapper.setState({ - geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456), - }); - expect(wrapper.find('.geocoding-results')).to.exist; - }); -}); +import React from 'react'; +import { mount, shallow } from 'enzyme'; +import { expect } from '../../src/tests/testHelper'; +import PlacesAutocomplete from '../../src'; +import Demo from '../Demo'; + +describe('', () => { + let wrapper; + beforeEach(() => { + wrapper = shallow(); + }); + + it('renders a PlacesAutocomplete component', () => { + expect(wrapper.find(PlacesAutocomplete)).to.exist; + }); + + it('sets the value prop of the input element to state.address', () => { + const wrapper = mount(); + wrapper.setState({ address: '123 Fake St' }); + expect(wrapper.find(PlacesAutocomplete).props().value).to.equal( + '123 Fake St' + ); + }); + + it('renders loading animation when state.loading is true', () => { + wrapper.setState({ loading: true }); + expect(wrapper.find('.loader')).to.exist; + }); + + it('doesn\'t initially render geocoding results', () => { + expect(wrapper.find('.geocoding-results')).to.not.exist; + }); + + it('renders geocoding results when state.geocodeResults has value', () => { + wrapper.setState({ + geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456), + }); + expect(wrapper.find('.geocoding-results')).to.exist; + }); +}); diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 67928795..3645f7f0 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -1,67 +1,65 @@ -var debug = process.env.NODE_ENV !== 'production'; -var webpack = require('webpack'); -var path = require('path'); -var CopyWebpackPlugin = require('copy-webpack-plugin'); - -module.exports = { - entry: './demo/index.js', - output: { - path: __dirname + '/dist', - filename: 'index.min.js', - }, - devtool: 'source-map', - module: { - loaders: [ - { - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel', - query: { - presets: ['es2015', 'react'], - }, - }, - { test: /\.json$/, loader: 'json' }, - { - test: /\.(jpe?g|png|gif|svg)$/i, - loaders: [ - 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', - 'image-webpack-loader', - ], - }, - ], - }, - plugins: - process.argv.indexOf('-p') !== -1 - ? [ - new CopyWebpackPlugin([ - { from: './demo/app.css' }, - { from: './demo/favicon.ico' }, - { from: './demo/index.html' }, - ]), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify('production'), - }, - }), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurrenceOrderPlugin(), - new webpack.optimize.UglifyJsPlugin(), - new webpack.optimize.UglifyJsPlugin({ - mangle: true, - compress: { - warnings: false, - pure_getters: true, - unsafe: true, - unsafe_comps: true, - screw_ie8: true, - }, - output: { - comments: false, - }, - exclude: [/\.min\.js$/gi], - }), - new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), - ] - : [], -}; +var webpack = require('webpack'); +var CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = { + entry: './demo/index.js', + output: { + path: __dirname + '/dist', + filename: 'index.min.js', + }, + devtool: 'source-map', + module: { + loaders: [ + { + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel', + query: { + presets: ['es2015', 'react'], + }, + }, + { test: /\.json$/, loader: 'json' }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + loaders: [ + 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', + 'image-webpack-loader', + ], + }, + ], + }, + plugins: + process.argv.indexOf('-p') !== -1 + ? [ + new CopyWebpackPlugin([ + { from: './demo/app.css' }, + { from: './demo/favicon.ico' }, + { from: './demo/index.html' }, + ]), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify('production'), + }, + }), + new webpack.optimize.AggressiveMergingPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurrenceOrderPlugin(), + new webpack.optimize.UglifyJsPlugin(), + new webpack.optimize.UglifyJsPlugin({ + mangle: true, + compress: { + warnings: false, + pure_getters: true, + unsafe: true, + unsafe_comps: true, + screw_ie8: true, + }, + output: { + comments: false, + }, + exclude: [/\.min\.js$/gi], + }), + new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), + ] + : [], +}; diff --git a/package.json b/package.json index 3385a110..f87889c3 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "demo:deploy": "gh-pages -d demo/dist", "postpublish": "npm run demo:deploy", "prettier": "prettier --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"", - "lint": "eslint src/**/*.js demo/**/*.js", - "lint:fix": "eslint --fix src/**/*.js demo/**/*.js" + "lint": "eslint .", + "lint:fix": "eslint . --fix" }, "repository": { "type": "git", diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 53c2cfa8..29369a6a 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -7,6 +7,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import debounce from 'lodash.debounce'; +import defaultSuggestionItem from './SuggestionItem'; import defaultStyles from './defaultStyles'; class PlacesAutocomplete extends Component { @@ -41,8 +42,8 @@ class PlacesAutocomplete extends Component { ); } - this.autocompleteService = new google.maps.places.AutocompleteService(); - this.autocompleteOK = google.maps.places.PlacesServiceStatus.OK; + this.autocompleteService = new window.google.maps.places.AutocompleteService(); + this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK; } autocompleteCallback(predictions, status) { @@ -140,8 +141,6 @@ class PlacesAutocomplete extends Component { if (this.props.onEnterKeyDown) { this.props.onEnterKeyDown(this.props.inputProps.value); this.clearSuggestions(); - } else { - return; //noop } } @@ -177,21 +176,21 @@ class PlacesAutocomplete extends Component { handleInputKeyDown(event) { switch (event.key) { - case 'Enter': - event.preventDefault(); - this.handleEnterKey(); - break; - case 'ArrowDown': - event.preventDefault(); // prevent the cursor from moving - this.handleDownKey(); - break; - case 'ArrowUp': - event.preventDefault(); // prevent the cursor from moving - this.handleUpKey(); - break; - case 'Escape': - this.clearSuggestions(); - break; + case 'Enter': + event.preventDefault(); + this.handleEnterKey(); + break; + case 'ArrowDown': + event.preventDefault(); // prevent the cursor from moving + this.handleDownKey(); + break; + case 'ArrowUp': + event.preventDefault(); // prevent the cursor from moving + this.handleUpKey(); + break; + case 'Escape': + this.clearSuggestions(); + break; } if (this.props.inputProps.onKeyDown) { @@ -360,17 +359,17 @@ class PlacesAutocomplete extends Component { style={ p.active ? this.inlineStyleFor( - 'autocompleteItem', - 'autocompleteItemActive' - ) + 'autocompleteItem', + 'autocompleteItemActive' + ) : this.inlineStyleFor('autocompleteItem') } className={ p.active ? this.classNameFor( - 'autocompleteItem', - 'autocompleteItemActive' - ) + 'autocompleteItem', + 'autocompleteItemActive' + ) : this.classNameFor('autocompleteItem') } > @@ -393,13 +392,14 @@ PlacesAutocomplete.propTypes = { const inputProps = props[propName]; if (!inputProps.hasOwnProperty('value')) { - throw new Error("'inputProps' must have 'value'."); + throw new Error('\'inputProps\' must have \'value\'.'); } if (!inputProps.hasOwnProperty('onChange')) { - throw new Error("'inputProps' must have 'onChange'."); + throw new Error('\'inputProps\' must have \'onChange\'.'); } }, + onEnterKeyDown: PropTypes.func, onError: PropTypes.func, onSelect: PropTypes.func, renderSuggestion: PropTypes.func, @@ -432,13 +432,15 @@ PlacesAutocomplete.propTypes = { }; PlacesAutocomplete.defaultProps = { + /* eslint-disable no-unused-vars, no-console */ onError: (status, _clearSuggestions) => console.error( '[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status ), + /* eslint-enable no-unused-vars, no-console */ classNames: {}, - renderSuggestion: ({ suggestion }) =>
{suggestion}
, + renderSuggestion: defaultSuggestionItem, styles: {}, options: {}, debounce: 200, diff --git a/src/SuggestionItem.js b/src/SuggestionItem.js new file mode 100644 index 00000000..e637d96d --- /dev/null +++ b/src/SuggestionItem.js @@ -0,0 +1,12 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const SuggestionItem = (props) => ( +
{props.suggestion}
+); + +SuggestionItem.propTypes = { + suggestion: PropTypes.string.isRequired, +}; + +export default SuggestionItem; diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index ab290386..63c75a19 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,9 +1,9 @@ +/* eslint-disable react/prop-types */ import React from 'react'; -import TestUtils from 'react-addons-test-utils'; import { mount, shallow } from 'enzyme'; import sinon from 'sinon'; import { expect } from './testHelper'; -import PlacesAutocomplete, { geocodeByAddress } from '../index.js'; +import PlacesAutocomplete from '../index.js'; const testInputProps = { value: 'San Francisco, CA', @@ -38,7 +38,7 @@ describe('PlacesAutocomplete callbacks', () => { sinon.stub(console, 'error'); const wrapper = mount(); wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); - expect(console.error.calledOnce).to.equal(true); + expect(console.error.calledOnce).to.equal(true); // eslint-disable-line no-console }); }); @@ -197,6 +197,7 @@ describe('customizable autocompleteItem', () => { const renderSuggestion = ({ suggestion }) => (
+ {suggestion}
); const wrapper = shallow( @@ -301,10 +302,7 @@ describe('AutocompletionRequest options', () => { value: 'Boston, MA', }; it('calls getPlacePredictions with the correct options', done => { - global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = ( - request, - callback - ) => {}; + global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = () => {}; const spy = sinon.spy( global.google.maps.places.AutocompleteService.prototype, 'getPlacePredictions' @@ -341,7 +339,7 @@ describe('autoFocus prop', () => { }); }); -describe("Enables using original input's value as it was another entry in autocomplete", () => { +describe('Enables using original input\'s value as it was another entry in autocomplete', () => { const data = [ { suggestion: 'San Francisco, CA', @@ -390,7 +388,7 @@ describe("Enables using original input's value as it was another entry in autoco expect(wrapper.state().userInputValue).to.equal('san'); }); - it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { + it('don\'t focus on any entry when focus is on last item and arrow down key is pressed', () => { const lastItemActive = data.map((item, idx) => { return idx === data.length - 1 ? { ...item, active: true } : item; }); @@ -403,7 +401,7 @@ describe("Enables using original input's value as it was another entry in autoco }); }); - it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { + it('don\'t focus on any entry when focus is on first item and arrow up key is pressed', () => { const firstItemActive = data.map((item, idx) => { return idx === 0 ? { ...item, active: true } : item; }); diff --git a/src/utils.js b/src/utils.js index 25ef3771..0a8e923c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,15 +1,17 @@ export const geocodeByAddress = (address, callback) => { - const geocoder = new google.maps.Geocoder(); - const OK = google.maps.GeocoderStatus.OK; + const geocoder = new window.google.maps.Geocoder(); + const OK = window.google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ address }, (results, status) => { if (status !== OK) { // TODO: Remove callback support in the next major version. if (callback) { + /* eslint-disable no-console */ console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' ); + /* eslint-enable no-console */ callback({ status }, null, results); return; } @@ -23,9 +25,11 @@ export const geocodeByAddress = (address, callback) => { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), }; + /* eslint-disable no-console */ console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' ); + /* eslint-enable no-console */ callback(null, latLng, results); } @@ -49,17 +53,19 @@ export const getLatLng = result => { }; export const geocodeByPlaceId = (placeId, callback) => { - const geocoder = new google.maps.Geocoder(); - const OK = google.maps.GeocoderStatus.OK; + const geocoder = new window.google.maps.Geocoder(); + const OK = window.google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ placeId }, (results, status) => { if (status !== OK) { // TODO: Remove callback support in the next major version. if (callback) { + /* eslint-disable no-console */ console.warn( 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' ); + /* eslint-enable no-console */ callback({ status }, null, results); return; } @@ -73,9 +79,11 @@ export const geocodeByPlaceId = (placeId, callback) => { lat: results[0].geometry.location.lat(), lng: results[0].geometry.location.lng(), }; + /* eslint-disable no-console */ console.warn( 'Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' ); + /* eslint-enable no-console */ callback(null, latLng, results); } diff --git a/webpack.config.babel.js b/webpack.config.babel.js index b81e0872..e01efe4a 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -1,6 +1,6 @@ -import { join } from 'path' +import { join } from 'path'; -const include = join(__dirname, 'src') +const include = join(__dirname, 'src'); export default { entry: './src/index.js', @@ -33,4 +33,4 @@ export default { } ] } -} +}; From 697134a962daba6246ddc95c83fb230e5c35b323 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 11 Mar 2018 15:59:11 -0700 Subject: [PATCH 111/165] chore(format): Configure prettier and eslint to work together --- .eslintrc.json | 10 ++-- .prettierrc.json | 5 ++ demo/tests/index.spec.js | 3 +- demo/webpack.config.js | 61 ++++++++++----------- package-lock.json | 39 ++++++++++++++ package.json | 8 ++- src/PlacesAutocomplete.js | 108 ++++++++++++++++++++------------------ src/SuggestionItem.js | 4 +- src/tests/index.spec.js | 8 +-- webpack.config.babel.js | 16 +++--- 10 files changed, 159 insertions(+), 103 deletions(-) create mode 100644 .prettierrc.json diff --git a/.eslintrc.json b/.eslintrc.json index 6555b9c8..2b83e96c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,7 +7,9 @@ }, "extends": [ "eslint:recommended", - "plugin:react/recommended" + "plugin:react/recommended", + "prettier", + "prettier/react" ], "parserOptions": { "ecmaFeatures": { @@ -17,7 +19,8 @@ "sourceType": "module" }, "plugins": [ - "react" + "react", + "prettier" ], "rules": { "indent": [ @@ -35,6 +38,7 @@ "semi": [ "error", "always" - ] + ], + "prettier/prettier": "error" } } diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..eab3a285 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "arrowParens": "avoid", + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js index 5c42f917..87848436 100644 --- a/demo/tests/index.spec.js +++ b/demo/tests/index.spec.js @@ -1,3 +1,4 @@ +/* eslint-disable quotes */ import React from 'react'; import { mount, shallow } from 'enzyme'; import { expect } from '../../src/tests/testHelper'; @@ -27,7 +28,7 @@ describe('', () => { expect(wrapper.find('.loader')).to.exist; }); - it('doesn\'t initially render geocoding results', () => { + it("doesn't initially render geocoding results", () => { expect(wrapper.find('.geocoding-results')).to.not.exist; }); diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 3645f7f0..7cce7004 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -1,3 +1,4 @@ +/* eslint-disable indent */ var webpack = require('webpack'); var CopyWebpackPlugin = require('copy-webpack-plugin'); @@ -31,35 +32,35 @@ module.exports = { plugins: process.argv.indexOf('-p') !== -1 ? [ - new CopyWebpackPlugin([ - { from: './demo/app.css' }, - { from: './demo/favicon.ico' }, - { from: './demo/index.html' }, - ]), - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify('production'), - }, - }), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurrenceOrderPlugin(), - new webpack.optimize.UglifyJsPlugin(), - new webpack.optimize.UglifyJsPlugin({ - mangle: true, - compress: { - warnings: false, - pure_getters: true, - unsafe: true, - unsafe_comps: true, - screw_ie8: true, - }, - output: { - comments: false, - }, - exclude: [/\.min\.js$/gi], - }), - new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), - ] + new CopyWebpackPlugin([ + { from: './demo/app.css' }, + { from: './demo/favicon.ico' }, + { from: './demo/index.html' }, + ]), + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify('production'), + }, + }), + new webpack.optimize.AggressiveMergingPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurrenceOrderPlugin(), + new webpack.optimize.UglifyJsPlugin(), + new webpack.optimize.UglifyJsPlugin({ + mangle: true, + compress: { + warnings: false, + pure_getters: true, + unsafe: true, + unsafe_comps: true, + screw_ie8: true, + }, + output: { + comments: false, + }, + exclude: [/\.min\.js$/gi], + }), + new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), + ] : [], }; diff --git a/package-lock.json b/package-lock.json index 87827751..65e67b46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6741,6 +6741,33 @@ } } }, + "eslint-config-prettier": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz", + "integrity": "sha512-ag8YEyBXsm3nmOv1Hz991VtNNDMRa+MNy8cY47Pl4bw6iuzqKbJajXdqUpiw13STdLLrznxgm1hj9NhxeOYq0A==", + "dev": true, + "requires": { + "get-stdin": "5.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz", + "integrity": "sha512-floiaI4F7hRkTrFe8V2ItOK97QYrX75DjmdzmVITZoAP6Cn06oEDPQRsO6MlHEP/u2SxI3xQ52Kpjw6j5WGfeQ==", + "dev": true, + "requires": { + "fast-diff": "1.1.2", + "jest-docblock": "21.2.0" + } + }, "eslint-plugin-react": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", @@ -7220,6 +7247,12 @@ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -10237,6 +10270,12 @@ } } }, + "jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, "jodid25519": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", diff --git a/package.json b/package.json index f87889c3..81a88614 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,11 @@ "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", "demo:deploy": "gh-pages -d demo/dist", "postpublish": "npm run demo:deploy", - "prettier": "prettier --single-quote --trailing-comma es5 --arrow-parens avoid --write \"src/**/*.js\" \"demo/**/*.js\"", + "prettier": "prettier --write \"src/**/*.js\" \"demo/**/*.js\"", "lint": "eslint .", - "lint:fix": "eslint . --fix" + "lint:fix": "eslint . --fix", + "format-code": "npm run prettier & npm run lint:fix", + "eslint-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check" }, "repository": { "type": "git", @@ -70,6 +72,8 @@ "cz-conventional-changelog": "1.1.6", "enzyme": "2.4.1", "eslint": "4.18.2", + "eslint-config-prettier": "2.9.0", + "eslint-plugin-prettier": "2.6.0", "eslint-plugin-react": "7.7.0", "file-loader": "0.11.2", "gh-pages": "^0.12.0", diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 29369a6a..d95d75cf 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -175,23 +175,25 @@ class PlacesAutocomplete extends Component { } handleInputKeyDown(event) { + /* eslint-disable indent */ switch (event.key) { - case 'Enter': - event.preventDefault(); - this.handleEnterKey(); - break; - case 'ArrowDown': - event.preventDefault(); // prevent the cursor from moving - this.handleDownKey(); - break; - case 'ArrowUp': - event.preventDefault(); // prevent the cursor from moving - this.handleUpKey(); - break; - case 'Escape': - this.clearSuggestions(); - break; + case 'Enter': + event.preventDefault(); + this.handleEnterKey(); + break; + case 'ArrowDown': + event.preventDefault(); // prevent the cursor from moving + this.handleDownKey(); + break; + case 'ArrowUp': + event.preventDefault(); // prevent the cursor from moving + this.handleUpKey(); + break; + case 'Escape': + this.clearSuggestions(); + break; } + /* eslint-enable indent */ if (this.props.inputProps.onKeyDown) { this.props.inputProps.onKeyDown(event); @@ -344,41 +346,43 @@ class PlacesAutocomplete extends Component { style={this.inlineStyleFor('autocompleteContainer')} className={this.classNameFor('autocompleteContainer')} > - {autocompleteItems.map((p, idx) => ( -
- {this.props.renderSuggestion({ - suggestion: p.suggestion, - formattedSuggestion: p.formattedSuggestion, - })} -
- ))} + {autocompleteItems.map((p, idx) => { + /* eslint-disable indent */ + const style = p.active + ? this.inlineStyleFor( + 'autocompleteItem', + 'autocompleteItemActive' + ) + : this.inlineStyleFor('autocompleteItem'); + const className = p.active + ? this.classNameFor( + 'autocompleteItem', + 'autocompleteItemActive' + ) + : this.classNameFor('autocompleteItem'); + /* eslint-enable indent */ + return ( +
+ {this.props.renderSuggestion({ + suggestion: p.suggestion, + formattedSuggestion: p.formattedSuggestion, + })} +
+ ); + })} {this.props.renderFooter && this.props.renderFooter()}
)} @@ -392,11 +396,11 @@ PlacesAutocomplete.propTypes = { const inputProps = props[propName]; if (!inputProps.hasOwnProperty('value')) { - throw new Error('\'inputProps\' must have \'value\'.'); + throw new Error("'inputProps' must have 'value'."); // eslint-disable-line quotes } if (!inputProps.hasOwnProperty('onChange')) { - throw new Error('\'inputProps\' must have \'onChange\'.'); + throw new Error("'inputProps' must have 'onChange'."); // eslint-disable-line quotes } }, onEnterKeyDown: PropTypes.func, diff --git a/src/SuggestionItem.js b/src/SuggestionItem.js index e637d96d..d75e31bb 100644 --- a/src/SuggestionItem.js +++ b/src/SuggestionItem.js @@ -1,9 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -const SuggestionItem = (props) => ( -
{props.suggestion}
-); +const SuggestionItem = props =>
{props.suggestion}
; SuggestionItem.propTypes = { suggestion: PropTypes.string.isRequired, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 63c75a19..1fa387cf 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,4 +1,4 @@ -/* eslint-disable react/prop-types */ +/* eslint-disable react/prop-types, quotes */ import React from 'react'; import { mount, shallow } from 'enzyme'; import sinon from 'sinon'; @@ -339,7 +339,7 @@ describe('autoFocus prop', () => { }); }); -describe('Enables using original input\'s value as it was another entry in autocomplete', () => { +describe("Enables using original input's value as it was another entry in autocomplete", () => { const data = [ { suggestion: 'San Francisco, CA', @@ -388,7 +388,7 @@ describe('Enables using original input\'s value as it was another entry in autoc expect(wrapper.state().userInputValue).to.equal('san'); }); - it('don\'t focus on any entry when focus is on last item and arrow down key is pressed', () => { + it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { const lastItemActive = data.map((item, idx) => { return idx === data.length - 1 ? { ...item, active: true } : item; }); @@ -401,7 +401,7 @@ describe('Enables using original input\'s value as it was another entry in autoc }); }); - it('don\'t focus on any entry when focus is on first item and arrow up key is pressed', () => { + it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { const firstItemActive = data.map((item, idx) => { return idx === 0 ? { ...item, active: true } : item; }); diff --git a/webpack.config.babel.js b/webpack.config.babel.js index e01efe4a..cff8e9b2 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -7,7 +7,7 @@ export default { output: { path: join(__dirname, 'dist'), libraryTarget: 'umd', - libraryName: 'PlacesAutocomplete' + libraryName: 'PlacesAutocomplete', }, devtool: 'source-map', module: { @@ -16,21 +16,21 @@ export default { test: /\.js$/, exclude: /node_modules/, loader: 'babel', - include + include, }, { test: /\.json$/, loader: 'json', - include + include, }, { test: /\.(jpe?g|png|gif|svg)$/i, loaders: [ 'file-loader?hash=sha512&digest=hex&name=[hash].[ext]', - 'image-webpack-loader' + 'image-webpack-loader', ], - include - } - ] - } + include, + }, + ], + }, }; From cc8c65f8519ef69612cd0a581156737c2de2fd74 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 21 Mar 2018 07:14:45 -0700 Subject: [PATCH 112/165] Start developing v.7 --- .babelrc | 4 +- .eslintrc.json | 1 + demo/app.css | 8 +- demo/components/SearchBar.js | 183 ++------ demo/webpack.config.js | 2 +- package-lock.json | 641 ++++++++++++++++++++++++- package.json | 3 +- src/PlacesAutocomplete.js | 419 ++++++----------- src/SuggestionItem.js | 10 - src/defaultStyles.js | 29 -- src/helpers.js | 12 + src/tests/index.spec.js | 886 +++++++++++++++++------------------ src/utils.js | 56 +-- 13 files changed, 1313 insertions(+), 941 deletions(-) delete mode 100644 src/SuggestionItem.js delete mode 100644 src/defaultStyles.js create mode 100644 src/helpers.js diff --git a/.babelrc b/.babelrc index 001d476f..0174190b 100644 --- a/.babelrc +++ b/.babelrc @@ -1,11 +1,11 @@ { "env": { "development": { - "presets": ["es2015", "stage-0", "react"], + "presets": ["env", "stage-0", "react"], "plugins": ["transform-class-properties"] }, "production": { - "presets": ["es2015", "stage-0", "react"], + "presets": ["env", "stage-0", "react"], "plugins": [ [ "transform-react-remove-prop-types", { diff --git a/.eslintrc.json b/.eslintrc.json index 2b83e96c..594486b7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,6 +11,7 @@ "prettier", "prettier/react" ], + "parser": "babel-eslint", "parserOptions": { "ecmaFeatures": { "experimentalObjectRestSpread": true, diff --git a/demo/app.css b/demo/app.css index 2958cc22..29e935ad 100644 --- a/demo/app.css +++ b/demo/app.css @@ -64,8 +64,14 @@ body, #root, .page-wrapper { } .Demo__suggestion-item { - padding: 4px; + padding: 6px; text-align: left; + background-color: #fff; + cursor: pointer; +} + +.Demo__suggestion-item--active { + background-color: #fafafa; } .Demo__dropdown-footer { diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 2109d21a..751ae844 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,146 +1,65 @@ -import React, { Component } from 'react'; -import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src'; +import React from 'react'; +import PlacesAutocomplete from '../../src'; -/* eslint-disable react/prop-types */ -const renderSuggestion = ({ formattedSuggestion }) => ( -
- - {formattedSuggestion.mainText}{' '} - {formattedSuggestion.secondaryText} -
-); -/* eslint-enable react/prop-types */ - -const renderFooter = () => ( -
-
- -
-
-); - -const cssClasses = { - root: 'form-group', - input: 'Demo__search-input', - autocompleteContainer: 'Demo__autocomplete-container', -}; - -const shouldFetchSuggestions = ({ value }) => value.length > 2; - -const onError = (status, clearSuggestions) => { - /* eslint-disable no-console */ - console.log( - 'Error happened while fetching suggestions from Google Maps API', - status - ); - /* eslint-enable no-console */ - clearSuggestions(); -}; - -class SearchBar extends Component { +class SearchBar extends React.Component { constructor(props) { super(props); this.state = { address: '', - geocodeResults: null, - loading: false, }; - - this.handleSelect = this.handleSelect.bind(this); - this.handleChange = this.handleChange.bind(this); - } - - handleSelect(address) { - this.setState({ - address, - loading: true, - }); - - geocodeByAddress(address) - .then(results => getLatLng(results[0])) - .then(({ lat, lng }) => { - console.log('Geocode Success', { lat, lng }); // eslint-disable-line no-console - this.setState({ - geocodeResults: this.renderGeocodeSuccess(lat, lng), - loading: false, - }); - }) - .catch(error => { - console.log('Geocode Error', error); // eslint-disable-line no-console - this.setState({ - geocodeResults: this.renderGeocodeFailure(error), - loading: false, - }); - }); - } - - handleChange(address) { - this.setState({ - address, - geocodeResults: null, - }); - } - - renderGeocodeFailure(err) { - return ( -
- Error! {err} -
- ); + this.handleChange = address => this.setState({ address }); } - renderGeocodeSuccess(lat, lng) { - return ( -
- Success! Geocoder found latitude and longitude:{' '} - - {lat}, {lng} - -
- ); - } + handleSelect = selected => { + console.log('selected', selected); // eslint-disable-line no-console + }; render() { - const inputProps = { - type: 'text', - value: this.state.address, - onChange: this.handleChange, - onBlur: () => { - console.log('Blur event!'); // eslint-disable-line no-console - }, - onFocus: () => { - console.log('Focused!'); // eslint-disable-line no-console - }, - autoFocus: true, - placeholder: 'Search Places', - name: 'Demo__input', - id: 'my-input-id', - }; - return ( -
- - {this.state.loading && ( -
- -
- )} - {this.state.geocodeResults && ( -
{this.state.geocodeResults}
- )} -
+ {}} + searchOptions={{}} + debounce={300} + shouldFetchSuggestions={this.state.address.length > 3} + > + {({ getInputProps, suggestions, getSuggestionItemProps }) => { + return ( +
+ +
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.formattedSuggestion.mainText}{' '} + + {suggestion.formattedSuggestion.secondaryText} + +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+ ); + }} +
); } } diff --git a/demo/webpack.config.js b/demo/webpack.config.js index 7cce7004..b8d905fb 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.js @@ -16,7 +16,7 @@ module.exports = { exclude: /node_modules/, loader: 'babel', query: { - presets: ['es2015', 'react'], + presets: ['env', 'stage-0', 'react'], }, }, { test: /\.json$/, loader: 'json' }, diff --git a/package-lock.json b/package-lock.json index 65e67b46..eb6082a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,193 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz", + "integrity": "sha512-L8i94FLSyaLQpRfDo/qqSm8Ndb44zMtXParXo0MebJICG1zoCCL4+GkzUOlB4BNTRSXXQdb3feam/qw7bKPipQ==", + "dev": true, + "requires": { + "@babel/highlight": "7.0.0-beta.42" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.42.tgz", + "integrity": "sha512-9x3zS4nG/6GAvJWB8fAK+5g/Di36xdubB43dMNSucNJTwPvmyfCippir/0I8zyG+ID66hLCLi8V9bomlWRYaHA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.42", + "jsesc": "2.5.1", + "lodash": "4.17.4", + "source-map": "0.5.6", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz", + "integrity": "sha512-6IZ+kkPypwJrnmNzI3y31qAps2kXoPtCE241SvBva2YzB0n/YORWx2YM0jHPYOJBU9Xx5KkUhOKuWkeXZQgtTA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.42", + "@babel/template": "7.0.0-beta.42", + "@babel/types": "7.0.0-beta.42" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz", + "integrity": "sha512-hF5KKcn+V/5PwU7KZ1aVwo535woLC9eV+djaoyNPZeMMJ2s+8bZlEa66Tarei0T68VRL5LXIs1Ao4hSabSkpBg==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.42" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz", + "integrity": "sha512-2r8pZG6SAJTTaI2OhxCmz5PKlMUPY5adOHrHtb1gM3ibJPDOzPAeOQNzItdxNnM33jjRakEGitXX6iYg7Sz73w==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.42" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.42.tgz", + "integrity": "sha512-X3Ur/A/lIbbP8W0pmwgqtDXIxhQmxPaiwY9SKP7kF9wvZfjZRwMvbJE92ozUhF3UDK3DCKaV7oGqmI1rP/zqWA==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "@babel/template": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.42.tgz", + "integrity": "sha512-EK7YdTe47j4VxlwNvz5bnlk5Jx/wWublnqfgOY2IuSNdxCQgXrLD34PfTnabGxywNSkJkcSo6jwr2JGT+S48dA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.42", + "@babel/types": "7.0.0-beta.42", + "babylon": "7.0.0-beta.42", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.42.tgz", + "integrity": "sha512-DZwMuZBfYVIn/cxpXZzHDgKmarW/MWqplLv1k7QJYhK5r5l6GAac/DkKl75A0CjPYrD3VGco6H6ZQp12QaYKSw==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.42", + "@babel/generator": "7.0.0-beta.42", + "@babel/helper-function-name": "7.0.0-beta.42", + "@babel/helper-split-export-declaration": "7.0.0-beta.42", + "@babel/types": "7.0.0-beta.42", + "babylon": "7.0.0-beta.42", + "debug": "3.1.0", + "globals": "11.3.0", + "invariant": "2.2.1", + "lodash": "4.17.4" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.42.tgz", + "integrity": "sha512-+pmpISmTHQqMMpHHtDLxcvtRhmn53bAxy8goJfHipS/uy/r3PLcuSdPizLW7DhtBWbtgIKZufLObfnIMoyMNsw==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@semantic-release/commit-analyzer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-2.0.0.tgz", @@ -650,6 +837,28 @@ } } }, + "babel-eslint": { + "version": "8.2.2", + "resolved": "http://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz", + "integrity": "sha512-Qt2lz2egBxNYWqN9JIO2z4NOOf8i4b5JS6CFoYrOZZTDssueiV1jH/jsefyg+86SeNY3rB361/mi3kE1WK2WYQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.42", + "@babel/traverse": "7.0.0-beta.42", + "@babel/types": "7.0.0-beta.42", + "babylon": "7.0.0-beta.42", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0" + }, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.42", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.42.tgz", + "integrity": "sha512-h6E/OkkvcBw/JimbL0p8dIaxrcuQn3QmIYGC/GtJlRYif5LTKBYPHXYwqluJpfS/kOXoz0go+9mkmOVC0M+zWw==", + "dev": true + } + } + }, "babel-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", @@ -801,6 +1010,35 @@ } } }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-helper-builder-react-jsx": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", @@ -1072,6 +1310,35 @@ } } }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-helper-explode-class": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", @@ -1169,6 +1436,65 @@ } } }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-helper-hoist-variables": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", @@ -1290,6 +1616,37 @@ } } }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-helper-replace-supers": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", @@ -1536,6 +1893,33 @@ } } }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-plugin-check-es2015-constants": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", @@ -1659,6 +2043,12 @@ "babel-runtime": "6.9.2" } }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, "babel-plugin-transform-async-generator-functions": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", @@ -1804,6 +2194,35 @@ } } }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.8.0", + "babel-runtime": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-plugin-transform-class-constructor-call": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", @@ -3627,6 +4046,35 @@ } } }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.8.0", + "babel-runtime": "6.26.0" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, "babel-plugin-transform-export-extensions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", @@ -3907,13 +4355,15 @@ } } }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", "dev": true, "requires": { "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", "babel-plugin-transform-es2015-arrow-functions": "6.22.0", "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", "babel-plugin-transform-es2015-block-scoping": "6.24.1", @@ -3936,7 +4386,28 @@ "babel-plugin-transform-es2015-template-literals": "6.22.0", "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1" + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.24.1", + "browserslist": "2.11.3", + "invariant": "2.2.4", + "semver": "5.5.0" + }, + "dependencies": { + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.2.0" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } } }, "babel-preset-flow": { @@ -4246,6 +4717,144 @@ "regenerator-runtime": "0.9.5" } }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.4" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.2.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + }, + "dependencies": { + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.4.0", + "regenerator-runtime": "0.11.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, "balanced-match": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz", @@ -4438,6 +5047,16 @@ "pako": "0.2.9" } }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000817", + "electron-to-chromium": "1.3.40" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -4541,6 +5160,12 @@ "map-obj": "1.0.1" } }, + "caniuse-lite": { + "version": "1.0.30000817", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000817.tgz", + "integrity": "sha512-O68CSiZY4NuxdGT0gQO+2vtU07/FOrCUpGPYincrOjybQIdsSyWC9CWx+hhm+SnCTAwpG/AywH4cU5RAkqbFXA==", + "dev": true + }, "capture-stack-trace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", @@ -6231,6 +6856,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.40", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.40.tgz", + "integrity": "sha1-H71tl779crim+SHcONIkE9L2/d8=", + "dev": true + }, "emojis-list": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.0.1.tgz", diff --git a/package.json b/package.json index 81a88614..e747d785 100644 --- a/package.json +++ b/package.json @@ -57,11 +57,12 @@ "homepage": "https://github.com/kenny-hibino/react-places-autocomplete#readme", "devDependencies": { "babel-cli": "^6.23.0", + "babel-eslint": "8.2.2", "babel-loader": "^6.3.2", "babel-plugin-react-transform": "^2.0.2", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-react-remove-prop-types": "^0.3.2", - "babel-preset-es2015": "^6.22.0", + "babel-preset-env": "1.6.1", "babel-preset-react": "^6.23.1", "babel-preset-stage-0": "^6.22.0", "babel-register": "^6.23.0", diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d95d75cf..deb57e7a 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -4,41 +4,42 @@ * See https://kenny-hibino.github.io/react-places-autocomplete */ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import debounce from 'lodash.debounce'; -import defaultSuggestionItem from './SuggestionItem'; -import defaultStyles from './defaultStyles'; +import { compose, pick } from './helpers'; -class PlacesAutocomplete extends Component { +// transform snake_case to camelCase +const formattedSuggestion = structured_formatting => ({ + mainText: structured_formatting.main_text, + secondaryText: structured_formatting.secondary_text, +}); + +class PlacesAutocomplete extends React.Component { constructor(props) { super(props); this.state = { - autocompleteItems: [], - userInputValue: props.inputProps.value, + suggestions: [], + userInputValue: props.value, }; - this.autocompleteCallback = this.autocompleteCallback.bind(this); - this.handleInputKeyDown = this.handleInputKeyDown.bind(this); - this.handleInputChange = this.handleInputChange.bind(this); this.debouncedFetchPredictions = debounce( this.fetchPredictions, this.props.debounce ); - this.clearSuggestions = this.clearSuggestions.bind(this); } componentDidMount() { if (!window.google) { throw new Error( - 'Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' + '[react-places-autocomplete]: Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' ); } if (!window.google.maps.places) { throw new Error( - 'Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' + '[react-places-autocomplete]: Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' ); } @@ -46,135 +47,112 @@ class PlacesAutocomplete extends Component { this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK; } - autocompleteCallback(predictions, status) { + autocompleteCallback = (predictions, status) => { if (status !== this.autocompleteOK) { this.props.onError(status, this.clearSuggestions); return; } - - // transform snake_case to camelCase - const formattedSuggestion = structured_formatting => ({ - mainText: structured_formatting.main_text, - secondaryText: structured_formatting.secondary_text, - }); - const { highlightFirstSuggestion } = this.props; - this.setState({ - autocompleteItems: predictions.map((p, idx) => ({ - suggestion: p.description, + suggestions: predictions.map((p, idx) => ({ + description: p.description, placeId: p.place_id, active: highlightFirstSuggestion && idx === 0 ? true : false, index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), })), }); - } + }; - fetchPredictions() { - const { value } = this.props.inputProps; + fetchPredictions = () => { + const { value } = this.props; if (value.length) { this.autocompleteService.getPlacePredictions( { - ...this.props.options, + ...this.props.searchOptions, input: value, }, this.autocompleteCallback ); } - } + }; - clearSuggestions() { - this.setState({ autocompleteItems: [] }); - } + clearSuggestions = () => { + this.setState({ suggestions: [] }); + }; - clearActive() { + clearActive = () => { this.setState({ - autocompleteItems: this.state.autocompleteItems.map(item => ({ - ...item, + suggestions: this.state.suggestions.map(suggestion => ({ + ...suggestion, active: false, })), }); - } + }; - selectAddress(address, placeId, e) { - if (e !== undefined) { - e.preventDefault(); - } + handleSelect = (address, placeId) => { this.clearSuggestions(); - this.handleSelect(address, placeId); - } - - handleSelect(address, placeId) { - this.props.onSelect - ? this.props.onSelect(address, placeId) - : this.props.inputProps.onChange(address); - } - - getActiveItem() { - return this.state.autocompleteItems.find(item => item.active); - } - - selectActiveItemAtIndex(index) { - const activeName = this.state.autocompleteItems.find( - item => item.index === index - ).suggestion; - this.setActiveItemAtIndex(index); - this.props.inputProps.onChange(activeName); - } - - selectUserInputValue() { + this.props.onChange(address); + this.props.onSelect && this.props.onSelect(address, placeId); + }; + + getActiveSuggestion = () => { + return this.state.suggestions.find(suggestion => suggestion.active); + }; + + selectActiveAtIndex = index => { + const activeName = this.state.suggestions.find( + suggestion => suggestion.index === index + ).description; + this.setActiveAtIndex(index); + this.props.onChange(activeName); + }; + + selectUserInputValue = () => { this.clearActive(); - this.props.inputProps.onChange(this.state.userInputValue); - } + this.props.onChange(this.state.userInputValue); + }; - handleEnterKey() { - const activeItem = this.getActiveItem(); - if (activeItem === undefined) { - this.handleEnterKeyWithoutActiveItem(); + handleEnterKey = () => { + const activeSuggestion = this.getActiveSuggestion(); + if (activeSuggestion === undefined) { + this.handleSelect(this.props.value, null); } else { - this.selectAddress(activeItem.suggestion, activeItem.placeId); - } - } - - handleEnterKeyWithoutActiveItem() { - if (this.props.onEnterKeyDown) { - this.props.onEnterKeyDown(this.props.inputProps.value); - this.clearSuggestions(); + this.handleSelect(activeSuggestion.description, activeSuggestion.placeId); } - } + }; - handleDownKey() { - if (this.state.autocompleteItems.length === 0) { + handleDownKey = () => { + if (this.state.suggestions.length === 0) { return; } - const activeItem = this.getActiveItem(); - if (activeItem === undefined) { - this.selectActiveItemAtIndex(0); - } else if (activeItem.index === this.state.autocompleteItems.length - 1) { + const activeSuggestion = this.getActiveSuggestion(); + if (activeSuggestion === undefined) { + this.selectActiveAtIndex(0); + } else if (activeSuggestion.index === this.state.suggestions.length - 1) { this.selectUserInputValue(); } else { - this.selectActiveItemAtIndex(activeItem.index + 1); + this.selectActiveAtIndex(activeSuggestion.index + 1); } - } + }; - handleUpKey() { - if (this.state.autocompleteItems.length === 0) { + handleUpKey = () => { + if (this.state.suggestions.length === 0) { return; } - const activeItem = this.getActiveItem(); - if (activeItem === undefined) { - this.selectActiveItemAtIndex(this.state.autocompleteItems.length - 1); - } else if (activeItem.index === 0) { + const activeSuggestion = this.getActiveSuggestion(); + if (activeSuggestion === undefined) { + this.selectActiveAtIndex(this.state.suggestions.length - 1); + } else if (activeSuggestion.index === 0) { this.selectUserInputValue(); } else { - this.selectActiveItemAtIndex(activeItem.index - 1); + this.selectActiveAtIndex(activeSuggestion.index - 1); } - } + }; - handleInputKeyDown(event) { + handleInputKeyDown = event => { /* eslint-disable indent */ switch (event.key) { case 'Enter': @@ -194,81 +172,60 @@ class PlacesAutocomplete extends Component { break; } /* eslint-enable indent */ + }; - if (this.props.inputProps.onKeyDown) { - this.props.inputProps.onKeyDown(event); - } - } - - setActiveItemAtIndex(index) { + setActiveAtIndex = index => { this.setState({ - autocompleteItems: this.state.autocompleteItems.map((item, idx) => { + suggestions: this.state.suggestions.map((suggestion, idx) => { if (idx === index) { - return { ...item, active: true }; + return { ...suggestion, active: true }; } else { - return { ...item, active: false }; + return { ...suggestion, active: false }; } }), }); - } + }; - handleInputChange(event) { + handleInputChange = event => { const { value } = event.target; - this.props.inputProps.onChange(value); + this.props.onChange(value); this.setState({ userInputValue: value }); if (!value) { this.clearSuggestions(); return; } - if (this.props.shouldFetchSuggestions({ value })) { + if (this.props.shouldFetchSuggestions) { this.debouncedFetchPredictions(); } - } + }; - handleInputOnBlur(event) { + handleInputOnBlur = () => { if (!this.mousedownOnSuggestion) { this.clearSuggestions(); } + }; - if (this.props.inputProps.onBlur) { - this.props.inputProps.onBlur(event); - } - } + getIsExpanded = () => { + return this.state.suggestions.length > 0; + }; - inlineStyleFor(...props) { - const { classNames, styles } = this.props; - // No inline style if className is passed via props for the element. - if (props.some(prop => classNames.hasOwnProperty(prop))) { - return {}; + getInputProps = (options = {}) => { + if (options.hasOwnProperty('value')) { + throw new Error( + '[react-places-autocomplete]: getInputProps does not accept `value`. Use `value` prop instead' + ); } - return props.reduce((acc, prop) => { - return { - ...acc, - ...defaultStyles[prop], - ...styles[prop], - }; - }, {}); - } - - classNameFor(...props) { - const { classNames } = this.props; - - return props.reduce((acc, prop) => { - const name = classNames[prop] || ''; - return name ? `${acc} ${name}` : acc; - }, ''); - } - - shouldRenderDropdown() { - return this.state.autocompleteItems.length > 0; - } + if (options.hasOwnProperty('onChange')) { + throw new Error( + '[react-places-autocomplete]: getInputProps does not accept `onChange`. Use `onChange` prop instead' + ); + } - getInputProps() { - const isExpanded = this.shouldRenderDropdown(); - const activeItem = this.getActiveItem(); - const activeItemId = activeItem - ? `PlacesAutocomplete__autocomplete-item-${activeItem.placeId}` + const isExpanded = this.getIsExpanded(); + const activeSuggestion = this.getActiveSuggestion(); + const activeSuggestionId = activeSuggestion + ? `PlacesAutocomplete__suggestion-${activeSuggestion.placeId}` : null; const defaultInputProps = { type: 'text', @@ -278,150 +235,90 @@ class PlacesAutocomplete extends Component { 'aria-controls': 'PlacesAutocomplete__autocomplete-container', 'aria-expanded': isExpanded, 'aria-haspopup': isExpanded, - 'aria-activedescendant': activeItemId, + 'aria-activedescendant': activeSuggestionId, }; return { ...defaultInputProps, - ...this.props.inputProps, + ...options, + onKeyDown: compose(this.handleInputKeyDown, options.onKeyDown), + onBlur: compose(this.handleInputOnBlur, options.onBlur), + value: this.props.value, onChange: event => { this.handleInputChange(event); }, - onKeyDown: event => { - this.handleInputKeyDown(event); - }, - onBlur: event => { - this.handleInputOnBlur(event); - }, - style: this.inlineStyleFor('input'), - className: this.classNameFor('input'), }; - } + }; - handleSuggestionMouseEnter(index) { - this.setActiveItemAtIndex(index); - } + getSuggestionItemProps = (suggestion, options = {}) => { + const whitelistedOptions = pick(options, 'className', 'style'); + return { + ...whitelistedOptions, + key: suggestion.placeId, + id: `PlacesAutocomplete__suggestion-${suggestion.placeId}`, + role: 'option', + onMouseEnter: this.handleSuggestionMouseEnter.bind( + this, + suggestion.index + ), + onMouseLeave: this.handleSuggestionMouseLeave, + onMouseDown: this.handleSuggestionMouseDown, + onMouseUp: this.handleSuggestionMouseUp, + onTouchStart: this.handleSuggestionTouchStart, + onTouchEnd: this.handleSuggestionMouseUp, + onClick: this.handleSuggestionClick.bind(this, suggestion), + }; + }; + + handleSuggestionMouseEnter = index => { + this.setActiveAtIndex(index); + }; - handleSuggestionMouseLeave() { + handleSuggestionMouseLeave = () => { this.mousedownOnSuggestion = false; this.clearActive(); - } + }; - handleSuggestionMouseDown(event) { + handleSuggestionMouseDown = event => { event.preventDefault(); this.mousedownOnSuggestion = true; - } + }; - handleSuggestionTouchStart() { + handleSuggestionTouchStart = () => { this.mousedownOnSuggestion = true; - } + }; - handleSuggestionMouseUp() { + handleSuggestionMouseUp = () => { this.mousedownOnSuggestion = false; - } + }; - handleSuggestionClick(prediction, event) { - const { suggestion, placeId } = prediction; - this.selectAddress(suggestion, placeId, event); + handleSuggestionClick = (suggestion, event) => { + if (event && event.preventDefault) { + event.preventDefault(); + } + const { description, placeId } = suggestion; + this.handleSelect(description, placeId); setTimeout(() => { this.mousedownOnSuggestion = false; }); - } + }; render() { - const { autocompleteItems } = this.state; - const inputProps = this.getInputProps(); - - return ( -
- - {this.shouldRenderDropdown() && ( -
- {autocompleteItems.map((p, idx) => { - /* eslint-disable indent */ - const style = p.active - ? this.inlineStyleFor( - 'autocompleteItem', - 'autocompleteItemActive' - ) - : this.inlineStyleFor('autocompleteItem'); - const className = p.active - ? this.classNameFor( - 'autocompleteItem', - 'autocompleteItemActive' - ) - : this.classNameFor('autocompleteItem'); - /* eslint-enable indent */ - return ( -
- {this.props.renderSuggestion({ - suggestion: p.suggestion, - formattedSuggestion: p.formattedSuggestion, - })} -
- ); - })} - {this.props.renderFooter && this.props.renderFooter()} -
- )} -
- ); + return this.props.children({ + getInputProps: this.getInputProps, + suggestions: this.state.suggestions, + getSuggestionItemProps: this.getSuggestionItemProps, + }); } } PlacesAutocomplete.propTypes = { - inputProps: (props, propName) => { - const inputProps = props[propName]; - - if (!inputProps.hasOwnProperty('value')) { - throw new Error("'inputProps' must have 'value'."); // eslint-disable-line quotes - } - - if (!inputProps.hasOwnProperty('onChange')) { - throw new Error("'inputProps' must have 'onChange'."); // eslint-disable-line quotes - } - }, - onEnterKeyDown: PropTypes.func, + onChange: PropTypes.func.isRequired, + value: PropTypes.string.isRequired, + children: PropTypes.func.isRequired, onError: PropTypes.func, onSelect: PropTypes.func, - renderSuggestion: PropTypes.func, - classNames: PropTypes.shape({ - root: PropTypes.string, - input: PropTypes.string, - autocompleteContainer: PropTypes.string, - autocompleteItem: PropTypes.string, - autocompleteItemActive: PropTypes.string, - }), - styles: PropTypes.shape({ - root: PropTypes.object, - input: PropTypes.object, - autocompleteContainer: PropTypes.object, - autocompleteItem: PropTypes.object, - autocompleteItemActive: PropTypes.object, - }), - options: PropTypes.shape({ + searchOptions: PropTypes.shape({ bounds: PropTypes.object, componentRestrictions: PropTypes.object, location: PropTypes.object, @@ -431,8 +328,7 @@ PlacesAutocomplete.propTypes = { }), debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, - renderFooter: PropTypes.func, - shouldFetchSuggestions: PropTypes.func.isRequired, + shouldFetchSuggestions: PropTypes.bool, }; PlacesAutocomplete.defaultProps = { @@ -443,13 +339,10 @@ PlacesAutocomplete.defaultProps = { status ), /* eslint-enable no-unused-vars, no-console */ - classNames: {}, - renderSuggestion: defaultSuggestionItem, - styles: {}, - options: {}, + searchOptions: {}, debounce: 200, highlightFirstSuggestion: false, - shouldFetchSuggestions: () => true, + shouldFetchSuggestions: true, }; export default PlacesAutocomplete; diff --git a/src/SuggestionItem.js b/src/SuggestionItem.js deleted file mode 100644 index d75e31bb..00000000 --- a/src/SuggestionItem.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const SuggestionItem = props =>
{props.suggestion}
; - -SuggestionItem.propTypes = { - suggestion: PropTypes.string.isRequired, -}; - -export default SuggestionItem; diff --git a/src/defaultStyles.js b/src/defaultStyles.js deleted file mode 100644 index d70ebff6..00000000 --- a/src/defaultStyles.js +++ /dev/null @@ -1,29 +0,0 @@ -const defaultStyles = { - root: { - position: 'relative', - paddingBottom: '0px', - }, - input: { - display: 'inline-block', - width: '100%', - padding: '10px', - }, - autocompleteContainer: { - position: 'absolute', - top: '100%', - backgroundColor: 'white', - border: '1px solid #555555', - width: '100%', - }, - autocompleteItem: { - backgroundColor: '#ffffff', - padding: '10px', - color: '#555555', - cursor: 'pointer', - }, - autocompleteItemActive: { - backgroundColor: '#fafafa', - }, -}; - -export default defaultStyles; diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 00000000..2d590591 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,12 @@ +export const compose = (...fns) => (...args) => { + fns.forEach(fn => fn && fn(...args)); +}; + +export const pick = (obj, ...props) => { + return props.reduce((newObj, prop) => { + if (obj.hasOwnProperty(prop)) { + newObj[prop] = obj[prop]; + } + return newObj; + }, {}); +}; diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js index 1fa387cf..273bb39e 100644 --- a/src/tests/index.spec.js +++ b/src/tests/index.spec.js @@ -1,443 +1,443 @@ -/* eslint-disable react/prop-types, quotes */ -import React from 'react'; -import { mount, shallow } from 'enzyme'; -import sinon from 'sinon'; -import { expect } from './testHelper'; -import PlacesAutocomplete from '../index.js'; - -const testInputProps = { - value: 'San Francisco, CA', - onChange: () => {}, -}; - -/*** Enzyme Rocks ***/ -describe('', () => { - let wrapper; - beforeEach(() => { - wrapper = shallow(); - }); - - it('renders an input element', () => { - expect(wrapper.find('input')).to.have.length(1); - }); -}); - -// TODO: What's the value of this test? -describe('PlacesAutocomplete callbacks', () => { - it('executes onError callback passed in as prop when status is not OK', () => { - const spy = sinon.spy(); - const wrapper = mount( - - ); - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); - expect(spy.calledOnce).to.equal(true); - expect(spy.calledWith('ZERO_RESULTS')).to.equal(true); - }); - - it('executes default onError function when there is no custom prop and status is not OK', () => { - sinon.stub(console, 'error'); - const wrapper = mount(); - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); - expect(console.error.calledOnce).to.equal(true); // eslint-disable-line no-console - }); -}); - -describe('PlacesAutocomplete props', () => { - it('allows user to set the value of the input through prop', () => { - const inputProps = { - ...testInputProps, - value: 'New York, NY', - }; - - const wrapper = mount(); - expect(wrapper.find('input').props().value).to.equal('New York, NY'); - }); -}); - -describe('autocomplete dropdown', () => { - let wrapper; - const renderSuggestion = ({ suggestion }) => ( -
{suggestion}
- ); - const renderFooter = () => ( -
Footer element
- ); - beforeEach(() => { - wrapper = shallow( - - ); - }); - - it('initially does not have an autocomplete dropdown', () => { - expect( - wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.length(0); - }); - - it('renders autocomplete dropdown once it receives data from google maps', () => { - const data = [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - { - suggestion: 'San Jose, CA', - placeId: 2, - active: false, - index: 1, - }, - { - suggestion: 'San Diego, CA', - placeId: 3, - active: false, - index: 2, - }, - ]; - wrapper.setState({ autocompleteItems: data }); - expect( - wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.length(1); - expect(wrapper.find('.autocomplete-item')).to.have.length(3); - expect(wrapper.find('.my-dropdown-footer')).to.have.length(1); - }); - - it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { - const initialItems = [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ]; - const wrapper = shallow( - - ); - wrapper.setState({ autocompleteItems: initialItems }); - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); - expect(wrapper.find('.autocomplete-item')).to.have.length(0); - }); - - it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { - const initialItems = [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ]; - wrapper.setState({ autocompleteItems: initialItems }); - wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); - expect(wrapper.find('.autocomplete-item')).to.have.length(1); - }); -}); - -describe('custom classNames, placeholder', () => { - const inputProps = { - ...testInputProps, - placeholder: 'Your Address', - }; - - const classNames = { - root: 'my-container', - input: 'my-input', - autocompleteContainer: 'my-autocomplete-container', - }; - - let wrapper; - - beforeEach(() => { - wrapper = shallow( - - ); - }); - - it('lets you set a custom className for the container', () => { - expect(wrapper.find('.my-container')).to.have.length(1); - }); - - it('lets you set a custom className for the input', () => { - expect(wrapper.find('input')).to.have.className('my-input'); - }); - - it('lets you set a custom className for autocomplete container', () => { - wrapper.setState({ - autocompleteItems: [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ], - }); - expect( - wrapper.find('#PlacesAutocomplete__autocomplete-container') - ).to.have.className('my-autocomplete-container'); - }); - - it('lets you set a custom placeholder for the input', () => { - expect(wrapper.find('input').props().placeholder).to.equal('Your Address'); - }); -}); - -// TODO: test formattedSuggestion -describe('customizable autocompleteItem', () => { - it('lets you provide a custom autocomplete item', () => { - const renderSuggestion = ({ suggestion }) => ( -
- - {suggestion} -
- ); - const wrapper = shallow( - - ); - wrapper.setState({ - autocompleteItems: [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ], - }); - expect(wrapper.find('.my-autocomplete-item')).to.have.length(1); - expect(wrapper.find('.my-autocomplete-item')).to.contain( - - ); - }); -}); - -describe('custom inline styles', () => { - const styles = { - root: { position: 'absolute' }, - input: { width: '100%' }, - autocompleteContainer: { backgroundColor: 'green' }, - autocompleteItem: { color: 'black' }, - autocompleteItemActive: { color: 'blue' }, - }; - - let wrapper; - beforeEach(() => { - wrapper = shallow( - - ); - }); - - it('lets you set custom styles for the root element', () => { - expect( - wrapper.find('#PlacesAutocomplete__root').props().style.position - ).to.equal('absolute'); - }); - - it('lets you set custom styles for the input element', () => { - expect(wrapper.find('input').props().style.width).to.equal('100%'); - }); - - it('lets you set custom styles for the autocomplete container element', () => { - wrapper.setState({ - autocompleteItems: [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ], - }); - expect( - wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style - .backgroundColor - ).to.equal('green'); - }); - - it('lets you set custom styles for autocomplete items', () => { - wrapper.setState({ - autocompleteItems: [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - ], - }); - const item = wrapper - .find('#PlacesAutocomplete__autocomplete-container') - .childAt(0); - expect(item.props().style.color).to.equal('black'); - }); - - it('lets you set custom styles for active autocomplete items', () => { - wrapper.setState({ - autocompleteItems: [ - { suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }, - ], - }); - const item = wrapper - .find('#PlacesAutocomplete__autocomplete-container') - .childAt(0); - expect(item.props().style.color).to.equal('blue'); - }); -}); - -describe('AutocompletionRequest options', () => { - const inputProps = { - ...testInputProps, - value: 'Boston, MA', - }; - it('calls getPlacePredictions with the correct options', done => { - global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = () => {}; - const spy = sinon.spy( - global.google.maps.places.AutocompleteService.prototype, - 'getPlacePredictions' - ); - const options = { radius: 2000, types: ['address'] }; - const wrapper = mount( - - ); - wrapper - .find('input') - .simulate('change', { target: { value: 'Los Angeles, CA' } }); - setTimeout(() => { - done(); - expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be - .true; - }, 0); - }); -}); - -describe('autoFocus prop', () => { - const inputProps = { - ...testInputProps, - autoFocus: true, - }; - - it('automatically gives focus when set to true', () => { - const wrapper = mount(); - expect(wrapper.find('input').node).to.equal(document.activeElement); - }); - - it('does not give the input element a focus by default', () => { - const wrapper = mount(); - expect(wrapper.find('input').node).to.not.equal(document.activeElement); - }); -}); - -describe("Enables using original input's value as it was another entry in autocomplete", () => { - const data = [ - { - suggestion: 'San Francisco, CA', - placeId: 1, - active: false, - index: 0, - }, - { - suggestion: 'San Jose, CA', - placeId: 2, - active: false, - index: 1, - }, - { - suggestion: 'San Diego, CA', - placeId: 3, - active: false, - index: 2, - }, - ]; - const spy = sinon.spy(); - const inputProps = { - value: 'san', - onChange: spy, - }; - let wrapper; - - beforeEach(() => { - wrapper = shallow(); - spy.reset(); - }); - - it('save value of input when pressing arrow down key and none of autocomplete entries is being focused', () => { - wrapper.setState({ autocompleteItems: data }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - expect(wrapper.state().userInputValue).to.equal('san'); - }); - - it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { - wrapper.setState({ autocompleteItems: data }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); - expect(wrapper.state().userInputValue).to.equal('san'); - }); - - it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { - const lastItemActive = data.map((item, idx) => { - return idx === data.length - 1 ? { ...item, active: true } : item; - }); - wrapper.setState({ autocompleteItems: lastItemActive }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - wrapper.state().autocompleteItems.forEach(item => { - expect(item.active).to.be.false; - }); - }); - - it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { - const firstItemActive = data.map((item, idx) => { - return idx === 0 ? { ...item, active: true } : item; - }); - wrapper.setState({ autocompleteItems: firstItemActive }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); - wrapper.state().autocompleteItems.forEach(item => { - expect(item.active).to.be.false; - }); - }); - - it('onChange function is called with appropriate value', () => { - // Amount of entries is 3 for this test case, so when we press arrow down fourth time - // we expect onChange function to be called with original input value - // being stored in `userInputValue` state entry - // rest of calls should be called with appropraite entries from autocomplete items - wrapper.setState({ autocompleteItems: data }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - wrapper - .instance() - .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); - expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion); - expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion); - expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion); - expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue); - }); -}); - -// TODOs: -// * Test geocodeByAddress function +// /* eslint-disable react/prop-types, quotes */ +// import React from 'react'; +// import { mount, shallow } from 'enzyme'; +// import sinon from 'sinon'; +// import { expect } from './testHelper'; +// import PlacesAutocomplete from '../index.js'; +// +// const testInputProps = { +// value: 'San Francisco, CA', +// onChange: () => {}, +// }; +// +// /*** Enzyme Rocks ***/ +// describe('', () => { +// let wrapper; +// beforeEach(() => { +// wrapper = shallow(); +// }); +// +// it('renders an input element', () => { +// expect(wrapper.find('input')).to.have.length(1); +// }); +// }); +// +// // TODO: What's the value of this test? +// describe('PlacesAutocomplete callbacks', () => { +// it('executes onError callback passed in as prop when status is not OK', () => { +// const spy = sinon.spy(); +// const wrapper = mount( +// +// ); +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); +// expect(spy.calledOnce).to.equal(true); +// expect(spy.calledWith('ZERO_RESULTS')).to.equal(true); +// }); +// +// it('executes default onError function when there is no custom prop and status is not OK', () => { +// sinon.stub(console, 'error'); +// const wrapper = mount(); +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); +// expect(console.error.calledOnce).to.equal(true); // eslint-disable-line no-console +// }); +// }); +// +// describe('PlacesAutocomplete props', () => { +// it('allows user to set the value of the input through prop', () => { +// const inputProps = { +// ...testInputProps, +// value: 'New York, NY', +// }; +// +// const wrapper = mount(); +// expect(wrapper.find('input').props().value).to.equal('New York, NY'); +// }); +// }); +// +// describe('autocomplete dropdown', () => { +// let wrapper; +// const renderSuggestion = ({ suggestion }) => ( +//
{suggestion}
+// ); +// const renderFooter = () => ( +//
Footer element
+// ); +// beforeEach(() => { +// wrapper = shallow( +// +// ); +// }); +// +// it('initially does not have an autocomplete dropdown', () => { +// expect( +// wrapper.find('#PlacesAutocomplete__autocomplete-container') +// ).to.have.length(0); +// }); +// +// it('renders autocomplete dropdown once it receives data from google maps', () => { +// const data = [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// { +// suggestion: 'San Jose, CA', +// placeId: 2, +// active: false, +// index: 1, +// }, +// { +// suggestion: 'San Diego, CA', +// placeId: 3, +// active: false, +// index: 2, +// }, +// ]; +// wrapper.setState({ autocompleteItems: data }); +// expect( +// wrapper.find('#PlacesAutocomplete__autocomplete-container') +// ).to.have.length(1); +// expect(wrapper.find('.autocomplete-item')).to.have.length(3); +// expect(wrapper.find('.my-dropdown-footer')).to.have.length(1); +// }); +// +// it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { +// const initialItems = [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ]; +// const wrapper = shallow( +// +// ); +// wrapper.setState({ autocompleteItems: initialItems }); +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); +// expect(wrapper.find('.autocomplete-item')).to.have.length(0); +// }); +// +// it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { +// const initialItems = [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ]; +// wrapper.setState({ autocompleteItems: initialItems }); +// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); +// expect(wrapper.find('.autocomplete-item')).to.have.length(1); +// }); +// }); +// +// describe('custom classNames, placeholder', () => { +// const inputProps = { +// ...testInputProps, +// placeholder: 'Your Address', +// }; +// +// const classNames = { +// root: 'my-container', +// input: 'my-input', +// autocompleteContainer: 'my-autocomplete-container', +// }; +// +// let wrapper; +// +// beforeEach(() => { +// wrapper = shallow( +// +// ); +// }); +// +// it('lets you set a custom className for the container', () => { +// expect(wrapper.find('.my-container')).to.have.length(1); +// }); +// +// it('lets you set a custom className for the input', () => { +// expect(wrapper.find('input')).to.have.className('my-input'); +// }); +// +// it('lets you set a custom className for autocomplete container', () => { +// wrapper.setState({ +// autocompleteItems: [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ], +// }); +// expect( +// wrapper.find('#PlacesAutocomplete__autocomplete-container') +// ).to.have.className('my-autocomplete-container'); +// }); +// +// it('lets you set a custom placeholder for the input', () => { +// expect(wrapper.find('input').props().placeholder).to.equal('Your Address'); +// }); +// }); +// +// // TODO: test formattedSuggestion +// describe('customizable autocompleteItem', () => { +// it('lets you provide a custom autocomplete item', () => { +// const renderSuggestion = ({ suggestion }) => ( +//
+// +// {suggestion} +//
+// ); +// const wrapper = shallow( +// +// ); +// wrapper.setState({ +// autocompleteItems: [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ], +// }); +// expect(wrapper.find('.my-autocomplete-item')).to.have.length(1); +// expect(wrapper.find('.my-autocomplete-item')).to.contain( +// +// ); +// }); +// }); +// +// describe('custom inline styles', () => { +// const styles = { +// root: { position: 'absolute' }, +// input: { width: '100%' }, +// autocompleteContainer: { backgroundColor: 'green' }, +// autocompleteItem: { color: 'black' }, +// autocompleteItemActive: { color: 'blue' }, +// }; +// +// let wrapper; +// beforeEach(() => { +// wrapper = shallow( +// +// ); +// }); +// +// it('lets you set custom styles for the root element', () => { +// expect( +// wrapper.find('#PlacesAutocomplete__root').props().style.position +// ).to.equal('absolute'); +// }); +// +// it('lets you set custom styles for the input element', () => { +// expect(wrapper.find('input').props().style.width).to.equal('100%'); +// }); +// +// it('lets you set custom styles for the autocomplete container element', () => { +// wrapper.setState({ +// autocompleteItems: [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ], +// }); +// expect( +// wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style +// .backgroundColor +// ).to.equal('green'); +// }); +// +// it('lets you set custom styles for autocomplete items', () => { +// wrapper.setState({ +// autocompleteItems: [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// ], +// }); +// const item = wrapper +// .find('#PlacesAutocomplete__autocomplete-container') +// .childAt(0); +// expect(item.props().style.color).to.equal('black'); +// }); +// +// it('lets you set custom styles for active autocomplete items', () => { +// wrapper.setState({ +// autocompleteItems: [ +// { suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }, +// ], +// }); +// const item = wrapper +// .find('#PlacesAutocomplete__autocomplete-container') +// .childAt(0); +// expect(item.props().style.color).to.equal('blue'); +// }); +// }); +// +// describe('AutocompletionRequest options', () => { +// const inputProps = { +// ...testInputProps, +// value: 'Boston, MA', +// }; +// it('calls getPlacePredictions with the correct options', done => { +// global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = () => {}; +// const spy = sinon.spy( +// global.google.maps.places.AutocompleteService.prototype, +// 'getPlacePredictions' +// ); +// const options = { radius: 2000, types: ['address'] }; +// const wrapper = mount( +// +// ); +// wrapper +// .find('input') +// .simulate('change', { target: { value: 'Los Angeles, CA' } }); +// setTimeout(() => { +// done(); +// expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be +// .true; +// }, 0); +// }); +// }); +// +// describe('autoFocus prop', () => { +// const inputProps = { +// ...testInputProps, +// autoFocus: true, +// }; +// +// it('automatically gives focus when set to true', () => { +// const wrapper = mount(); +// expect(wrapper.find('input').node).to.equal(document.activeElement); +// }); +// +// it('does not give the input element a focus by default', () => { +// const wrapper = mount(); +// expect(wrapper.find('input').node).to.not.equal(document.activeElement); +// }); +// }); +// +// describe("Enables using original input's value as it was another entry in autocomplete", () => { +// const data = [ +// { +// suggestion: 'San Francisco, CA', +// placeId: 1, +// active: false, +// index: 0, +// }, +// { +// suggestion: 'San Jose, CA', +// placeId: 2, +// active: false, +// index: 1, +// }, +// { +// suggestion: 'San Diego, CA', +// placeId: 3, +// active: false, +// index: 2, +// }, +// ]; +// const spy = sinon.spy(); +// const inputProps = { +// value: 'san', +// onChange: spy, +// }; +// let wrapper; +// +// beforeEach(() => { +// wrapper = shallow(); +// spy.reset(); +// }); +// +// it('save value of input when pressing arrow down key and none of autocomplete entries is being focused', () => { +// wrapper.setState({ autocompleteItems: data }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// expect(wrapper.state().userInputValue).to.equal('san'); +// }); +// +// it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { +// wrapper.setState({ autocompleteItems: data }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); +// expect(wrapper.state().userInputValue).to.equal('san'); +// }); +// +// it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { +// const lastItemActive = data.map((item, idx) => { +// return idx === data.length - 1 ? { ...item, active: true } : item; +// }); +// wrapper.setState({ autocompleteItems: lastItemActive }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// wrapper.state().autocompleteItems.forEach(item => { +// expect(item.active).to.be.false; +// }); +// }); +// +// it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { +// const firstItemActive = data.map((item, idx) => { +// return idx === 0 ? { ...item, active: true } : item; +// }); +// wrapper.setState({ autocompleteItems: firstItemActive }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); +// wrapper.state().autocompleteItems.forEach(item => { +// expect(item.active).to.be.false; +// }); +// }); +// +// it('onChange function is called with appropriate value', () => { +// // Amount of entries is 3 for this test case, so when we press arrow down fourth time +// // we expect onChange function to be called with original input value +// // being stored in `userInputValue` state entry +// // rest of calls should be called with appropraite entries from autocomplete items +// wrapper.setState({ autocompleteItems: data }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// wrapper +// .instance() +// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); +// expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion); +// expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion); +// expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion); +// expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue); +// }); +// }); +// +// // TODOs: +// // * Test geocodeByAddress function diff --git a/src/utils.js b/src/utils.js index 0a8e923c..41ecd8bd 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,38 +1,12 @@ -export const geocodeByAddress = (address, callback) => { +export const geocodeByAddress = address => { const geocoder = new window.google.maps.Geocoder(); const OK = window.google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ address }, (results, status) => { if (status !== OK) { - // TODO: Remove callback support in the next major version. - if (callback) { - /* eslint-disable no-console */ - console.warn( - 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' - ); - /* eslint-enable no-console */ - callback({ status }, null, results); - return; - } - reject(status); } - - // TODO: Remove callback support in the next major version. - if (callback) { - const latLng = { - lat: results[0].geometry.location.lat(), - lng: results[0].geometry.location.lng(), - }; - /* eslint-disable no-console */ - console.warn( - 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyaddress-api"' - ); - /* eslint-enable no-console */ - callback(null, latLng, results); - } - resolve(results); }); }); @@ -52,41 +26,15 @@ export const getLatLng = result => { }); }; -export const geocodeByPlaceId = (placeId, callback) => { +export const geocodeByPlaceId = placeId => { const geocoder = new window.google.maps.Geocoder(); const OK = window.google.maps.GeocoderStatus.OK; return new Promise((resolve, reject) => { geocoder.geocode({ placeId }, (results, status) => { if (status !== OK) { - // TODO: Remove callback support in the next major version. - if (callback) { - /* eslint-disable no-console */ - console.warn( - 'Deprecated: Passing a callback to geocodeByAddress is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' - ); - /* eslint-enable no-console */ - callback({ status }, null, results); - return; - } - reject(status); } - - // TODO: Remove callback support in the next major version. - if (callback) { - const latLng = { - lat: results[0].geometry.location.lat(), - lng: results[0].geometry.location.lng(), - }; - /* eslint-disable no-console */ - console.warn( - 'Deprecated: Passing a callback to geocodeByPlaceId is deprecated. Please see "https://github.com/kenny-hibino/react-places-autocomplete#geocodebyplaceid-api"' - ); - /* eslint-enable no-console */ - callback(null, latLng, results); - } - resolve(results); }); }); From 97902dd400a37224e7390e7c0cf0cd6320fd1b22 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 24 Mar 2018 20:19:56 -0700 Subject: [PATCH 113/165] Update tests to use jest --- demo/tests/index.spec.js | 42 +- package-lock.json | 5267 ++++++++++++++++++++++++++++++++------ package.json | 11 +- src/tests/index.spec.js | 443 ---- src/tests/index.test.js | 3 + src/tests/setup.js | 48 +- src/tests/testHelper.js | 50 +- 7 files changed, 4506 insertions(+), 1358 deletions(-) delete mode 100644 src/tests/index.spec.js create mode 100644 src/tests/index.test.js diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js index 87848436..61b818ae 100644 --- a/demo/tests/index.spec.js +++ b/demo/tests/index.spec.js @@ -1,41 +1,3 @@ -/* eslint-disable quotes */ -import React from 'react'; -import { mount, shallow } from 'enzyme'; -import { expect } from '../../src/tests/testHelper'; -import PlacesAutocomplete from '../../src'; -import Demo from '../Demo'; - -describe('', () => { - let wrapper; - beforeEach(() => { - wrapper = shallow(); - }); - - it('renders a PlacesAutocomplete component', () => { - expect(wrapper.find(PlacesAutocomplete)).to.exist; - }); - - it('sets the value prop of the input element to state.address', () => { - const wrapper = mount(); - wrapper.setState({ address: '123 Fake St' }); - expect(wrapper.find(PlacesAutocomplete).props().value).to.equal( - '123 Fake St' - ); - }); - - it('renders loading animation when state.loading is true', () => { - wrapper.setState({ loading: true }); - expect(wrapper.find('.loader')).to.exist; - }); - - it("doesn't initially render geocoding results", () => { - expect(wrapper.find('.geocoding-results')).to.not.exist; - }); - - it('renders geocoding results when state.geocodeResults has value', () => { - wrapper.setState({ - geocodeResults: () => wrapper.instance.renderGeocodeSuccess(123, 456), - }); - expect(wrapper.find('.geocoding-results')).to.exist; - }); +test('smoke test', () => { + expect(true).toBe(true); }); diff --git a/package-lock.json b/package-lock.json index eb6082a8..95d15c21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -246,9 +246,9 @@ } }, "abab": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", - "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", + "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", "dev": true }, "abbrev": { @@ -268,27 +268,18 @@ } }, "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "dev": true, - "optional": true + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true }, "acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz", + "integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==", "dev": true, "requires": { - "acorn": "2.7.0" - }, - "dependencies": { - "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "dev": true - } + "acorn": "5.5.3" } }, "acorn-jsx": { @@ -389,6 +380,15 @@ "micromatch": "2.3.11" } }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, "aproba": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", @@ -454,6 +454,12 @@ "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=", "dev": true }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -589,10 +595,16 @@ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, - "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, "async": { @@ -613,12 +625,24 @@ "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", "dev": true }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, "aws-sign2": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", @@ -1867,6 +1891,16 @@ } } }, + "babel-jest": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-22.4.3.tgz", + "integrity": "sha512-BgSjmtl3mW3i+VeVHEr9d2zFSAT66G++pJcHQiUjd00pkW+voYXFctIm/indcqOWWXw5a1nUpR1XWszD9fJ1qg==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "4.1.5", + "babel-preset-jest": "22.4.3" + } + }, "babel-loader": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.4.1.tgz", @@ -1947,6 +1981,34 @@ } } }, + "babel-plugin-istanbul": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz", + "integrity": "sha1-Z2DN2Xf0EdPhdbsGTyvDJ9mbK24=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "istanbul-lib-instrument": "1.10.1", + "test-exclude": "4.2.1" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "babel-plugin-jest-hoist": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.3.tgz", + "integrity": "sha512-zhvv4f6OTWy2bYevcJftwGCWXMFe7pqoz41IhMi4xna7xNsX5NygdagsrE0y6kkfuXq8UalwvPwKTyAxME2E/g==", + "dev": true + }, "babel-plugin-react-transform": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/babel-plugin-react-transform/-/babel-plugin-react-transform-2.0.2.tgz", @@ -4419,6 +4481,24 @@ "babel-plugin-transform-flow-strip-types": "6.22.0" } }, + "babel-preset-jest": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-22.4.3.tgz", + "integrity": "sha512-a+M3LTEXTq3gxv0uBN9Qm6ahUl7a8pj923nFbCUdqFUSsf3YrX8Uc+C3MEwji5Af3LiQjSC7w4ooYewlz8HRTA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "22.4.3", + "babel-plugin-syntax-object-rest-spread": "6.13.0" + }, + "dependencies": { + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + } + } + }, "babel-preset-react": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", @@ -4861,6 +4941,38 @@ "integrity": "sha1-GQU+LgdI6ts3nabAnUVc9eEDkzU=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "base64-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", @@ -4993,12 +5105,6 @@ "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", "dev": true }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -5029,6 +5135,21 @@ "repeat-element": "1.1.2" } }, + "browser-process-hrtime": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz", + "integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44=", + "dev": true + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, "browserify-aes": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-0.4.0.tgz", @@ -5057,6 +5178,15 @@ "electron-to-chromium": "1.3.40" } }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "0.4.0" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -5129,6 +5259,31 @@ "integrity": "sha1-1baAoWW2IBc5rLYRVCqrwtjOsHA=", "dev": true }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -5173,9 +5328,9 @@ "dev": true }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "caw": { @@ -5208,27 +5363,6 @@ "lazy-cache": "1.0.4" } }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "1.0.2", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" - } - }, - "chai-enzyme": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/chai-enzyme/-/chai-enzyme-0.5.0.tgz", - "integrity": "sha1-HvI2eWE0zuWoSDQgFph8j/dhXT8=", - "dev": true, - "requires": { - "html": "0.0.10", - "react-element-to-jsx-string": "3.1.0" - } - }, "chalk": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", @@ -5248,53 +5382,6 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, - "cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.8.3", - "jsdom": "7.2.2", - "lodash": "4.17.4" - }, - "dependencies": { - "jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "dev": true, - "optional": true, - "requires": { - "abab": "1.0.3", - "acorn": "2.7.0", - "acorn-globals": "1.0.9", - "cssom": "0.3.1", - "cssstyle": "0.2.36", - "escodegen": "1.8.0", - "nwmatcher": "1.3.8", - "parse5": "1.5.1", - "request": "2.73.0", - "sax": "1.2.1", - "symbol-tree": "3.1.4", - "tough-cookie": "2.2.2", - "webidl-conversions": "2.0.1", - "whatwg-url-compat": "0.6.5", - "xml-name-validator": "2.0.1" - } - }, - "webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "dev": true, - "optional": true - } - } - }, "chokidar": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", @@ -5312,6 +5399,12 @@ "readdirp": "2.1.0" } }, + "ci-info": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", + "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -5342,6 +5435,98 @@ } } }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "cli-cursor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", @@ -5412,11 +5597,15 @@ "number-is-nan": "1.0.0" } }, - "collapse-white-space": { + "collection-visit": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.0.tgz", - "integrity": "sha1-lMgJZgxWYYdPu1K8dNw1Ga/KkCM=", - "dev": true + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } }, "collections": { "version": "0.2.2", @@ -5557,6 +5746,18 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.1.0.tgz", + "integrity": "sha512-4hAxDSBypT/yp2ySFD346So6Ragw5xmBn/e/agIGl3bZr6DLUqnoRZPusxKrXdYRZpgexO9daejmIenlq/wrIQ==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "compressible": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.9.tgz", @@ -5676,6 +5877,12 @@ "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", "dev": true }, + "content-type-parser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.2.tgz", + "integrity": "sha512-lM4l4CnMEwOLHAHr/P6MEZwZFPJFtAAKgL6pogbXmVZggIqXhdB6RbBtPOTsw2FcXwYhehRGERJmRrjOiIB8pQ==", + "dev": true + }, "conventional-changelog": { "version": "0.0.17", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-0.0.17.tgz", @@ -5726,6 +5933,12 @@ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "dev": true }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "copy-webpack-plugin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.0.1.tgz", @@ -5886,24 +6099,6 @@ "sha.js": "2.2.6" } }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, "csso": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", @@ -5915,18 +6110,18 @@ } }, "cssom": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.1.tgz", - "integrity": "sha1-yeN+8kkOZPbRuqEP2oUiVwgsJdM=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", + "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=", "dev": true }, "cssstyle": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.36.tgz", - "integrity": "sha1-XP7WsaRSa1jXdnPVGzUghW+2rz4=", + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", + "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", "dev": true, "requires": { - "cssom": "0.3.1" + "cssom": "0.3.2" } }, "currently-unhandled": { @@ -5995,6 +6190,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "decompress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", @@ -6374,23 +6575,6 @@ "integrity": "sha1-Dm2o8M5Sg471zsXI+TlrDBtko8s=", "dev": true }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", @@ -6403,6 +6587,15 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -6422,6 +6615,24 @@ "object-keys": "1.0.11" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -6531,6 +6742,12 @@ "repeating": "2.0.1" } }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "dezalgo": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", @@ -6542,9 +6759,9 @@ } }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "doctrine": { @@ -6556,53 +6773,19 @@ "esutils": "2.0.2" } }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, "domain-browser": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", "dev": true }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", "dev": true, "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" + "webidl-conversions": "4.0.2" } }, "download": { @@ -6844,12 +7027,6 @@ "jsbn": "0.1.0" } }, - "editions": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/editions/-/editions-1.1.2.tgz", - "integrity": "sha1-jN8Ms56vxWQUkYHKN8gnLpixbqs=", - "dev": true - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6910,26 +7087,6 @@ } } }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - }, - "enzyme": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.4.1.tgz", - "integrity": "sha1-kPqYYdmC0M65Kp/VfjhCai9007E=", - "dev": true, - "requires": { - "cheerio": "0.20.0", - "is-subset": "0.1.1", - "lodash": "4.17.4", - "object-is": "1.0.1", - "object.assign": "4.0.4", - "object.values": "1.0.4" - } - }, "errno": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", @@ -6984,27 +7141,30 @@ "dev": true }, "escodegen": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.0.tgz", - "integrity": "sha1-skaq6CnOc9WeLFVyc1nt0cEwqBs=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", + "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", "dev": true, "requires": { - "esprima": "2.7.2", - "estraverse": "1.9.3", + "esprima": "3.1.3", + "estraverse": "4.2.0", "esutils": "2.0.2", - "optionator": "0.8.1", - "source-map": "0.2.0" + "optionator": "0.8.2", + "source-map": "0.6.1" }, "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "requires": { - "amdefine": "1.0.0" - } + "optional": true } } }, @@ -7543,9 +7703,9 @@ } }, "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "esutils": { @@ -7732,6 +7892,15 @@ "object-assign": "4.1.0" } }, + "exec-sh": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", + "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", + "dev": true, + "requires": { + "merge": "1.2.0" + } + }, "execa": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.4.0.tgz", @@ -7755,6 +7924,12 @@ "meow": "3.7.0" } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -7779,6 +7954,31 @@ "fill-range": "2.2.3" } }, + "expect": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-22.4.3.tgz", + "integrity": "sha512-XcNXEPehqn8b/jm8FYotdX0YrXn36qp4HWlrVT4ktwQas1l1LPxiVWncYnnL2eyMtKAmVIaG0XAp0QlrqJaxaA==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "jest-diff": "22.4.3", + "jest-get-type": "22.4.3", + "jest-matcher-utils": "22.4.3", + "jest-message-util": "22.4.3", + "jest-regex-util": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + } + } + }, "express": { "version": "4.14.0", "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", @@ -7891,9 +8091,9 @@ "dev": true }, "fast-levenshtein": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.3.tgz", - "integrity": "sha1-KuezKrweYS2kik4ThJuIii9h5+k=", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "faye-websocket": { @@ -7905,6 +8105,15 @@ "websocket-driver": "0.6.5" } }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "2.0.0" + } + }, "fbjs": { "version": "0.8.14", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", @@ -8008,6 +8217,57 @@ "trim-repeated": "1.0.0" } }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "7.1.2", + "minimatch": "3.0.4" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", @@ -8208,23 +8468,40 @@ "dev": true }, "form-data": { - "version": "1.0.0-rc4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz", - "integrity": "sha1-BaxrwiIntD5EYfSIFhVUaZ1Pi14=", - "dev": true, - "requires": { - "async": "1.5.2", - "combined-stream": "1.0.5", - "mime-types": "2.1.11" - } - }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { - "samsam": "1.1.2" + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + } } }, "forwarded": { @@ -8233,6 +8510,15 @@ "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", "dev": true }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "fresh": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", @@ -9382,21 +9668,12 @@ "globule": "0.1.0" } }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "get-proxy": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", @@ -9418,6 +9695,12 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "getpass": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", @@ -9831,10 +10114,10 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, "gulp": { @@ -9987,6 +10270,29 @@ "glogg": "1.0.0" } }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.0" + } + } + } + }, "har-schema": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", @@ -9994,15 +10300,39 @@ "dev": true }, "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "chalk": "1.1.1", - "commander": "2.9.0", - "is-my-json-valid": "2.13.1", - "pinkie-promise": "2.0.1" + "ajv": "5.5.2", + "har-schema": "2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + } } }, "has": { @@ -10044,6 +10374,72 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", @@ -10078,81 +10474,19 @@ "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=", "dev": true }, - "html": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/html/-/html-0.0.10.tgz", - "integrity": "sha1-b9w++GaMCaOhmO46Wqnp8oeLld4=", - "dev": true, - "requires": { - "concat-stream": "1.5.1", - "glob": "3.2.11" - }, - "dependencies": { - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.1", - "minimatch": "0.3.0" - } - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - } - } - }, "html-comment-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "dev": true, "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.3.0", - "domutils": "1.5.1", - "entities": "1.0.0", - "readable-stream": "1.1.14" - }, - "dependencies": { - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.1", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } + "whatwg-encoding": "1.0.3" } }, "http-errors": { @@ -10402,6 +10736,36 @@ "svgo": "0.7.2" } }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + } + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -10492,6 +10856,12 @@ "loose-envify": "1.2.0" } }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, "ip-regex": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", @@ -10513,6 +10883,23 @@ "is-relative": "0.1.3" } }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -10555,12 +10942,57 @@ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "dev": true, + "requires": { + "ci-info": "1.1.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "is-dotfile": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", @@ -10606,6 +11038,12 @@ "number-is-nan": "1.0.0" } }, + "is-generator-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", + "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", + "dev": true + }, "is-gif": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", @@ -10633,18 +11071,6 @@ "integrity": "sha1-KVnBfnNDDbOCZNp1uQ3VTy2G2hw=", "dev": true }, - "is-my-json-valid": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz", - "integrity": "sha1-1Vd4qC/rawlj/0vhEdXRaE6JBwc=", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "2.0.0", - "xtend": "4.0.1" - } - }, "is-natural-number": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", @@ -10666,6 +11092,23 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -10690,25 +11133,19 @@ "path-is-inside": "1.0.2" } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, "is-plain-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz", - "integrity": "sha1-TXylObydubc3uKy2EvIxjvkvKU8=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "1.0.2" + "isobject": "3.0.1" }, "dependencies": { "isobject": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz", - "integrity": "sha1-8Pm4zpLdVA+gdAiC44NaLgIux4o=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } @@ -10737,12 +11174,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", @@ -10755,12 +11186,6 @@ "integrity": "sha1-DVUYK9358v3ieCIK7Dp1ZCyQhjc=", "dev": true }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, "is-relative": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", @@ -10784,12 +11209,6 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, "is-svg": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", @@ -10835,6 +11254,12 @@ "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", "dev": true }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, "is-zip": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", @@ -10877,106 +11302,1424 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "dev": true, - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" + "istanbul-api": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", + "dev": true, + "requires": { + "async": "2.6.0", + "compare-versions": "3.1.0", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.4", + "istanbul-lib-source-maps": "1.2.4", + "istanbul-reports": "1.3.0", + "js-yaml": "3.11.0", + "mkdirp": "0.5.1", + "once": "1.4.0" }, "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.0" + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz", + "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.6" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } } } }, - "jest-docblock": { - "version": "21.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", - "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", "dev": true }, - "jodid25519": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", - "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "istanbul-lib-hook": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz", + "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", "dev": true, - "optional": true, "requires": { - "jsbn": "0.1.0" + "append-transform": "0.4.0" } }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "istanbul-lib-instrument": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "dev": true, "requires": { - "argparse": "1.0.7", - "esprima": "4.0.0" + "babel-generator": "6.24.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" }, "dependencies": { - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true } } }, - "jsbn": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", - "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", - "dev": true, - "optional": true - }, - "jsdom": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.4.1.tgz", - "integrity": "sha1-syLJGHJYS+shQnatNfa0dbrPEjg=", + "istanbul-lib-report": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, "requires": { - "abab": "1.0.3", - "acorn": "2.7.0", - "acorn-globals": "1.0.9", - "array-equal": "1.0.0", - "cssom": "0.3.1", - "cssstyle": "0.2.36", - "escodegen": "1.8.0", - "iconv-lite": "0.4.13", - "nwmatcher": "1.3.8", - "parse5": "1.5.1", - "request": "2.73.0", - "sax": "1.2.1", - "symbol-tree": "3.1.4", - "tough-cookie": "2.2.2", - "webidl-conversions": "3.0.1", - "whatwg-url": "3.0.0", - "xml-name-validator": "2.0.1" + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" }, "dependencies": { - "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", + "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.6" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + } + } + }, + "istanbul-reports": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "jest": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-22.4.3.tgz", + "integrity": "sha512-FFCdU/pXOEASfHxFDOWUysI/+FFoqiXJADEIXgDKuZyqSmBD3tZ4BEGH7+M79v7czj7bbkhwtd2LaEDcJiM/GQ==", + "dev": true, + "requires": { + "import-local": "1.0.0", + "jest-cli": "22.4.3" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "cliui": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", + "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jest-cli": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-22.4.3.tgz", + "integrity": "sha512-IiHybF0DJNqZPsbjn4Cy4vcqcmImpoFwNFnkehzVw8lTUSl4axZh5DHewu5bdpZF2Y5gUqFKYzH0FH4Qx2k+UA==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.2", + "exit": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "import-local": "1.0.0", + "is-ci": "1.1.0", + "istanbul-api": "1.3.1", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-source-maps": "1.2.3", + "jest-changed-files": "22.4.3", + "jest-config": "22.4.3", + "jest-environment-jsdom": "22.4.3", + "jest-get-type": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-message-util": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve-dependencies": "22.4.3", + "jest-runner": "22.4.3", + "jest-runtime": "22.4.3", + "jest-snapshot": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "jest-worker": "22.4.3", + "micromatch": "2.3.11", + "node-notifier": "5.2.1", + "realpath-native": "1.0.0", + "rimraf": "2.6.2", + "slash": "1.0.0", + "string-length": "2.0.0", + "strip-ansi": "4.0.0", + "which": "1.3.0", + "yargs": "10.1.2" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "4.0.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.1.0" + } + } + } + }, + "jest-changed-files": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-22.4.3.tgz", + "integrity": "sha512-83Dh0w1aSkUNFhy5d2dvqWxi/y6weDwVVLU6vmK0cV9VpRxPzhTeGimbsbRDSnEoszhF937M4sDLLeS7Cu/Tmw==", + "dev": true, + "requires": { + "throat": "4.1.0" + } + }, + "jest-config": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-22.4.3.tgz", + "integrity": "sha512-KSg3EOToCgkX+lIvenKY7J8s426h6ahXxaUFJxvGoEk0562Z6inWj1TnKoGycTASwiLD+6kSYFALcjdosq9KIQ==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "glob": "7.1.2", + "jest-environment-jsdom": "22.4.3", + "jest-environment-node": "22.4.3", + "jest-get-type": "22.4.3", + "jest-jasmine2": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "pretty-format": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-diff": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", + "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "diff": "3.5.0", + "jest-get-type": "22.4.3", + "pretty-format": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, + "jest-environment-jsdom": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz", + "integrity": "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w==", + "dev": true, + "requires": { + "jest-mock": "22.4.3", + "jest-util": "22.4.3", + "jsdom": "11.6.2" + } + }, + "jest-environment-node": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-22.4.3.tgz", + "integrity": "sha512-reZl8XF6t/lMEuPWwo9OLfttyC26A5AMgDyEQ6DBgZuyfyeNUzYT8BFo6uxCCP/Av/b7eb9fTi3sIHFPBzmlRA==", + "dev": true, + "requires": { + "jest-mock": "22.4.3", + "jest-util": "22.4.3" + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-haste-map": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-22.4.3.tgz", + "integrity": "sha512-4Q9fjzuPVwnaqGKDpIsCSoTSnG3cteyk2oNVjBX12HHOaF1oxql+uUiqZb5Ndu7g/vTZfdNwwy4WwYogLh29DQ==", + "dev": true, + "requires": { + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.11", + "jest-docblock": "22.4.3", + "jest-serializer": "22.4.3", + "jest-worker": "22.4.3", + "micromatch": "2.3.11", + "sane": "2.5.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "jest-docblock": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-22.4.3.tgz", + "integrity": "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg==", + "dev": true, + "requires": { + "detect-newline": "2.1.0" + } + } + } + }, + "jest-jasmine2": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-22.4.3.tgz", + "integrity": "sha512-yZCPCJUcEY6R5KJB/VReo1AYI2b+5Ky+C+JA1v34jndJsRcLpU4IZX4rFJn7yDTtdNbO/nNqg+3SDIPNH2ecnw==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "co": "4.6.0", + "expect": "22.4.3", + "graceful-fs": "4.1.11", + "is-generator-fn": "1.0.0", + "jest-diff": "22.4.3", + "jest-matcher-utils": "22.4.3", + "jest-message-util": "22.4.3", + "jest-snapshot": "22.4.3", + "jest-util": "22.4.3", + "source-map-support": "0.5.4" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", + "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-22.4.3.tgz", + "integrity": "sha512-NZpR/Ls7+ndO57LuXROdgCGz2RmUdC541tTImL9bdUtU3WadgFGm0yV+Ok4Fuia/1rLAn5KaJ+i76L6e3zGJYQ==", + "dev": true, + "requires": { + "pretty-format": "22.4.3" + } + }, + "jest-matcher-utils": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz", + "integrity": "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "jest-get-type": "22.4.3", + "pretty-format": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-message-util": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.4.3.tgz", + "integrity": "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.42", + "chalk": "2.3.2", + "micromatch": "2.3.11", + "slash": "1.0.0", + "stack-utils": "1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-mock": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-22.4.3.tgz", + "integrity": "sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q==", + "dev": true + }, + "jest-regex-util": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-22.4.3.tgz", + "integrity": "sha512-LFg1gWr3QinIjb8j833bq7jtQopiwdAs67OGfkPrvy7uNUbVMfTXXcOKXJaeY5GgjobELkKvKENqq1xrUectWg==", + "dev": true + }, + "jest-resolve": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-22.4.3.tgz", + "integrity": "sha512-u3BkD/MQBmwrOJDzDIaxpyqTxYH+XqAXzVJP51gt29H8jpj3QgKof5GGO2uPGKGeA1yTMlpbMs1gIQ6U4vcRhw==", + "dev": true, + "requires": { + "browser-resolve": "1.11.2", + "chalk": "2.3.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-22.4.3.tgz", + "integrity": "sha512-06czCMVToSN8F2U4EvgSB1Bv/56gc7MpCftZ9z9fBgUQM7dzHGCMBsyfVA6dZTx8v0FDcnALf7hupeQxaBCvpA==", + "dev": true, + "requires": { + "jest-regex-util": "22.4.3" + } + }, + "jest-runner": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-22.4.3.tgz", + "integrity": "sha512-U7PLlQPRlWNbvOHWOrrVay9sqhBJmiKeAdKIkvX4n1G2tsvzLlf77nBD28GL1N6tGv4RmuTfI8R8JrkvCa+IBg==", + "dev": true, + "requires": { + "exit": "0.1.2", + "jest-config": "22.4.3", + "jest-docblock": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-jasmine2": "22.4.3", + "jest-leak-detector": "22.4.3", + "jest-message-util": "22.4.3", + "jest-runtime": "22.4.3", + "jest-util": "22.4.3", + "jest-worker": "22.4.3", + "throat": "4.1.0" + }, + "dependencies": { + "jest-docblock": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-22.4.3.tgz", + "integrity": "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg==", + "dev": true, + "requires": { + "detect-newline": "2.1.0" + } + } + } + }, + "jest-runtime": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-22.4.3.tgz", + "integrity": "sha512-Eat/esQjevhx9BgJEC8udye+FfoJ2qvxAZfOAWshYGS22HydHn5BgsvPdTtt9cp0fSl5LxYOFA1Pja9Iz2Zt8g==", + "dev": true, + "requires": { + "babel-core": "6.24.1", + "babel-jest": "22.4.3", + "babel-plugin-istanbul": "4.1.5", + "chalk": "2.3.2", + "convert-source-map": "1.5.0", + "exit": "0.1.2", + "graceful-fs": "4.1.11", + "jest-config": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "json-stable-stringify": "1.0.1", + "micromatch": "2.3.11", + "realpath-native": "1.0.0", + "slash": "1.0.0", + "strip-bom": "3.0.0", + "write-file-atomic": "2.3.0", + "yargs": "10.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "cliui": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", + "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "4.0.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.1.0" + } + } + } + }, + "jest-serializer": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-22.4.3.tgz", + "integrity": "sha512-uPaUAppx4VUfJ0QDerpNdF43F68eqKWCzzhUlKNDsUPhjOon7ZehR4C809GCqh765FoMRtTVUVnGvIoskkYHiw==", + "dev": true + }, + "jest-snapshot": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-22.4.3.tgz", + "integrity": "sha512-JXA0gVs5YL0HtLDCGa9YxcmmV2LZbwJ+0MfyXBBc5qpgkEYITQFJP7XNhcHFbUvRiniRpRbGVfJrOoYhhGE0RQ==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "jest-diff": "22.4.3", + "jest-matcher-utils": "22.4.3", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "pretty-format": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-util": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-22.4.3.tgz", + "integrity": "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ==", + "dev": true, + "requires": { + "callsites": "2.0.0", + "chalk": "2.3.2", + "graceful-fs": "4.1.11", + "is-ci": "1.1.0", + "jest-message-util": "22.4.3", + "mkdirp": "0.5.1", + "source-map": "0.6.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-validate": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-22.4.3.tgz", + "integrity": "sha512-CfFM18W3GSP/xgmA4UouIx0ljdtfD2mjeBC6c89Gg17E44D4tQhAcTrZmf9djvipwU30kSTnk6CzcxdCCeSXfA==", + "dev": true, + "requires": { + "chalk": "2.3.2", + "jest-config": "22.4.3", + "jest-get-type": "22.4.3", + "leven": "2.1.0", + "pretty-format": "22.4.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "jest-worker": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-22.4.3.tgz", + "integrity": "sha512-B1ucW4fI8qVAuZmicFxI1R3kr2fNeYJyvIQ1rKcuLYnenFV5K5aMbxFj6J0i00Ju83S8jP2d7Dz14+AvbIHRYQ==", + "dev": true, + "requires": { + "merge-stream": "1.0.1" + } + }, + "jodid25519": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz", + "integrity": "sha1-BtSRIlUJNBlHfUJWM2BuDpB4KWc=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true, + "requires": { + "argparse": "1.0.7", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "dev": true, + "optional": true + }, + "jsdom": { + "version": "11.6.2", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.6.2.tgz", + "integrity": "sha512-pAeZhpbSlUp5yQcS6cBQJwkbzmv4tWFaYxHbFVSxzXefqjvtRA851Z5N2P+TguVG9YeUDcgb8pdeVQRJh0XR3Q==", + "dev": true, + "requires": { + "abab": "1.0.4", + "acorn": "5.5.3", + "acorn-globals": "4.1.0", + "array-equal": "1.0.0", + "browser-process-hrtime": "0.1.2", + "content-type-parser": "1.0.2", + "cssom": "0.3.2", + "cssstyle": "0.2.37", + "domexception": "1.0.1", + "escodegen": "1.9.1", + "html-encoding-sniffer": "1.0.2", + "left-pad": "1.2.0", + "nwmatcher": "1.4.4", + "parse5": "4.0.0", + "pn": "1.1.0", + "request": "2.85.0", + "request-promise-native": "1.0.5", + "sax": "1.2.4", + "symbol-tree": "3.2.2", + "tough-cookie": "2.3.4", + "w3c-hr-time": "1.0.1", + "webidl-conversions": "4.0.2", + "whatwg-encoding": "1.0.3", + "whatwg-url": "6.4.0", + "ws": "4.1.0", + "xml-name-validator": "3.0.0" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true } } @@ -11062,12 +12805,6 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsonpointer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz", - "integrity": "sha1-OvHdIP6FRjkQ1GmjheMwF9KgMNk=", - "dev": true - }, "jsprim": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz", @@ -11136,6 +12873,27 @@ "readable-stream": "2.1.4" } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "left-pad": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.2.0.tgz", + "integrity": "sha1-0wpzxrggHY99jnlWupYWCHpo4O4=", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -11203,6 +12961,16 @@ } } }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -11383,6 +13151,12 @@ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.template": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", @@ -11420,12 +13194,6 @@ "squeak": "1.3.0" } }, - "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true - }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -11490,12 +13258,27 @@ "pify": "2.3.0" } }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.4" + } + }, "manage-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/manage-path/-/manage-path-2.0.0.tgz", "integrity": "sha1-9M+EV7km7u4qg7FzUBQUvHbrlZc=", "dev": true }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", @@ -11508,12 +13291,30 @@ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", "dev": true }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.2.0" + } + }, "memory-fs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", @@ -11638,6 +13439,33 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -11655,64 +13483,6 @@ } } }, - "mocha": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", - "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", - "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", - "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" - }, - "dependencies": { - "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true - }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", - "dev": true, - "requires": { - "inherits": "2.0.1", - "minimatch": "0.3.0" - } - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "dev": true, - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, - "supports-color": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", - "dev": true - } - } - }, "mozjpeg": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-4.1.1.tgz", @@ -11752,6 +13522,65 @@ "dev": true, "optional": true }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -11788,6 +13617,12 @@ "is-stream": "1.1.0" } }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, "node-libs-browser": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.7.0.tgz", @@ -11819,18 +13654,47 @@ "vm-browserify": "0.0.4" } }, + "node-notifier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", + "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "dev": true, + "requires": { + "growly": "1.3.0", + "semver": "5.5.0", + "shellwords": "0.1.1", + "which": "1.3.0" + }, + "dependencies": { + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + } + } + }, "node-status-codes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", "dev": true }, - "node-uuid": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", - "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=", - "dev": true - }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -12155,15 +14019,6 @@ } } }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, "number-is-nan": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", @@ -12171,9 +14026,9 @@ "dev": true }, "nwmatcher": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.3.8.tgz", - "integrity": "sha1-NO25PeGqbLREi1c8nyoFkwAkEVc=", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", "dev": true }, "nyc": { @@ -13790,11 +15645,64 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + } + } }, "object-keys": { "version": "1.0.11", @@ -13802,15 +15710,31 @@ "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", "dev": true }, - "object.assign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", - "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { "define-properties": "1.1.2", - "function-bind": "1.1.0", - "object-keys": "1.0.11" + "es-abstract": "1.5.1" } }, "object.omit": { @@ -13823,29 +15747,20 @@ "is-extendable": "0.1.1" } }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.7.0", - "function-bind": "1.1.0", - "has": "1.0.1" + "isobject": "3.0.1" }, "dependencies": { - "es-abstract": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", - "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", - "dev": true, - "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.0", - "is-callable": "1.1.3", - "is-regex": "1.0.3" - } + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -13930,13 +15845,13 @@ } }, "optionator": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.1.tgz", - "integrity": "sha1-4xtJMs3V+4Yqiw0QvGPT7h7H14s=", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { "deep-is": "0.1.3", - "fast-levenshtein": "1.1.3", + "fast-levenshtein": "2.0.6", "levn": "0.3.0", "prelude-ls": "1.1.2", "type-check": "0.3.2", @@ -14010,6 +15925,76 @@ "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", "dev": true }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.2.10" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.0", + "strip-eof": "1.0.0" + } + }, + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, "os-tmpdir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.1.tgz", @@ -14043,12 +16028,36 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, "p-pipe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", "dev": true }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -14083,9 +16092,9 @@ } }, "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true }, "parseurl": { @@ -14094,6 +16103,12 @@ "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", "dev": true }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", @@ -14106,6 +16121,12 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", @@ -14134,6 +16155,12 @@ "lodash.assign": "3.2.0" } }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -14214,6 +16241,12 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "pngquant-bin": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-3.1.1.tgz", @@ -14225,6 +16258,12 @@ "logalot": "2.1.0" } }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -14249,6 +16288,33 @@ "integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==", "dev": true }, + "pretty-format": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", + "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "dev": true, + "requires": { + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + } + } + }, "pretty-hrtime": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", @@ -14516,26 +16582,65 @@ } } }, - "react-element-to-jsx-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-3.1.0.tgz", - "integrity": "sha1-8pgaRns6bJizRyelxDMWhs9Aagg=", + "react-test-renderer": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.2.0.tgz", + "integrity": "sha512-Kd4gJFtpNziR9ElOE/C23LeflKLZPRpNQYWP3nQBY43SJ5a+xyEGSeMrm2zxNKXcnCbBS/q1UpD9gqd5Dv+rew==", "dev": true, "requires": { - "collapse-white-space": "1.0.0", - "is-plain-object": "2.0.1", - "lodash": "3.10.1", - "react-addons-test-utils": "15.6.0", - "sortobject": "1.1.1", - "stringify-object": "2.4.0", - "traverse": "0.6.6" + "fbjs": "0.8.16", + "object-assign": "4.1.1", + "prop-types": "15.6.1" }, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + }, + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "dev": true, + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.2.0", + "object-assign": "4.1.1", + "promise": "7.1.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.12" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + } + } } } }, @@ -14597,6 +16702,15 @@ "set-immediate-shim": "1.0.1" } }, + "realpath-native": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.0.tgz", + "integrity": "sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==", + "dev": true, + "requires": { + "util.promisify": "1.0.0" + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -14679,6 +16793,37 @@ "is-primitive": "2.0.0" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", @@ -14713,6 +16858,12 @@ } } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", @@ -14731,42 +16882,198 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.1" + "is-finite": "1.0.1" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.3.0", + "sshpk": "1.8.3" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + } + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, + "requires": { + "lodash": "4.17.4" } }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "2.73.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.73.0.tgz", - "integrity": "sha1-X3ip/eQ3CryP9kedeoSnGhS4eKI=", + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.4.1", - "bl": "1.1.2", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.0", - "forever-agent": "0.6.1", - "form-data": "1.0.0-rc4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.11", - "node-uuid": "1.4.7", - "oauth-sign": "0.8.2", - "qs": "6.2.0", - "stringstream": "0.0.5", - "tough-cookie": "2.2.2", - "tunnel-agent": "0.4.3" + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" } }, "require-dir": { @@ -14775,6 +17082,18 @@ "integrity": "sha1-geAeKZ+vW3TDS2WU+OWt1Zhd3sU=", "dev": true }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "require-relative": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", @@ -14803,12 +17122,35 @@ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, "restore-cursor": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", @@ -14819,6 +17161,12 @@ "onetime": "1.1.0" } }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "retry": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", @@ -14849,80 +17197,430 @@ "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.5", - "inherits": "2.0.1", - "minimatch": "3.0.2", - "once": "1.3.3", - "path-is-absolute": "1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + } + } + }, + "ripemd160": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", + "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", + "dev": true + }, + "run-async": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz", + "integrity": "sha1-h4Or2Dx7uG9B7gYC/IJASzvW6Lk=", + "dev": true, + "requires": { + "is-promise": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "run-auto": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/run-auto/-/run-auto-1.1.3.tgz", + "integrity": "sha1-wtUWP+wat4tjRc3TmS/OAy9nH4g=", + "dev": true, + "requires": { + "dezalgo": "1.0.3" + } + }, + "run-series": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.4.tgz", + "integrity": "sha1-iac93F51ye+KtjIMChYA1qQRebk=", + "dev": true + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", + "dev": true + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "sane": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.0.tgz", + "integrity": "sha512-glfKd7YH4UCrh/7dD+UESsr8ylKWRE7UQPoXuz28FgmcF0ViJQhCTCCZHICRKxf8G8O1KdLEn20dcICK54c7ew==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "exec-sh": "0.2.1", + "fb-watchman": "2.0.0", + "fsevents": "1.1.1", + "micromatch": "3.1.10", + "minimist": "1.2.0", + "walker": "1.0.7", + "watch": "0.18.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true } } }, - "ripemd160": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz", - "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", - "dev": true - }, - "run-async": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz", - "integrity": "sha1-h4Or2Dx7uG9B7gYC/IJASzvW6Lk=", - "dev": true, - "requires": { - "is-promise": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "run-auto": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/run-auto/-/run-auto-1.1.3.tgz", - "integrity": "sha1-wtUWP+wat4tjRc3TmS/OAy9nH4g=", - "dev": true, - "requires": { - "dezalgo": "1.0.3" - } - }, - "run-series": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.4.tgz", - "integrity": "sha1-iac93F51ye+KtjIMChYA1qQRebk=", - "dev": true - }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=", - "dev": true - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true - }, "sax": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", @@ -15075,8 +17773,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true, - "optional": true + "dev": true }, "set-immediate-shim": { "version": "1.0.1", @@ -15084,6 +17781,18 @@ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -15134,6 +17843,12 @@ "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", "dev": true }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -15146,18 +17861,6 @@ "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g=", "dev": true }, - "sinon": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.4.tgz", - "integrity": "sha1-Tk/02Esgre4TE482rLEyyhzXLIM=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": "0.10.3" - } - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -15187,6 +17890,150 @@ "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.2.0", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.6", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", @@ -15231,15 +18078,6 @@ } } }, - "sortobject": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sortobject/-/sortobject-1.1.1.tgz", - "integrity": "sha1-T2ldTUTtCkwGSCw0wlgqLc3CqzQ=", - "dev": true, - "requires": { - "editions": "1.1.2" - } - }, "source-list-map": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", @@ -15252,6 +18090,19 @@ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, "source-map-support": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz", @@ -15261,6 +18112,12 @@ "source-map": "0.5.6" } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "sparkles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", @@ -15313,6 +18170,36 @@ "through": "2.3.8" } }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -15354,18 +18241,114 @@ } } }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", - "dev": true - }, + "stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha1-1PM6tU6OOHeLDKXP07OvsS22hiA=", + "dev": true + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", @@ -15463,6 +18446,33 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "1.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, "string-width": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz", @@ -15491,16 +18501,6 @@ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, - "stringify-object": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-2.4.0.tgz", - "integrity": "sha1-xi0RAj6yH+LZsIe+A5om3zsioJ0=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0", - "is-regexp": "1.0.0" - } - }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -15628,9 +18628,9 @@ } }, "symbol-tree": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.1.4.tgz", - "integrity": "sha1-ArJ5NI0zfevDlpTFyV+ILUSKMSo=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", "dev": true }, "table": { @@ -15760,37 +18760,362 @@ "once": "1.4.0" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "requires": { - "temp-dir": "1.0.0", - "uuid": "3.1.0" - }, - "dependencies": { - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", + "dev": true, + "requires": { + "temp-dir": "1.0.0", + "uuid": "3.1.0" + }, + "dependencies": { + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + } + } + }, + "test-exclude": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", + "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "3.1.10", + "object-assign": "4.1.0", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true } } @@ -15801,6 +19126,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -15890,6 +19221,12 @@ } } }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, "to-absolute-glob": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", @@ -15911,29 +19248,100 @@ "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", "dev": true }, - "to-iso-string": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", - "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", - "dev": true + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + } + } }, "tough-cookie": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", - "integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc=", - "dev": true + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } }, "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=", + "dev": true + } + } }, "trim-newlines": { "version": "1.0.0", @@ -15984,12 +19392,6 @@ "prelude-ls": "1.1.2" } }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, "type-is": { "version": "1.6.14", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz", @@ -16028,6 +19430,18 @@ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz", "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=" }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, "uglify-to-browserify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", @@ -16040,6 +19454,32 @@ "integrity": "sha1-Wj2yPvXb1VuB/ODsmirG/M3ruB4=", "dev": true }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, "unique-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", @@ -16052,12 +19492,64 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "unzip-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", "dev": true }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -16110,6 +19602,23 @@ "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=", "dev": true }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -16131,6 +19640,16 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "object.getownpropertydescriptors": "2.0.3" + } + }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", @@ -16291,6 +19810,15 @@ "indexof": "0.0.1" } }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "0.1.2" + } + }, "walk": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.9.tgz", @@ -16300,6 +19828,15 @@ "foreachasync": "3.0.0" } }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.11" + } + }, "ware": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", @@ -16309,6 +19846,16 @@ "wrap-fn": "0.1.5" } }, + "watch": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", + "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", + "dev": true, + "requires": { + "exec-sh": "0.2.1", + "minimist": "1.2.0" + } + }, "watchpack": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz", @@ -16335,9 +19882,9 @@ "dev": true }, "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, "webpack": { @@ -16498,29 +20045,37 @@ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", "dev": true }, + "whatwg-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz", + "integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.19" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + } + } + }, "whatwg-fetch": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz", "integrity": "sha1-B4uUYbvpHOpzy86LsSKgX56St3I=" }, "whatwg-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-3.0.0.tgz", - "integrity": "sha1-uQM8UMfOdj6R14d3zoJabX9W2sU=", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.0.tgz", + "integrity": "sha512-Z0CVh/YE217Foyb488eo+iBv+r7eAQ0wSTyApi9n06jhcA3z6Nidg/EGvl0UFkg7kMdKxfBzzr+o9JF+cevgMg==", "dev": true, "requires": { - "tr46": "0.0.3", - "webidl-conversions": "3.0.1" - } - }, - "whatwg-url-compat": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", - "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", - "dev": true, - "optional": true, - "requires": { - "tr46": "0.0.3" + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" } }, "whet.extend": { @@ -16538,6 +20093,12 @@ "isexe": "1.1.2" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", @@ -16580,6 +20141,16 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.1", + "strip-ansi": "3.0.1" + } + }, "wrap-fn": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", @@ -16604,10 +20175,45 @@ "mkdirp": "0.5.1" } }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + } + } + }, + "ws": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", + "dev": true, + "requires": { + "async-limiter": "1.0.0", + "safe-buffer": "5.1.1" + } + }, "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, "xtend": { @@ -16616,6 +20222,12 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yallist": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", @@ -16642,6 +20254,23 @@ } } }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, "yauzl": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", diff --git a/package.json b/package.json index e747d785..d5d51763 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "commit": "git-cz", "watch:test": "npm t -- -w", - "test": "mocha src/tests/setup.js src/tests/index.spec.js", + "test": "jest", "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:*", "build:main": "babel --copy-files --out-dir dist --ignore *.spec.js src", @@ -58,6 +58,7 @@ "devDependencies": { "babel-cli": "^6.23.0", "babel-eslint": "8.2.2", + "babel-jest": "22.4.3", "babel-loader": "^6.3.2", "babel-plugin-react-transform": "^2.0.2", "babel-plugin-transform-class-properties": "^6.24.1", @@ -66,12 +67,9 @@ "babel-preset-react": "^6.23.1", "babel-preset-stage-0": "^6.22.0", "babel-register": "^6.23.0", - "chai": "3.5.0", - "chai-enzyme": "0.5.0", "commitizen": "2.8.2", "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", - "enzyme": "2.4.1", "eslint": "4.18.2", "eslint-config-prettier": "2.9.0", "eslint-plugin-prettier": "2.6.0", @@ -80,18 +78,17 @@ "gh-pages": "^0.12.0", "ghooks": "1.3.2", "image-webpack-loader": "3.3.1", - "jsdom": "9.4.1", + "jest": "22.4.3", "json-loader": "0.5.4", - "mocha": "2.5.3", "npm-run-all": "2.3.0", "nyc": "7.0.0", "prettier": "1.10.2", "react": "^15.6.1", "react-addons-test-utils": "^15.6.0", "react-dom": "^15.6.1", + "react-test-renderer": "16.2.0", "rimraf": "2.5.3", "semantic-release": "^4.3.5", - "sinon": "1.17.4", "webpack": "^1.14.0", "webpack-dev-server": "^1.16.2" }, diff --git a/src/tests/index.spec.js b/src/tests/index.spec.js deleted file mode 100644 index 273bb39e..00000000 --- a/src/tests/index.spec.js +++ /dev/null @@ -1,443 +0,0 @@ -// /* eslint-disable react/prop-types, quotes */ -// import React from 'react'; -// import { mount, shallow } from 'enzyme'; -// import sinon from 'sinon'; -// import { expect } from './testHelper'; -// import PlacesAutocomplete from '../index.js'; -// -// const testInputProps = { -// value: 'San Francisco, CA', -// onChange: () => {}, -// }; -// -// /*** Enzyme Rocks ***/ -// describe('', () => { -// let wrapper; -// beforeEach(() => { -// wrapper = shallow(); -// }); -// -// it('renders an input element', () => { -// expect(wrapper.find('input')).to.have.length(1); -// }); -// }); -// -// // TODO: What's the value of this test? -// describe('PlacesAutocomplete callbacks', () => { -// it('executes onError callback passed in as prop when status is not OK', () => { -// const spy = sinon.spy(); -// const wrapper = mount( -// -// ); -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); -// expect(spy.calledOnce).to.equal(true); -// expect(spy.calledWith('ZERO_RESULTS')).to.equal(true); -// }); -// -// it('executes default onError function when there is no custom prop and status is not OK', () => { -// sinon.stub(console, 'error'); -// const wrapper = mount(); -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); -// expect(console.error.calledOnce).to.equal(true); // eslint-disable-line no-console -// }); -// }); -// -// describe('PlacesAutocomplete props', () => { -// it('allows user to set the value of the input through prop', () => { -// const inputProps = { -// ...testInputProps, -// value: 'New York, NY', -// }; -// -// const wrapper = mount(); -// expect(wrapper.find('input').props().value).to.equal('New York, NY'); -// }); -// }); -// -// describe('autocomplete dropdown', () => { -// let wrapper; -// const renderSuggestion = ({ suggestion }) => ( -//
{suggestion}
-// ); -// const renderFooter = () => ( -//
Footer element
-// ); -// beforeEach(() => { -// wrapper = shallow( -// -// ); -// }); -// -// it('initially does not have an autocomplete dropdown', () => { -// expect( -// wrapper.find('#PlacesAutocomplete__autocomplete-container') -// ).to.have.length(0); -// }); -// -// it('renders autocomplete dropdown once it receives data from google maps', () => { -// const data = [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// { -// suggestion: 'San Jose, CA', -// placeId: 2, -// active: false, -// index: 1, -// }, -// { -// suggestion: 'San Diego, CA', -// placeId: 3, -// active: false, -// index: 2, -// }, -// ]; -// wrapper.setState({ autocompleteItems: data }); -// expect( -// wrapper.find('#PlacesAutocomplete__autocomplete-container') -// ).to.have.length(1); -// expect(wrapper.find('.autocomplete-item')).to.have.length(3); -// expect(wrapper.find('.my-dropdown-footer')).to.have.length(1); -// }); -// -// it('clears the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is true', () => { -// const initialItems = [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ]; -// const wrapper = shallow( -// -// ); -// wrapper.setState({ autocompleteItems: initialItems }); -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); -// expect(wrapper.find('.autocomplete-item')).to.have.length(0); -// }); -// -// it('does not clear the autocomplete items when PlacesServiceStatus is not OK and clearSuggestionsOnError prop is false', () => { -// const initialItems = [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ]; -// wrapper.setState({ autocompleteItems: initialItems }); -// wrapper.instance().autocompleteCallback([], 'ZERO_RESULTS'); -// expect(wrapper.find('.autocomplete-item')).to.have.length(1); -// }); -// }); -// -// describe('custom classNames, placeholder', () => { -// const inputProps = { -// ...testInputProps, -// placeholder: 'Your Address', -// }; -// -// const classNames = { -// root: 'my-container', -// input: 'my-input', -// autocompleteContainer: 'my-autocomplete-container', -// }; -// -// let wrapper; -// -// beforeEach(() => { -// wrapper = shallow( -// -// ); -// }); -// -// it('lets you set a custom className for the container', () => { -// expect(wrapper.find('.my-container')).to.have.length(1); -// }); -// -// it('lets you set a custom className for the input', () => { -// expect(wrapper.find('input')).to.have.className('my-input'); -// }); -// -// it('lets you set a custom className for autocomplete container', () => { -// wrapper.setState({ -// autocompleteItems: [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ], -// }); -// expect( -// wrapper.find('#PlacesAutocomplete__autocomplete-container') -// ).to.have.className('my-autocomplete-container'); -// }); -// -// it('lets you set a custom placeholder for the input', () => { -// expect(wrapper.find('input').props().placeholder).to.equal('Your Address'); -// }); -// }); -// -// // TODO: test formattedSuggestion -// describe('customizable autocompleteItem', () => { -// it('lets you provide a custom autocomplete item', () => { -// const renderSuggestion = ({ suggestion }) => ( -//
-// -// {suggestion} -//
-// ); -// const wrapper = shallow( -// -// ); -// wrapper.setState({ -// autocompleteItems: [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ], -// }); -// expect(wrapper.find('.my-autocomplete-item')).to.have.length(1); -// expect(wrapper.find('.my-autocomplete-item')).to.contain( -// -// ); -// }); -// }); -// -// describe('custom inline styles', () => { -// const styles = { -// root: { position: 'absolute' }, -// input: { width: '100%' }, -// autocompleteContainer: { backgroundColor: 'green' }, -// autocompleteItem: { color: 'black' }, -// autocompleteItemActive: { color: 'blue' }, -// }; -// -// let wrapper; -// beforeEach(() => { -// wrapper = shallow( -// -// ); -// }); -// -// it('lets you set custom styles for the root element', () => { -// expect( -// wrapper.find('#PlacesAutocomplete__root').props().style.position -// ).to.equal('absolute'); -// }); -// -// it('lets you set custom styles for the input element', () => { -// expect(wrapper.find('input').props().style.width).to.equal('100%'); -// }); -// -// it('lets you set custom styles for the autocomplete container element', () => { -// wrapper.setState({ -// autocompleteItems: [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ], -// }); -// expect( -// wrapper.find('#PlacesAutocomplete__autocomplete-container').props().style -// .backgroundColor -// ).to.equal('green'); -// }); -// -// it('lets you set custom styles for autocomplete items', () => { -// wrapper.setState({ -// autocompleteItems: [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// ], -// }); -// const item = wrapper -// .find('#PlacesAutocomplete__autocomplete-container') -// .childAt(0); -// expect(item.props().style.color).to.equal('black'); -// }); -// -// it('lets you set custom styles for active autocomplete items', () => { -// wrapper.setState({ -// autocompleteItems: [ -// { suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }, -// ], -// }); -// const item = wrapper -// .find('#PlacesAutocomplete__autocomplete-container') -// .childAt(0); -// expect(item.props().style.color).to.equal('blue'); -// }); -// }); -// -// describe('AutocompletionRequest options', () => { -// const inputProps = { -// ...testInputProps, -// value: 'Boston, MA', -// }; -// it('calls getPlacePredictions with the correct options', done => { -// global.google.maps.places.AutocompleteService.prototype.getPlacePredictions = () => {}; -// const spy = sinon.spy( -// global.google.maps.places.AutocompleteService.prototype, -// 'getPlacePredictions' -// ); -// const options = { radius: 2000, types: ['address'] }; -// const wrapper = mount( -// -// ); -// wrapper -// .find('input') -// .simulate('change', { target: { value: 'Los Angeles, CA' } }); -// setTimeout(() => { -// done(); -// expect(spy.calledWith({ ...options, input: 'Los Angeles, CA' })).to.be -// .true; -// }, 0); -// }); -// }); -// -// describe('autoFocus prop', () => { -// const inputProps = { -// ...testInputProps, -// autoFocus: true, -// }; -// -// it('automatically gives focus when set to true', () => { -// const wrapper = mount(); -// expect(wrapper.find('input').node).to.equal(document.activeElement); -// }); -// -// it('does not give the input element a focus by default', () => { -// const wrapper = mount(); -// expect(wrapper.find('input').node).to.not.equal(document.activeElement); -// }); -// }); -// -// describe("Enables using original input's value as it was another entry in autocomplete", () => { -// const data = [ -// { -// suggestion: 'San Francisco, CA', -// placeId: 1, -// active: false, -// index: 0, -// }, -// { -// suggestion: 'San Jose, CA', -// placeId: 2, -// active: false, -// index: 1, -// }, -// { -// suggestion: 'San Diego, CA', -// placeId: 3, -// active: false, -// index: 2, -// }, -// ]; -// const spy = sinon.spy(); -// const inputProps = { -// value: 'san', -// onChange: spy, -// }; -// let wrapper; -// -// beforeEach(() => { -// wrapper = shallow(); -// spy.reset(); -// }); -// -// it('save value of input when pressing arrow down key and none of autocomplete entries is being focused', () => { -// wrapper.setState({ autocompleteItems: data }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// expect(wrapper.state().userInputValue).to.equal('san'); -// }); -// -// it('save value of input when pressing arrow up key and none of autocomplete entries is being focused', () => { -// wrapper.setState({ autocompleteItems: data }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); -// expect(wrapper.state().userInputValue).to.equal('san'); -// }); -// -// it("don't focus on any entry when focus is on last item and arrow down key is pressed", () => { -// const lastItemActive = data.map((item, idx) => { -// return idx === data.length - 1 ? { ...item, active: true } : item; -// }); -// wrapper.setState({ autocompleteItems: lastItemActive }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// wrapper.state().autocompleteItems.forEach(item => { -// expect(item.active).to.be.false; -// }); -// }); -// -// it("don't focus on any entry when focus is on first item and arrow up key is pressed", () => { -// const firstItemActive = data.map((item, idx) => { -// return idx === 0 ? { ...item, active: true } : item; -// }); -// wrapper.setState({ autocompleteItems: firstItemActive }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowUp', preventDefault: () => {} }); -// wrapper.state().autocompleteItems.forEach(item => { -// expect(item.active).to.be.false; -// }); -// }); -// -// it('onChange function is called with appropriate value', () => { -// // Amount of entries is 3 for this test case, so when we press arrow down fourth time -// // we expect onChange function to be called with original input value -// // being stored in `userInputValue` state entry -// // rest of calls should be called with appropraite entries from autocomplete items -// wrapper.setState({ autocompleteItems: data }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// wrapper -// .instance() -// .handleInputKeyDown({ key: 'ArrowDown', preventDefault: () => {} }); -// expect(spy.getCall(0).args[0]).to.equal(data[0].suggestion); -// expect(spy.getCall(1).args[0]).to.equal(data[1].suggestion); -// expect(spy.getCall(2).args[0]).to.equal(data[2].suggestion); -// expect(spy.getCall(3).args[0]).to.equal(wrapper.state().userInputValue); -// }); -// }); -// -// // TODOs: -// // * Test geocodeByAddress function diff --git a/src/tests/index.test.js b/src/tests/index.test.js new file mode 100644 index 00000000..61b818ae --- /dev/null +++ b/src/tests/index.test.js @@ -0,0 +1,3 @@ +test('smoke test', () => { + expect(true).toBe(true); +}); diff --git a/src/tests/setup.js b/src/tests/setup.js index db0c1eb2..291e9e9e 100644 --- a/src/tests/setup.js +++ b/src/tests/setup.js @@ -1,24 +1,24 @@ -// This file does the following: -// 1. Sets the environment to 'production' so that -// dev-specific babel config in .babelrc doesn't run. -// 2. Disables Webpack-specific features that Mocha doesn't understand. -// 3. Registers babel for transpiling our code for testing. - -// This assures the .babelrc dev config doesn't apply for tests. -process.env.NODE_ENV = 'production'; - -// Disable webpack-specific features for tests since -// Mocha doesn't know what to do with them. -require.extensions['.css'] = function() { - return null; -}; -require.extensions['.png'] = function() { - return null; -}; -require.extensions['.jpg'] = function() { - return null; -}; - -// Register babel so that it will transpile ES6 to ES5 -// before our tests run. -require('babel-register')(); +// // This file does the following: +// // 1. Sets the environment to 'production' so that +// // dev-specific babel config in .babelrc doesn't run. +// // 2. Disables Webpack-specific features that Mocha doesn't understand. +// // 3. Registers babel for transpiling our code for testing. +// +// // This assures the .babelrc dev config doesn't apply for tests. +// process.env.NODE_ENV = 'production'; +// +// // Disable webpack-specific features for tests since +// // Mocha doesn't know what to do with them. +// require.extensions['.css'] = function() { +// return null; +// }; +// require.extensions['.png'] = function() { +// return null; +// }; +// require.extensions['.jpg'] = function() { +// return null; +// }; +// +// // Register babel so that it will transpile ES6 to ES5 +// // before our tests run. +// require('babel-register')(); diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js index 7c0292e4..00008fcc 100644 --- a/src/tests/testHelper.js +++ b/src/tests/testHelper.js @@ -1,25 +1,25 @@ -import chai, { expect } from 'chai'; -import chaiEnzyme from 'chai-enzyme'; -import jsdom from 'jsdom'; - -/*** Set up test environment to run in a browser-like environment ***/ -global.document = jsdom.jsdom(''); -global.window = global.document.defaultView; - -/*** Mock Google Maps JavaScript API ***/ -const google = { - maps: { - places: { - AutocompleteService: () => {}, - PlacesServiceStatus: { - OK: 'OK', - }, - }, - }, -}; -global.google = google; -global.window.google = google; - -chai.use(chaiEnzyme()); - -export { expect }; +// import chai, { expect } from 'chai'; +// import chaiEnzyme from 'chai-enzyme'; +// import jsdom from 'jsdom'; +// +// /*** Set up test environment to run in a browser-like environment ***/ +// global.document = jsdom.jsdom(''); +// global.window = global.document.defaultView; +// +// /*** Mock Google Maps JavaScript API ***/ +// const google = { +// maps: { +// places: { +// AutocompleteService: () => {}, +// PlacesServiceStatus: { +// OK: 'OK', +// }, +// }, +// }, +// }; +// global.google = google; +// global.window.google = google; +// +// chai.use(chaiEnzyme()); +// +// export { expect }; From 6441dc92f039c1faf145b844f7381a27a697ef04 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 24 Mar 2018 20:51:22 -0700 Subject: [PATCH 114/165] Add jest test snapshots --- package-lock.json | 99 +++++++++------------- package.json | 6 +- src/tests/__snapshots__/index.test.js.snap | 21 +++++ src/tests/index.test.js | 58 +++++++++++++ src/tests/testHelper.js | 37 +++----- 5 files changed, 133 insertions(+), 88 deletions(-) create mode 100644 src/tests/__snapshots__/index.test.js.snap diff --git a/package-lock.json b/package-lock.json index 95d15c21..ceea0eec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6006,34 +6006,6 @@ "capture-stack-trace": "1.0.0" } }, - "create-react-class": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz", - "integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ=", - "dev": true, - "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - }, - "dependencies": { - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "3.0.2" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - } - } - }, "cross-spawn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz", @@ -8115,9 +8087,9 @@ } }, "fbjs": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", - "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=", + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", "dev": true, "requires": { "core-js": "1.2.7", @@ -16506,26 +16478,32 @@ } }, "react": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/react/-/react-15.6.1.tgz", - "integrity": "sha1-uqhDTsZ4C96ZfNw4C3nNM7ljk98=", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.2.0.tgz", + "integrity": "sha512-ZmIomM7EE1DvPEnSFAHZn9Vs9zJl5A9H7el0EGTE6ZbW9FKe/14IYAlPbC8iH25YarEQxZL+E8VW7Mi7kfQrDQ==", "dev": true, "requires": { - "create-react-class": "15.6.0", - "fbjs": "0.8.14", + "fbjs": "0.8.16", "loose-envify": "1.2.0", - "object-assign": "4.1.0", - "prop-types": "15.5.10" + "object-assign": "4.1.1", + "prop-types": "15.6.1" }, "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, "prop-types": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "dev": true, "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" }, "dependencies": { "loose-envify": { @@ -16541,32 +16519,33 @@ } } }, - "react-addons-test-utils": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.6.0.tgz", - "integrity": "sha1-Bi02EX/o0Y87peBuszODsLhepbk=", - "dev": true - }, "react-dom": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz", - "integrity": "sha1-LLDtQZEDjlPCCes6eaI+Kkz5lHA=", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.2.0.tgz", + "integrity": "sha512-zpGAdwHVn9K0091d+hr+R0qrjoJ84cIBFL2uU60KvWBPfZ7LPSrfqviTxGHWN0sjPZb2hxWzMexwrvJdKePvjg==", "dev": true, "requires": { - "fbjs": "0.8.14", + "fbjs": "0.8.16", "loose-envify": "1.2.0", - "object-assign": "4.1.0", - "prop-types": "15.5.10" + "object-assign": "4.1.1", + "prop-types": "15.6.1" }, "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, "prop-types": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "dev": true, "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" }, "dependencies": { "loose-envify": { diff --git a/package.json b/package.json index d5d51763..ef767b01 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "commit": "git-cz", "watch:test": "npm t -- -w", "test": "jest", + "test:update": "jest --updateSnapshot", "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:*", "build:main": "babel --copy-files --out-dir dist --ignore *.spec.js src", @@ -83,9 +84,8 @@ "npm-run-all": "2.3.0", "nyc": "7.0.0", "prettier": "1.10.2", - "react": "^15.6.1", - "react-addons-test-utils": "^15.6.0", - "react-dom": "^15.6.1", + "react": "^16.2.0", + "react-dom": "^16.2.0", "react-test-renderer": "16.2.0", "rimraf": "2.5.3", "semantic-release": "^4.3.5", diff --git a/src/tests/__snapshots__/index.test.js.snap b/src/tests/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..a3039474 --- /dev/null +++ b/src/tests/__snapshots__/index.test.js.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`smoke test 1`] = ` +
+ +
+
+`; diff --git a/src/tests/index.test.js b/src/tests/index.test.js index 61b818ae..fa16ca1a 100644 --- a/src/tests/index.test.js +++ b/src/tests/index.test.js @@ -1,3 +1,61 @@ +import React from 'react'; +import PlacesAutocomplete from '../index'; +import renderer from 'react-test-renderer'; + +// TODO: Move this setup code to a separate file +/*** Mock Google Maps JavaScript API ***/ +const google = { + maps: { + places: { + AutocompleteService: () => {}, + PlacesServiceStatus: { + OK: 'OK', + }, + }, + }, +}; +global.window.google = google; + test('smoke test', () => { + console.log(typeof global.window !== "undefined" ? "global.window is defined" : "No window"); + console.log(global.window.google); expect(true).toBe(true); +}) + +test('smoke test', () => { + let state = { + address: '', + }; + const onChangeFunc = (newAddress) => { + state = { address: newAddress }; // reassian new object to state + } + + const component = renderer.create( + + {({ getInputProps, suggestions, getSuggestionItemProps }) => ( +
+ +
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.description} +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+ )} +
+ ); + + let tree = component.toJSON(); + expect(tree).toMatchSnapshot(); }); diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js index 00008fcc..487b36ba 100644 --- a/src/tests/testHelper.js +++ b/src/tests/testHelper.js @@ -1,25 +1,12 @@ -// import chai, { expect } from 'chai'; -// import chaiEnzyme from 'chai-enzyme'; -// import jsdom from 'jsdom'; -// -// /*** Set up test environment to run in a browser-like environment ***/ -// global.document = jsdom.jsdom(''); -// global.window = global.document.defaultView; -// -// /*** Mock Google Maps JavaScript API ***/ -// const google = { -// maps: { -// places: { -// AutocompleteService: () => {}, -// PlacesServiceStatus: { -// OK: 'OK', -// }, -// }, -// }, -// }; -// global.google = google; -// global.window.google = google; -// -// chai.use(chaiEnzyme()); -// -// export { expect }; +/*** Mock Google Maps JavaScript API ***/ +const google = { + maps: { + places: { + AutocompleteService: () => {}, + PlacesServiceStatus: { + OK: 'OK', + }, + }, + }, +}; +global.window.google = google; From de46915901c7dd4a8739deeb8c61a7ad491afba3 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 25 Mar 2018 10:54:54 -0700 Subject: [PATCH 115/165] Restructure tests folder --- demo/tests/index.spec.js | 3 --- ...est.js.snap => initialRender.test.js.snap} | 2 +- src/tests/helpers/setup.js | 20 ++++++++++++++ .../{index.test.js => initialRender.test.js} | 27 +++++-------------- src/tests/setup.js | 24 ----------------- src/tests/testHelper.js | 12 --------- 6 files changed, 27 insertions(+), 61 deletions(-) delete mode 100644 demo/tests/index.spec.js rename src/tests/__snapshots__/{index.test.js.snap => initialRender.test.js.snap} (92%) create mode 100644 src/tests/helpers/setup.js rename src/tests/{index.test.js => initialRender.test.js} (68%) delete mode 100644 src/tests/setup.js delete mode 100644 src/tests/testHelper.js diff --git a/demo/tests/index.spec.js b/demo/tests/index.spec.js deleted file mode 100644 index 61b818ae..00000000 --- a/demo/tests/index.spec.js +++ /dev/null @@ -1,3 +0,0 @@ -test('smoke test', () => { - expect(true).toBe(true); -}); diff --git a/src/tests/__snapshots__/index.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap similarity index 92% rename from src/tests/__snapshots__/index.test.js.snap rename to src/tests/__snapshots__/initialRender.test.js.snap index a3039474..3cde7a71 100644 --- a/src/tests/__snapshots__/index.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`smoke test 1`] = ` +exports[`initial render 1`] = `
{ + /*** Mock Google Maps JavaScript API ***/ + const google = { + maps: { + places: { + AutocompleteService: () => {}, + PlacesServiceStatus: { + INVALID_REQUEST: 'INVALID_REQUEST', + NOT_FOUND: 'NOT_FOUND', + OK: 'OK', + OVER_QUERY_LIMIT: 'OVER_QUERY_LIMIT', + REQUEST_DENIED: 'REQUEST_DENIED', + UNKNOWN_ERROR: 'UNKNOWN_ERROR', + ZERO_RESULTS: 'ZERO_RESULTS', + }, + }, + }, + }; + global.window.google = google; +}; diff --git a/src/tests/index.test.js b/src/tests/initialRender.test.js similarity index 68% rename from src/tests/index.test.js rename to src/tests/initialRender.test.js index fa16ca1a..71164f0c 100644 --- a/src/tests/index.test.js +++ b/src/tests/initialRender.test.js @@ -1,28 +1,13 @@ import React from 'react'; -import PlacesAutocomplete from '../index'; import renderer from 'react-test-renderer'; +import PlacesAutocomplete from '../index'; +import { setupGoogleMock } from './helpers/setup'; -// TODO: Move this setup code to a separate file -/*** Mock Google Maps JavaScript API ***/ -const google = { - maps: { - places: { - AutocompleteService: () => {}, - PlacesServiceStatus: { - OK: 'OK', - }, - }, - }, -}; -global.window.google = google; - -test('smoke test', () => { - console.log(typeof global.window !== "undefined" ? "global.window is defined" : "No window"); - console.log(global.window.google); - expect(true).toBe(true); -}) +beforeAll(() => { + setupGoogleMock(); +}); -test('smoke test', () => { +test('initial render', () => { let state = { address: '', }; diff --git a/src/tests/setup.js b/src/tests/setup.js deleted file mode 100644 index 291e9e9e..00000000 --- a/src/tests/setup.js +++ /dev/null @@ -1,24 +0,0 @@ -// // This file does the following: -// // 1. Sets the environment to 'production' so that -// // dev-specific babel config in .babelrc doesn't run. -// // 2. Disables Webpack-specific features that Mocha doesn't understand. -// // 3. Registers babel for transpiling our code for testing. -// -// // This assures the .babelrc dev config doesn't apply for tests. -// process.env.NODE_ENV = 'production'; -// -// // Disable webpack-specific features for tests since -// // Mocha doesn't know what to do with them. -// require.extensions['.css'] = function() { -// return null; -// }; -// require.extensions['.png'] = function() { -// return null; -// }; -// require.extensions['.jpg'] = function() { -// return null; -// }; -// -// // Register babel so that it will transpile ES6 to ES5 -// // before our tests run. -// require('babel-register')(); diff --git a/src/tests/testHelper.js b/src/tests/testHelper.js deleted file mode 100644 index 487b36ba..00000000 --- a/src/tests/testHelper.js +++ /dev/null @@ -1,12 +0,0 @@ -/*** Mock Google Maps JavaScript API ***/ -const google = { - maps: { - places: { - AutocompleteService: () => {}, - PlacesServiceStatus: { - OK: 'OK', - }, - }, - }, -}; -global.window.google = google; From 81ec6c520b8802197a5831fb3a9558778f2a833f Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 25 Mar 2018 11:07:34 -0700 Subject: [PATCH 116/165] Update initial render test --- .eslintignore | 3 +- .eslintrc.json | 2 +- .prettierignore | 5 ++ .../__snapshots__/initialRender.test.js.snap | 22 ++++++++ src/tests/initialRender.test.js | 53 ++++++++++++++++--- 5 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 .prettierignore diff --git a/.eslintignore b/.eslintignore index 1b780ffb..c41af1cc 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ -dist node_modules +dist/ +demo/dist/ **/*.min.js diff --git a/.eslintrc.json b/.eslintrc.json index 594486b7..ea3d2fd7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,7 @@ "browser": true, "es6": true, "node": true, - "mocha": true + "jest": true }, "extends": [ "eslint:recommended", diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..e4bdd77e --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +demo/dist/ +package-lock.json +package.json diff --git a/src/tests/__snapshots__/initialRender.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap index 3cde7a71..e41647d1 100644 --- a/src/tests/__snapshots__/initialRender.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -19,3 +19,25 @@ exports[`initial render 1`] = `
`; + +exports[`initial render with options to props-getter 1`] = ` +
+ +
+
+`; diff --git a/src/tests/initialRender.test.js b/src/tests/initialRender.test.js index 71164f0c..36c5c2ef 100644 --- a/src/tests/initialRender.test.js +++ b/src/tests/initialRender.test.js @@ -11,24 +11,61 @@ test('initial render', () => { let state = { address: '', }; - const onChangeFunc = (newAddress) => { + const onChangeFunc = newAddress => { state = { address: newAddress }; // reassian new object to state - } + }; const component = renderer.create( - + {({ getInputProps, suggestions, getSuggestionItemProps }) => (
+
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.description} +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+ )} +
+ ); + + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); +}); + +test('initial render with options to props-getter', () => { + let state = { + address: '', + }; + const onChangeFunc = newAddress => { + state = { address: newAddress }; // reassian new object to state + }; + + const component = renderer.create( + + {({ getInputProps, suggestions, getSuggestionItemProps }) => ( +
+
{suggestions.map( suggestion => ( /* eslint-disable react/jsx-key */
{suggestion.description}
@@ -41,6 +78,6 @@ test('initial render', () => { ); - let tree = component.toJSON(); + const tree = component.toJSON(); expect(tree).toMatchSnapshot(); }); From ab1f34a190fe10eebba2519c854cd71a03002649 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 25 Mar 2018 16:20:08 -0700 Subject: [PATCH 117/165] Add children prop test --- src/tests/childrenProp.test.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/tests/childrenProp.test.js diff --git a/src/tests/childrenProp.test.js b/src/tests/childrenProp.test.js new file mode 100644 index 00000000..8feaba4c --- /dev/null +++ b/src/tests/childrenProp.test.js @@ -0,0 +1,20 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import PlacesAutocomplete from '../index'; +import { setupGoogleMock } from './helpers/setup'; + +beforeAll(() => { + setupGoogleMock(); +}); + +test('children prop gets called once on initial render', () => { + const childrenProp = jest.fn().mockReturnValue(null); + + renderer.create( + {}}> + {childrenProp} + + ); + + expect(childrenProp.mock.calls.length).toBe(1); +}); From 1e179efb799e154b8bf32e9c046f818a81f2af83 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 25 Mar 2018 16:40:09 -0700 Subject: [PATCH 118/165] Add test for helper functions --- src/tests/helpers.test.js | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/tests/helpers.test.js diff --git a/src/tests/helpers.test.js b/src/tests/helpers.test.js new file mode 100644 index 00000000..ddfe44e1 --- /dev/null +++ b/src/tests/helpers.test.js @@ -0,0 +1,71 @@ +import { compose, pick } from '../helpers'; + +describe('pick', () => { + it('picks properties from object', () => { + const object = { one: 1, two: 2, three: 3 }; + const result = pick(object, 'one', 'three'); + expect(result).toEqual({ one: 1, three: 3 }); + }); + + it('picks only properties with value', () => { + const object = { one: 1, two: 2, three: 3 }; + const result = pick(object, 'one', 'four'); + expect(result).toEqual({ one: 1 }); + }); + + it('does not mutate the original object', () => { + const object = { one: 1, two: 2, three: 3 }; + pick(object, 'one', 'three'); + expect(object).toEqual({ one: 1, two: 2, three: 3 }); + }); + + it('works for function properties', () => { + const clickHandler = () => { + alert('clicked'); + }; + const mouseEnterHandler = () => { + alert('mouseenter'); + }; + const mouseLeaveHandler = () => { + alert('mouseleave'); + }; + const object = { + onClick: clickHandler, + onMouseEnter: mouseEnterHandler, + onMouseLeave: mouseLeaveHandler, + }; + const result = pick(object, 'onClick'); + expect(result).toEqual({ + onClick: clickHandler, + }); + }); +}); + +describe('compose', () => { + it('returns composed function', () => { + const func1 = jest.fn(); + const func2 = jest.fn(); + const composedFunc = compose(func1, func2); + composedFunc('one'); + + expect(func1.mock.calls.length).toBe(1); + expect(func2.mock.calls.length).toBe(1); + expect(func1).toBeCalledWith('one'); + expect(func2).toBeCalledWith('one'); + }); + + it('with multiple functions and arguments', () => { + const func1 = jest.fn(); + const func2 = jest.fn(); + const func3 = jest.fn(); + const composedFunc = compose(func1, func2, func3); + composedFunc('one', 'two'); + + expect(func1.mock.calls.length).toBe(1); + expect(func2.mock.calls.length).toBe(1); + expect(func3.mock.calls.length).toBe(1); + expect(func1).toBeCalledWith('one', 'two'); + expect(func2).toBeCalledWith('one', 'two'); + expect(func3).toBeCalledWith('one', 'two'); + }); +}); From 5d5e45bf09717c255af1017ab6cdefde472f6e1c Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 07:34:03 -0700 Subject: [PATCH 119/165] Add test for util functions --- demo/components/SearchBar.js | 13 +- package.json | 2 +- src/tests/__snapshots__/utils.test.js.snap | 133 +++++++++++++++++++++ src/tests/helpers/googlePayloads.js | 47 ++++++++ src/tests/helpers/setup.js | 40 +++++++ src/tests/utils.test.js | 34 ++++++ 6 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 src/tests/__snapshots__/utils.test.js.snap create mode 100644 src/tests/helpers/googlePayloads.js create mode 100644 src/tests/utils.test.js diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 751ae844..1580b160 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,5 +1,5 @@ import React from 'react'; -import PlacesAutocomplete from '../../src'; +import PlacesAutocomplete, { geocodeByAddress } from '../../src'; class SearchBar extends React.Component { constructor(props) { @@ -11,7 +11,16 @@ class SearchBar extends React.Component { } handleSelect = selected => { - console.log('selected', selected); // eslint-disable-line no-console + /* eslint-disable no-console */ + console.log('selected', selected); + geocodeByAddress(selected) + .then(res => + console.log('res', JSON.stringify(res)) + ) + .catch(error => { + console.log('error', error); + }); + /* eslint-enable no-console */ }; render() { diff --git a/package.json b/package.json index ef767b01..18a0d206 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,9 @@ "main": "dist/index.js", "scripts": { "commit": "git-cz", - "watch:test": "npm t -- -w", "test": "jest", "test:update": "jest --updateSnapshot", + "test:watch": "jest --watch", "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:*", "build:main": "babel --copy-files --out-dir dist --ignore *.spec.js src", diff --git a/src/tests/__snapshots__/utils.test.js.snap b/src/tests/__snapshots__/utils.test.js.snap new file mode 100644 index 00000000..1b954dda --- /dev/null +++ b/src/tests/__snapshots__/utils.test.js.snap @@ -0,0 +1,133 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`geocodeByAddress geocodes valid address 1`] = ` +Array [ + Object { + "address_components": Array [ + Object { + "long_name": "San Francisco", + "short_name": "SF", + "types": Array [ + "locality", + "political", + ], + }, + Object { + "long_name": "San Francisco County", + "short_name": "San Francisco County", + "types": Array [ + "administrative_area_level_2", + "political", + ], + }, + Object { + "long_name": "California", + "short_name": "CA", + "types": Array [ + "administrative_area_level_1", + "political", + ], + }, + Object { + "long_name": "United States", + "short_name": "US", + "types": Array [ + "country", + "political", + ], + }, + ], + "formatted_address": "San Francisco, CA, USA", + "geometry": Object { + "bounds": Object { + "east": -122.28178000000003, + "north": 37.9298239, + "south": 37.6398299, + "west": -123.17382499999997, + }, + "location": Object { + "lat": 37.7749295, + "lng": -122.41941550000001, + }, + "location_type": "APPROXIMATE", + "viewport": Object { + "east": -122.34820000000002, + "north": 37.812, + "south": 37.70339999999999, + "west": -122.52699999999999, + }, + }, + "place_id": "ChIJIQBpAG2ahYAR_6128GcTUEo", + "types": Array [ + "locality", + "political", + ], + }, +] +`; + +exports[`geocodeByPlaceId geocode valid placeID 1`] = ` +Array [ + Object { + "address_components": Array [ + Object { + "long_name": "San Francisco", + "short_name": "SF", + "types": Array [ + "locality", + "political", + ], + }, + Object { + "long_name": "San Francisco County", + "short_name": "San Francisco County", + "types": Array [ + "administrative_area_level_2", + "political", + ], + }, + Object { + "long_name": "California", + "short_name": "CA", + "types": Array [ + "administrative_area_level_1", + "political", + ], + }, + Object { + "long_name": "United States", + "short_name": "US", + "types": Array [ + "country", + "political", + ], + }, + ], + "formatted_address": "San Francisco, CA, USA", + "geometry": Object { + "bounds": Object { + "east": -122.28178000000003, + "north": 37.9298239, + "south": 37.6398299, + "west": -123.17382499999997, + }, + "location": Object { + "lat": 37.7749295, + "lng": -122.41941550000001, + }, + "location_type": "APPROXIMATE", + "viewport": Object { + "east": -122.34820000000002, + "north": 37.812, + "south": 37.70339999999999, + "west": -122.52699999999999, + }, + }, + "place_id": "ChIJIQBpAG2ahYAR_6128GcTUEo", + "types": Array [ + "locality", + "political", + ], + }, +] +`; diff --git a/src/tests/helpers/googlePayloads.js b/src/tests/helpers/googlePayloads.js new file mode 100644 index 00000000..12a26868 --- /dev/null +++ b/src/tests/helpers/googlePayloads.js @@ -0,0 +1,47 @@ +export const GEOCODE_RESULT = { + 'San Francisco': [ + { + address_components: [ + { + long_name: 'San Francisco', + short_name: 'SF', + types: ['locality', 'political'], + }, + { + long_name: 'San Francisco County', + short_name: 'San Francisco County', + types: ['administrative_area_level_2', 'political'], + }, + { + long_name: 'California', + short_name: 'CA', + types: ['administrative_area_level_1', 'political'], + }, + { + long_name: 'United States', + short_name: 'US', + types: ['country', 'political'], + }, + ], + formatted_address: 'San Francisco, CA, USA', + geometry: { + bounds: { + south: 37.6398299, + west: -123.17382499999997, + north: 37.9298239, + east: -122.28178000000003, + }, + location: { lat: 37.7749295, lng: -122.41941550000001 }, + location_type: 'APPROXIMATE', + viewport: { + south: 37.70339999999999, + west: -122.52699999999999, + north: 37.812, + east: -122.34820000000002, + }, + }, + place_id: 'ChIJIQBpAG2ahYAR_6128GcTUEo', + types: ['locality', 'political'], + }, + ], +}; diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index ebb489bb..9e8b34b4 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -1,3 +1,33 @@ +import { GEOCODE_RESULT } from './googlePayloads'; + +class GeocoderMock { + geocode({ address, placeId }, callback) { + if (address) { + this._geocodeAddress(address, callback); + } else if (placeId) { + this._geocodePlaceID(placeId, callback); + } else { + callback({}, 'ZERO_RESULTS'); + } + } + + _geocodeAddress(address, callback) { + if (address.startsWith('San Francisco')) { + callback(GEOCODE_RESULT['San Francisco'], 'OK'); + } else { + callback([], 'ZERO_RESULTS'); + } + } + + _geocodePlaceID(placeId, callback) { + if (placeId === 'ChIJIQBpAG2ahYAR_6128GcTUEo') { + callback(GEOCODE_RESULT['San Francisco'], 'OK'); + } else { + callback([], 'ZERO_RESULTS'); + } + } +} + export const setupGoogleMock = () => { /*** Mock Google Maps JavaScript API ***/ const google = { @@ -14,6 +44,16 @@ export const setupGoogleMock = () => { ZERO_RESULTS: 'ZERO_RESULTS', }, }, + Geocoder: GeocoderMock, + GeocoderStatus: { + ERROR: 'ERROR', + INVALID_REQUEST: 'INVALID_REQUEST', + OK: 'OK', + OVER_QUERY_LIMIT: 'OVER_QUERY_LIMIT', + REQUEST_DENIED: 'REQUEST_DENIED', + UNKNOWN_ERROR: 'UNKNOWN_ERROR', + ZERO_RESULTS: 'ZERO_RESULTS', + }, }, }; global.window.google = google; diff --git a/src/tests/utils.test.js b/src/tests/utils.test.js new file mode 100644 index 00000000..389bafaf --- /dev/null +++ b/src/tests/utils.test.js @@ -0,0 +1,34 @@ +import { geocodeByAddress, geocodeByPlaceId } from '../utils'; +import { setupGoogleMock } from './helpers/setup'; + +beforeAll(() => { + setupGoogleMock(); +}); + +describe('geocodeByAddress', () => { + it('geocodes valid address', () => { + expect.assertions(1); + return geocodeByAddress('San Francisco, CA').then(results => { + expect(results).toMatchSnapshot(); + }); + }); + + it('rejects invalid address', () => { + expect.assertions(1); + return geocodeByAddress('someinvalidaddress').catch(error => { + expect(error).toBeDefined(); + }); + }); +}); + +describe('geocodeByPlaceId', () => { + it('geocode valid placeID', () => { + expect.assertions(1); + /* placeID of San Francisco */ + return geocodeByPlaceId('ChIJIQBpAG2ahYAR_6128GcTUEo').then(results => { + expect(results).toMatchSnapshot(); + }); + }); +}); + +/* TODO: test getLatLng */ From 265081378e3f1b436e5ccdc6d5e5271ccb28f8cb Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 22:21:20 -0700 Subject: [PATCH 120/165] Add test coverage script --- .eslintignore | 1 + .gitignore | 4 ++-- package.json | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.eslintignore b/.eslintignore index c41af1cc..1a580ec3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ node_modules dist/ demo/dist/ **/*.min.js +coverage/ diff --git a/.gitignore b/.gitignore index ecb97abe..abd5eda7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ logs *.log node_modules -coverage -dist +coverage/ +dist/ diff --git a/package.json b/package.json index 18a0d206..01439bc6 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "test": "jest", "test:update": "jest --updateSnapshot", "test:watch": "jest --watch", + "test:coverage": "jest --coverage", "prebuild": "rimraf dist", "build": "npm-run-all --parallel build:*", "build:main": "babel --copy-files --out-dir dist --ignore *.spec.js src", @@ -113,5 +114,10 @@ }, "peerDependencies": { "react": ">=0.14.7" + }, + "jest": { + "collectCoverageFrom": [ + "src/*.js" + ] } } From 5c3e801c14c28fe1bcb0b8387f7577ecf1155077 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 22:36:33 -0700 Subject: [PATCH 121/165] Install enzyme as dev dependency --- package-lock.json | 552 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 + 2 files changed, 555 insertions(+) diff --git a/package-lock.json b/package-lock.json index ceea0eec..4da2e45b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -245,6 +245,12 @@ "github-url-from-git": "1.5.0" } }, + "@types/node": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.0.tgz", + "integrity": "sha512-h3YZbOq2+ZoDFI1z8Zx0Ck/xRWkOESVaLdgLdd/c25mMQ1Y2CAkILu9ny5A15S5f32gGcQdaUIZ2jzYr8D7IFg==", + "dev": true + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -5105,6 +5111,12 @@ "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", "dev": true }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -5382,6 +5394,31 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", + "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-serializer": "0.1.0", + "entities": "1.1.1", + "htmlparser2": "3.9.2", + "lodash": "4.17.4", + "parse5": "3.0.3" + }, + "dependencies": { + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "9.6.0" + } + } + } + }, "chokidar": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz", @@ -6071,6 +6108,24 @@ "sha.js": "2.2.6" } }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, "csso": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", @@ -6736,6 +6791,12 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "dev": true + }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -6745,12 +6806,36 @@ "esutils": "2.0.2" } }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, "domain-browser": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", "dev": true }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", @@ -6760,6 +6845,25 @@ "webidl-conversions": "4.0.2" } }, + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, "download": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", @@ -7059,6 +7163,127 @@ } } }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "enzyme": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.3.0.tgz", + "integrity": "sha512-l8csyPyLmtxskTz6pX9W8eDOyH1ckEtDttXk/vlFWCjv00SkjTjtoUrogqp4yEvMyneU9dUJoOLnqFoiHb8IHA==", + "dev": true, + "requires": { + "cheerio": "1.0.0-rc.2", + "function.prototype.name": "1.1.0", + "has": "1.0.1", + "is-boolean-object": "1.0.0", + "is-callable": "1.1.3", + "is-number-object": "1.0.3", + "is-string": "1.0.4", + "is-subset": "0.1.1", + "lodash": "4.17.4", + "object-inspect": "1.5.0", + "object-is": "1.0.1", + "object.assign": "4.1.0", + "object.entries": "1.0.4", + "object.values": "1.0.4", + "raf": "3.4.0", + "rst-selector-parser": "2.2.3" + } + }, + "enzyme-adapter-react-16": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.1.1.tgz", + "integrity": "sha512-kC8pAtU2Jk3OJ0EG8Y2813dg9Ol0TXi7UNxHzHiWs30Jo/hj7alc//G1YpKUsPP1oKl9X+Lkx+WlGJpPYA+nvw==", + "dev": true, + "requires": { + "enzyme-adapter-utils": "1.3.0", + "lodash": "4.17.4", + "object.assign": "4.1.0", + "object.values": "1.0.4", + "prop-types": "15.6.1", + "react-reconciler": "0.7.0", + "react-test-renderer": "16.2.0" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } + } + } + }, + "enzyme-adapter-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.3.0.tgz", + "integrity": "sha512-vVXSt6uDv230DIv+ebCG66T1Pm36Kv+m74L1TrF4kaE7e1V7Q/LcxO0QRkajk5cA6R3uu9wJf5h13wOTezTbjA==", + "dev": true, + "requires": { + "lodash": "4.17.4", + "object.assign": "4.1.0", + "prop-types": "15.6.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } + } + } + }, + "enzyme-to-json": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.3.tgz", + "integrity": "sha1-7eRZOPswnNh+vUOG9gx1RSVRWgc=", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, "errno": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", @@ -9608,6 +9833,25 @@ "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", "dev": true }, + "function.prototype.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", + "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "is-callable": "1.1.3" + }, + "dependencies": { + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + } + } + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -10340,6 +10584,12 @@ "sparkles": "1.0.0" } }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -10461,6 +10711,20 @@ "whatwg-encoding": "1.0.3" } }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.5.1", + "entities": "1.1.1", + "inherits": "2.0.1", + "readable-stream": "2.1.4" + } + }, "http-errors": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", @@ -10887,6 +11151,12 @@ "binary-extensions": "1.8.0" } }, + "is-boolean-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.0.tgz", + "integrity": "sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=", + "dev": true + }, "is-buffer": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz", @@ -11058,6 +11328,12 @@ "kind-of": "3.0.3" } }, + "is-number-object": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.3.tgz", + "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -11181,6 +11457,18 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz", + "integrity": "sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, "is-svg": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", @@ -13070,6 +13358,12 @@ "lodash._root": "3.0.1" } }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, "lodash.isarguments": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.8.tgz", @@ -13559,6 +13853,26 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nearley": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.13.0.tgz", + "integrity": "sha512-ioYYogSaZhFlCpRizQgY3UT3G1qFXmHGY/5ozoFE3dMfiCRAeJfh+IPE3/eh9gCZvqLhPCWb4bLt7Bqzo+1mLQ==", + "dev": true, + "requires": { + "nomnom": "1.6.2", + "railroad-diagrams": "1.0.0", + "randexp": "0.4.6", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -13667,6 +13981,24 @@ "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", "dev": true }, + "nomnom": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", + "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", + "dev": true, + "requires": { + "colors": "0.5.1", + "underscore": "1.4.4" + }, + "dependencies": { + "colors": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", + "dev": true + } + } + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -13991,6 +14323,15 @@ } } }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, "number-is-nan": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", @@ -15676,6 +16017,18 @@ } } }, + "object-inspect": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.5.0.tgz", + "integrity": "sha512-UmOFbHbwvv+XHj7BerrhVq+knjceBdkvU5AriwLMvhv2qi+e7DJzxfBeFpILEjVzCp+xA+W/pIf06RGPWlZNfw==", + "dev": true + }, + "object-is": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", + "dev": true + }, "object-keys": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", @@ -15699,6 +16052,70 @@ } } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" + }, + "dependencies": { + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + } + } + }, + "object.entries": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", + "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.11.0", + "function-bind": "1.1.0", + "has": "1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", + "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + }, + "dependencies": { + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + } + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + } + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -15736,6 +16153,50 @@ } } }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.11.0", + "function-bind": "1.1.0", + "has": "1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", + "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + }, + "dependencies": { + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + } + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + } + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -16449,6 +16910,39 @@ "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", "dev": true }, + "raf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", + "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", + "dev": true, + "requires": { + "performance-now": "2.1.0" + }, + "dependencies": { + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + } + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "dev": true + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "requires": { + "discontinuous-range": "1.0.0", + "ret": "0.1.15" + } + }, "randomatic": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz", @@ -16561,6 +17055,48 @@ } } }, + "react-reconciler": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.7.0.tgz", + "integrity": "sha512-50JwZ3yNyMS8fchN+jjWEJOH3Oze7UmhxeoJLn2j6f3NjpfCRbcmih83XTWmzqtar/ivd5f7tvQhvvhism2fgg==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.2.0", + "object-assign": "4.1.1", + "prop-types": "15.6.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "prop-types": { + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", + "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", + "dev": true, + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + }, + "dependencies": { + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + } + } + } + } + }, "react-test-renderer": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.2.0.tgz", @@ -17192,6 +17728,16 @@ "integrity": "sha1-K/GYveFnys+lHAqSjoS2i74XH84=", "dev": true }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", + "dev": true, + "requires": { + "lodash.flattendeep": "4.4.0", + "nearley": "2.13.0" + } + }, "run-async": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.2.0.tgz", @@ -19433,6 +19979,12 @@ "integrity": "sha1-Wj2yPvXb1VuB/ODsmirG/M3ruB4=", "dev": true }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", diff --git a/package.json b/package.json index 01439bc6..fc7162fd 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,9 @@ "commitizen": "2.8.2", "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", + "enzyme": "3.3.0", + "enzyme-adapter-react-16": "1.1.1", + "enzyme-to-json": "3.3.3", "eslint": "4.18.2", "eslint-config-prettier": "2.9.0", "eslint-plugin-prettier": "2.6.0", From 0318a7b17269ecf7fedafbf206299fc59c793760 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 22:44:02 -0700 Subject: [PATCH 122/165] Update jest configuration --- package.json | 6 +++--- src/tests/helpers/jestSetup.js | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/tests/helpers/jestSetup.js diff --git a/package.json b/package.json index fc7162fd..f354a3e9 100644 --- a/package.json +++ b/package.json @@ -119,8 +119,8 @@ "react": ">=0.14.7" }, "jest": { - "collectCoverageFrom": [ - "src/*.js" - ] + "setupFiles": ["./src/tests/helpers/jestSetup.js"], + "snapshotSerializers": ["enzyme-to-json/serializer"], + "collectCoverageFrom": ["src/*.js"] } } diff --git a/src/tests/helpers/jestSetup.js b/src/tests/helpers/jestSetup.js new file mode 100644 index 00000000..d3059bf9 --- /dev/null +++ b/src/tests/helpers/jestSetup.js @@ -0,0 +1,8 @@ +import Enzyme, { shallow, render, mount } from 'enzyme'; +import Adapter from 'enzyme-adapter-react-16'; +// React 16 Enzyme adapter +Enzyme.configure({ adapter: new Adapter() }); +// Make Enzyme functions available in all test files without importing +global.shallow = shallow; +global.render = render; +global.mount = mount; From c1d0bd172f8fca9caeefb460403c8ec9a31e10a6 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 22:51:00 -0700 Subject: [PATCH 123/165] Update test snapshots with enzyme-to-json serializer --- .../__snapshots__/initialRender.test.js.snap | 92 +++++++++++-------- src/tests/initialRender.test.js | 12 +-- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/tests/__snapshots__/initialRender.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap index e41647d1..3a52398f 100644 --- a/src/tests/__snapshots__/initialRender.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -1,43 +1,63 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`initial render 1`] = ` -
- -
-
+ +
+ +
+
+ `; exports[`initial render with options to props-getter 1`] = ` -
- -
-
+ +
+ +
+
+ `; diff --git a/src/tests/initialRender.test.js b/src/tests/initialRender.test.js index 36c5c2ef..a60ec01e 100644 --- a/src/tests/initialRender.test.js +++ b/src/tests/initialRender.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import renderer from 'react-test-renderer'; +import { mount } from 'enzyme'; import PlacesAutocomplete from '../index'; import { setupGoogleMock } from './helpers/setup'; @@ -15,7 +15,7 @@ test('initial render', () => { state = { address: newAddress }; // reassian new object to state }; - const component = renderer.create( + const component = mount( {({ getInputProps, suggestions, getSuggestionItemProps }) => (
@@ -36,8 +36,7 @@ test('initial render', () => { ); - const tree = component.toJSON(); - expect(tree).toMatchSnapshot(); + expect(component).toMatchSnapshot(); }); test('initial render with options to props-getter', () => { @@ -48,7 +47,7 @@ test('initial render with options to props-getter', () => { state = { address: newAddress }; // reassian new object to state }; - const component = renderer.create( + const component = mount( {({ getInputProps, suggestions, getSuggestionItemProps }) => (
@@ -78,6 +77,5 @@ test('initial render with options to props-getter', () => { ); - const tree = component.toJSON(); - expect(tree).toMatchSnapshot(); + expect(component).toMatchSnapshot(); }); From 422544550a0e3fd823ab442b0824cf4e3e3f8827 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 22:51:44 -0700 Subject: [PATCH 124/165] Remove globally defined functions in tests --- src/tests/helpers/jestSetup.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/tests/helpers/jestSetup.js b/src/tests/helpers/jestSetup.js index d3059bf9..5cc61361 100644 --- a/src/tests/helpers/jestSetup.js +++ b/src/tests/helpers/jestSetup.js @@ -1,8 +1,4 @@ -import Enzyme, { shallow, render, mount } from 'enzyme'; +import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; // React 16 Enzyme adapter Enzyme.configure({ adapter: new Adapter() }); -// Make Enzyme functions available in all test files without importing -global.shallow = shallow; -global.render = render; -global.mount = mount; From 6493b9eb16cbd68cb4ab86027acf75861b78f5c5 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 26 Mar 2018 23:17:40 -0700 Subject: [PATCH 125/165] Uninstall stale dev dependencies --- package-lock.json | 1603 --------------------------------------------- package.json | 14 +- 2 files changed, 9 insertions(+), 1608 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4da2e45b..d834c31b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14344,1609 +14344,6 @@ "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", "dev": true }, - "nyc": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-7.0.0.tgz", - "integrity": "sha1-GAmUHjmfLM/l4IjNj8R50TcomLA=", - "dev": true, - "requires": { - "append-transform": "0.4.0", - "arrify": "1.0.1", - "caching-transform": "1.0.1", - "convert-source-map": "1.2.0", - "default-require-extensions": "1.0.0", - "find-cache-dir": "0.1.1", - "find-up": "1.1.2", - "foreground-child": "1.5.3", - "glob": "7.0.5", - "istanbul-lib-coverage": "1.0.0-alpha.4", - "istanbul-lib-instrument": "1.1.0-alpha.2", - "istanbul-lib-report": "1.0.0-alpha.3", - "istanbul-lib-source-maps": "1.0.0-alpha.10", - "istanbul-reports": "1.0.0-alpha.7", - "md5-hex": "1.3.0", - "micromatch": "2.3.10", - "mkdirp": "0.5.1", - "pkg-up": "1.0.0", - "resolve-from": "2.0.0", - "rimraf": "2.5.3", - "signal-exit": "3.0.0", - "spawn-wrap": "1.2.3", - "test-exclude": "1.1.0", - "yargs": "4.7.1" - }, - "dependencies": { - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "3.0.3", - "longest": "1.0.1", - "repeat-string": "1.5.4" - } - }, - "amdefine": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz", - "integrity": "sha1-/RdHRwDLXMnCtwnwvp0jzjwZjDM=", - "dev": true - }, - "ansi-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", - "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "1.0.0" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.0.1" - } - }, - "arr-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz", - "integrity": "sha1-5f/lTUXhnzLyFukeuZyM6JK7YEs=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "babel-code-frame": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.11.0.tgz", - "integrity": "sha1-kHLdI1P7D4W2tX0sl/DRNNGIrtg=", - "dev": true, - "requires": { - "babel-runtime": "6.9.2", - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "2.0.0" - } - }, - "babel-generator": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.11.0.tgz", - "integrity": "sha1-jFpuOAOqzGxtp9ls112mzG4rMnU=", - "dev": true, - "requires": { - "babel-messages": "6.8.0", - "babel-runtime": "6.9.2", - "babel-types": "6.11.1", - "detect-indent": "3.0.1", - "lodash": "4.13.1", - "source-map": "0.5.6" - } - }, - "babel-messages": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.8.0.tgz", - "integrity": "sha1-v1BHNsqWfm1l7wrbWipflHyODrk=", - "dev": true, - "requires": { - "babel-runtime": "6.9.2" - } - }, - "babel-runtime": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.9.2.tgz", - "integrity": "sha1-1/45G8LMKbgIfB2bOYeJEun8/Vk=", - "dev": true, - "requires": { - "core-js": "2.4.0", - "regenerator-runtime": "0.9.5" - } - }, - "babel-template": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.9.0.tgz", - "integrity": "sha1-lwkPz2vBVoW08FvmXAqUOKp+I+M=", - "dev": true, - "requires": { - "babel-runtime": "6.9.2", - "babel-traverse": "6.10.4", - "babel-types": "6.11.1", - "babylon": "6.8.4", - "lodash": "4.13.1" - } - }, - "babel-traverse": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.10.4.tgz", - "integrity": "sha1-289B/x8y62FIWc6tSHEWDx8SDXg=", - "dev": true, - "requires": { - "babel-code-frame": "6.11.0", - "babel-messages": "6.8.0", - "babel-runtime": "6.9.2", - "babel-types": "6.11.1", - "babylon": "6.8.4", - "debug": "2.2.0", - "globals": "8.18.0", - "invariant": "2.2.1", - "lodash": "4.13.1" - } - }, - "babel-types": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.11.1.tgz", - "integrity": "sha1-o981W6uQ3c9mMYZAcXzywVTmZIo=", - "dev": true, - "requires": { - "babel-runtime": "6.9.2", - "babel-traverse": "6.10.4", - "esutils": "2.0.2", - "lodash": "4.13.1", - "to-fast-properties": "1.0.2" - } - }, - "babylon": { - "version": "6.8.4", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.8.4.tgz", - "integrity": "sha1-CXMGuNq66VFZIlzymz6lWRIFMYA=", - "dev": true, - "requires": { - "babel-runtime": "6.9.2" - } - }, - "balanced-match": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz", - "integrity": "sha1-GQU+LgdI6ts3nabAnUVc9eEDkzU=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.5.tgz", - "integrity": "sha1-9bStV04st8zB64Pm/nm47K33pSY=", - "dev": true, - "requires": { - "balanced-match": "0.4.1", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "caching-transform": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", - "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", - "dev": true, - "requires": { - "md5-hex": "1.3.0", - "mkdirp": "0.5.1", - "write-file-atomic": "1.1.4" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "code-point-at": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", - "integrity": "sha1-9psZLT99keOC5Lcb3bd4eGGasMY=", - "dev": true, - "requires": { - "number-is-nan": "1.0.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.2.0.tgz", - "integrity": "sha1-RMCMJQbxD7PKb9iI1aNETPjWpmk=", - "dev": true - }, - "core-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz", - "integrity": "sha1-30CKtG0Br/kcAcPnlxk11CLFT4E=", - "dev": true - }, - "cross-spawn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz", - "integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=", - "dev": true, - "requires": { - "lru-cache": "4.0.1", - "which": "1.2.10" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "requires": { - "strip-bom": "2.0.0" - } - }, - "detect-indent": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-3.0.1.tgz", - "integrity": "sha1-ncXl3bzu+DJXZLlFGwK8bVQIT3U=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "minimist": "1.2.0", - "repeating": "1.1.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "error-ex": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", - "integrity": "sha1-5ntD8+gsluo6WE/+4Ln8MyXYAtk=", - "dev": true, - "requires": { - "is-arrayish": "0.2.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "2.2.3" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "filename-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz", - "integrity": "sha1-mW4+gEebmLmJfxWopYs9CE6SZ3U=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.5", - "repeat-element": "1.1.2", - "repeat-string": "1.5.4" - } - }, - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, - "requires": { - "commondir": "1.0.1", - "mkdirp": "0.5.1", - "pkg-dir": "1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "for-in": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.5.tgz", - "integrity": "sha1-AHN04rbVxnQgoUeb23WgSHK3OMQ=", - "dev": true - }, - "for-own": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz", - "integrity": "sha1-AUm0GjkIjHUV9R6+HBOG1F+TUHI=", - "dev": true, - "requires": { - "for-in": "0.1.5" - } - }, - "foreground-child": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.3.tgz", - "integrity": "sha1-lN1qumcTiYZ96OV+mfHC7PsVwBo=", - "dev": true, - "requires": { - "cross-spawn": "4.0.0", - "signal-exit": "3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.5", - "inherits": "2.0.1", - "minimatch": "3.0.2", - "once": "1.3.3", - "path-is-absolute": "1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "globals": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", - "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", - "dev": true - }, - "graceful-fs": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", - "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", - "dev": true - }, - "handlebars": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.5.tgz", - "integrity": "sha1-ksbta7FkEQxQ1NjQ+93HCAbG+Oc=", - "dev": true, - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.7.0" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.0" - } - } - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "hosted-git-info": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz", - "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz", - "integrity": "sha1-2zIEzVqd4ubNiQuFxuL2a89PYgo=", - "dev": true, - "requires": { - "once": "1.3.3", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "invariant": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.1.tgz", - "integrity": "sha1-sJcBBUdmjH4zcCjr6Bbr42yKjVQ=", - "dev": true, - "requires": { - "loose-envify": "1.2.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.3.tgz", - "integrity": "sha1-24l/w/esotUN6UtsjCiWpHcWJ68=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-dotfile": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", - "integrity": "sha1-LBMjg/ORmfjtwmjKAbmwB9IFzE0=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-finite": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.1.tgz", - "integrity": "sha1-ZDhgPq6+J5OUj/SkJi7I2z1iWXs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.0" - } - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.0.3" - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", - "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", - "dev": true - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "istanbul-lib-coverage": { - "version": "1.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.0-alpha.4.tgz", - "integrity": "sha1-Ym9/2c+Am2479+1CqAn44LZK6XY=", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.1.0-alpha.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.1.0-alpha.2.tgz", - "integrity": "sha1-znzcbTrjX9S68QolwGtGHuzxqBU=", - "dev": true, - "requires": { - "babel-generator": "6.11.0", - "babel-template": "6.9.0", - "babel-traverse": "6.10.4", - "babel-types": "6.11.1", - "babylon": "6.8.4", - "istanbul-lib-coverage": "1.0.0-alpha.4" - } - }, - "istanbul-lib-report": { - "version": "1.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.0.0-alpha.3.tgz", - "integrity": "sha1-MtX27H8zyjpgIgnieLLm/xQ0mK8=", - "dev": true, - "requires": { - "async": "1.5.2", - "istanbul-lib-coverage": "1.0.0-alpha.4", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "rimraf": "2.5.3", - "supports-color": "3.1.2" - }, - "dependencies": { - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.0.0-alpha.10.tgz", - "integrity": "sha1-mxWlyLWdG5EBviy33VTHA9hq3vE=", - "dev": true, - "requires": { - "istanbul-lib-coverage": "1.0.0-alpha.4", - "mkdirp": "0.5.1", - "rimraf": "2.5.3", - "source-map": "0.5.6" - } - }, - "istanbul-reports": { - "version": "1.0.0-alpha.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.0.0-alpha.7.tgz", - "integrity": "sha1-XKML9EpIZmgbYoJRagigiykepsM=", - "dev": true, - "requires": { - "handlebars": "4.0.5" - } - }, - "js-tokens": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-2.0.0.tgz", - "integrity": "sha1-eZA/VWPud4zBFi5tzxoAJ8l/nLU=", - "dev": true - }, - "kind-of": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.3.tgz", - "integrity": "sha1-xhYIdH2BWwNiVW2zJ2Nip6OK3tM=", - "dev": true, - "requires": { - "is-buffer": "1.1.3" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.4", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "lodash": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", - "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=", - "dev": true - }, - "lodash.assign": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.0.9.tgz", - "integrity": "sha1-Cgcx2TWQ3dm6RYn61lqvbuCSF+M=", - "dev": true, - "requires": { - "lodash.keys": "4.0.7", - "lodash.rest": "4.0.3" - } - }, - "lodash.keys": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.0.7.tgz", - "integrity": "sha1-MOGzvZjlTWoGEZkYEmhba8R8tjs=", - "dev": true - }, - "lodash.rest": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/lodash.rest/-/lodash.rest-4.0.3.tgz", - "integrity": "sha1-TBwyxAAoCHJQ+r9w1C4BUVSPSMU=", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loose-envify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.2.0.tgz", - "integrity": "sha1-aaZarT3lQs9O4PT+dOjjPHCcyw8=", - "dev": true, - "requires": { - "js-tokens": "1.0.3" - }, - "dependencies": { - "js-tokens": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-1.0.3.tgz", - "integrity": "sha1-FOVutoyPGpLEPVn1AU7CncIPKuE=", - "dev": true - } - } - }, - "lru-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", - "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.0.0" - } - }, - "md5-hex": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", - "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", - "dev": true, - "requires": { - "md5-o-matic": "0.1.1" - } - }, - "md5-o-matic": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", - "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", - "dev": true - }, - "micromatch": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.10.tgz", - "integrity": "sha1-9Psxdb7sYnlae4wk1fdFw2gGYKs=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.0", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.0.3", - "normalize-path": "2.0.1", - "object.omit": "2.0.0", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" - } - }, - "minimatch": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", - "integrity": "sha1-DzmKcwDqRB6cNIyD2Yq4ydv5xAo=", - "dev": true, - "requires": { - "brace-expansion": "1.1.5" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "normalize-package-data": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.5.tgz", - "integrity": "sha1-jZJPFClg4Xd+f/4XBUNjHMfLAt8=", - "dev": true, - "requires": { - "hosted-git-info": "2.1.5", - "is-builtin-module": "1.0.0", - "semver": "5.2.0", - "validate-npm-package-license": "3.0.1" - } - }, - "normalize-path": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", - "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", - "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=", - "dev": true - }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true - }, - "object.omit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz", - "integrity": "sha1-hoWXMz1U5gZilAu0WGBd1q4S/pQ=", - "dev": true, - "requires": { - "for-own": "0.1.4", - "is-extendable": "0.1.1" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.3" - } - }, - "os-homedir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", - "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "1.0.0" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.2", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "1.3.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", - "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.4", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "pkg-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-1.1.3.tgz", - "integrity": "sha1-N45W1v0T6Iv7b0ol33qD+qvduls=", - "dev": true, - "requires": { - "find-up": "1.1.2", - "load-json-file": "1.1.0", - "object-assign": "4.1.0", - "symbol": "0.2.3" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "1.1.2" - } - }, - "pkg-up": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", - "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", - "dev": true, - "requires": { - "find-up": "1.1.2" - } - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "randomatic": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.5.tgz", - "integrity": "sha1-Xp718tVzxnvSuBJK6QtRVuRXhAs=", - "dev": true, - "requires": { - "is-number": "2.1.0", - "kind-of": "3.0.3" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.3.5", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "regenerator-runtime": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.9.5.tgz", - "integrity": "sha1-QD1tQKS9/5wzDdk5Lcuy2ai7ofw=", - "dev": true - }, - "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true, - "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz", - "integrity": "sha1-ZOwMkeD0tHX5DVtkNlHj5uW2wtU=", - "dev": true - }, - "repeating": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", - "integrity": "sha1-PUEUIYh3U3SU+X93+Xhfq4EPpKw=", - "dev": true, - "requires": { - "is-finite": "1.0.1" - } - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.3.tgz", - "integrity": "sha1-bl792kqi8DQX9rKldK7Cn0tlJwU=", - "dev": true, - "requires": { - "glob": "7.0.5" - } - }, - "semver": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.2.0.tgz", - "integrity": "sha1-KBmVuAwUSCCUFd28TPUMJpzvVcU=", - "dev": true - }, - "set-blocking": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-1.0.0.tgz", - "integrity": "sha1-zV5dk4BI3xrJLf6S4fFq3WVvXsU=", - "dev": true - }, - "signal-exit": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz", - "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g=", - "dev": true - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "spawn-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.2.3.tgz", - "integrity": "sha1-3300R/tKAZYZpB9o7mQqcY5gYuk=", - "dev": true, - "requires": { - "foreground-child": "1.5.3", - "mkdirp": "0.5.1", - "os-homedir": "1.0.1", - "rimraf": "2.5.3", - "signal-exit": "2.1.2", - "which": "1.2.10" - }, - "dependencies": { - "signal-exit": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-2.1.2.tgz", - "integrity": "sha1-N1h5sfkuvDszRIDQONxUam1VhWQ=", - "dev": true - } - } - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true, - "requires": { - "spdx-license-ids": "1.2.1" - } - }, - "spdx-exceptions": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-1.0.4.tgz", - "integrity": "sha1-IguEI5EZrpBFqJLbgag/TOFvgP0=", - "dev": true - }, - "spdx-expression-parse": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.2.tgz", - "integrity": "sha1-1SsUtelnB3FECvIlvLVjEirEUvY=", - "dev": true, - "requires": { - "spdx-exceptions": "1.0.4", - "spdx-license-ids": "1.2.1" - } - }, - "spdx-license-ids": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.1.tgz", - "integrity": "sha1-0H6hek0v2TUfnZTi/5zsdBgP6PM=", - "dev": true - }, - "string-width": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz", - "integrity": "sha1-ySEptvHX9SrPmvQkom44ZKBc6wo=", - "dev": true, - "requires": { - "code-point-at": "1.0.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "symbol": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/symbol/-/symbol-0.2.3.tgz", - "integrity": "sha1-O5hzuKkB5Hxu/iFSajrDcu8ou8c=", - "dev": true - }, - "test-exclude": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-1.1.0.tgz", - "integrity": "sha1-9d3XGJJ7Ev0C8nCgqpOc627qQVE=", - "dev": true, - "requires": { - "arrify": "1.0.1", - "lodash.assign": "4.0.9", - "micromatch": "2.3.10", - "read-pkg-up": "1.0.1", - "require-main-filename": "1.0.1" - } - }, - "to-fast-properties": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.2.tgz", - "integrity": "sha1-8/XAw7pymafvmUJ+RGMyV63kMyA=", - "dev": true - }, - "uglify-js": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.0.tgz", - "integrity": "sha1-8CHji6LKdAhg9b1caVwqgXNF8Ow=", - "dev": true, - "optional": true, - "requires": { - "async": "0.2.10", - "source-map": "0.5.6", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true, - "optional": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true, - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.2" - } - }, - "which": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz", - "integrity": "sha1-kc2b0HUTIkEbZZtA8FSyHelXqy0=", - "dev": true, - "requires": { - "isexe": "1.1.2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wrap-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.0.0.tgz", - "integrity": "sha1-fTD4+HP5pbvDpk2ryNF34HGuQm8=", - "dev": true, - "requires": { - "string-width": "1.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.1.4.tgz", - "integrity": "sha1-sfUtwujcDjywTRh6JfdYo4qQyjs=", - "dev": true, - "requires": { - "graceful-fs": "4.1.4", - "imurmurhash": "0.1.4", - "slide": "1.1.6" - } - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", - "integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ=", - "dev": true - }, - "yargs": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.7.1.tgz", - "integrity": "sha1-5gQyZYozh/8mnAKOrN5KUS5Djf8=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "lodash.assign": "4.0.9", - "os-locale": "1.4.0", - "pkg-conf": "1.1.3", - "read-pkg-up": "1.0.1", - "require-main-filename": "1.0.1", - "set-blocking": "1.0.0", - "string-width": "1.0.1", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "1.0.1", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.0.0" - } - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.0.tgz", - "integrity": "sha1-HzZ9ycbPpWYLaXEjDzsnf8Xjrco=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "lodash.assign": "4.0.9" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - } - } - }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", diff --git a/package.json b/package.json index f354a3e9..9618447d 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "babel-preset-env": "1.6.1", "babel-preset-react": "^6.23.1", "babel-preset-stage-0": "^6.22.0", - "babel-register": "^6.23.0", "commitizen": "2.8.2", "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", @@ -86,7 +85,6 @@ "jest": "22.4.3", "json-loader": "0.5.4", "npm-run-all": "2.3.0", - "nyc": "7.0.0", "prettier": "1.10.2", "react": "^16.2.0", "react-dom": "^16.2.0", @@ -119,8 +117,14 @@ "react": ">=0.14.7" }, "jest": { - "setupFiles": ["./src/tests/helpers/jestSetup.js"], - "snapshotSerializers": ["enzyme-to-json/serializer"], - "collectCoverageFrom": ["src/*.js"] + "setupFiles": [ + "./src/tests/helpers/jestSetup.js" + ], + "snapshotSerializers": [ + "enzyme-to-json/serializer" + ], + "collectCoverageFrom": [ + "src/*.js" + ] } } From 6657918f95449216909e9b901c3f3125db3aacdf Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 27 Mar 2018 10:58:59 -0700 Subject: [PATCH 126/165] Update aria-attributes --- demo/components/SearchBar.js | 4 +--- src/PlacesAutocomplete.js | 20 +++++++++---------- .../__snapshots__/initialRender.test.js.snap | 4 ---- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 1580b160..be0431f3 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -14,9 +14,7 @@ class SearchBar extends React.Component { /* eslint-disable no-console */ console.log('selected', selected); geocodeByAddress(selected) - .then(res => - console.log('res', JSON.stringify(res)) - ) + .then(res => console.log('res', JSON.stringify(res))) .catch(error => { console.log('error', error); }); diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index deb57e7a..d2077343 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -205,6 +205,13 @@ class PlacesAutocomplete extends React.Component { } }; + getActiveSuggestionId = () => { + const activeSuggestion = this.getActiveSuggestion(); + return activeSuggestion + ? `PlacesAutocomplete__suggestion-${activeSuggestion.placeId}` + : null; + }; + getIsExpanded = () => { return this.state.suggestions.length > 0; }; @@ -222,20 +229,13 @@ class PlacesAutocomplete extends React.Component { ); } - const isExpanded = this.getIsExpanded(); - const activeSuggestion = this.getActiveSuggestion(); - const activeSuggestionId = activeSuggestion - ? `PlacesAutocomplete__suggestion-${activeSuggestion.placeId}` - : null; const defaultInputProps = { type: 'text', autoComplete: 'off', role: 'combobox', 'aria-autocomplete': 'list', - 'aria-controls': 'PlacesAutocomplete__autocomplete-container', - 'aria-expanded': isExpanded, - 'aria-haspopup': isExpanded, - 'aria-activedescendant': activeSuggestionId, + 'aria-expanded': this.getIsExpanded(), + 'aria-activedescendant': this.getActiveSuggestionId(), }; return { @@ -255,7 +255,7 @@ class PlacesAutocomplete extends React.Component { return { ...whitelistedOptions, key: suggestion.placeId, - id: `PlacesAutocomplete__suggestion-${suggestion.placeId}`, + id: this.getActiveSuggestionId(), role: 'option', onMouseEnter: this.handleSuggestionMouseEnter.bind( this, diff --git a/src/tests/__snapshots__/initialRender.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap index 3a52398f..38de0870 100644 --- a/src/tests/__snapshots__/initialRender.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -14,9 +14,7 @@ exports[`initial render 1`] = ` Date: Thu, 29 Mar 2018 05:21:46 +0900 Subject: [PATCH 127/165] Add more initial render tests --- .../__snapshots__/initialRender.test.js.snap | 28 ++++++++++++++++ src/tests/initialRender.test.js | 32 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/tests/__snapshots__/initialRender.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap index 38de0870..99470dd8 100644 --- a/src/tests/__snapshots__/initialRender.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -28,6 +28,34 @@ exports[`initial render 1`] = ` `; +exports[`initial render with initial input value 1`] = ` + +
+ +
+
+ +`; + exports[`initial render with options to props-getter 1`] = ` { expect(component).toMatchSnapshot(); }); + +test('initial render with initial input value', () => { + let state = { + address: 'San Francisco, CA', + }; + const onChangeFunc = newAddress => { + state = { address: newAddress }; // reassian new object to state + }; + + const component = mount( + + {({ getInputProps, suggestions, getSuggestionItemProps }) => ( +
+ +
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.description} +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+ )} +
+ ); + + expect(component).toMatchSnapshot(); +}); From 7c32a7749f9a4dbe3000fe9b43ab902b43825761 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 29 Mar 2018 19:23:01 +0900 Subject: [PATCH 128/165] Include id, matchedSubstrings, terms, types in suggestions --- src/PlacesAutocomplete.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index d2077343..3f057822 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -55,11 +55,15 @@ class PlacesAutocomplete extends React.Component { const { highlightFirstSuggestion } = this.props; this.setState({ suggestions: predictions.map((p, idx) => ({ + id: p.id, description: p.description, placeId: p.place_id, active: highlightFirstSuggestion && idx === 0 ? true : false, index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), + matchedSubstrings: p.matched_substrings, + terms: p.terms, + types: p.types, })), }); }; From 5381634acb0f2bb26898838adccd0397a9b71b30 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 29 Mar 2018 22:04:11 +0900 Subject: [PATCH 129/165] Add clear button in demo --- demo/app.css | 18 ++++++++++++++++++ demo/components/SearchBar.js | 25 +++++++++++++++++++------ src/PlacesAutocomplete.js | 2 +- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/demo/app.css b/demo/app.css index 29e935ad..c2ae20f9 100644 --- a/demo/app.css +++ b/demo/app.css @@ -41,6 +41,10 @@ body, #root, .page-wrapper { color: #e53935; } +.Demo__search-input-container { + position: relative; +} + .Demo__search-input, .Demo__search-input:focus, .Demo__search-input:active { @@ -54,6 +58,20 @@ body, #root, .page-wrapper { outline: none; } +.Demo__clear-button, +.Demo__clear-button:active, +.Demo__clear-button:focus { + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + background: transparent; + border: none; + outline: none; + font-weight: 600; + color: #999; +} + .Demo__autocomplete-container { border-bottom: honeydew; border-left: honeydew; diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index be0431f3..ce231258 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -21,6 +21,11 @@ class SearchBar extends React.Component { /* eslint-enable no-console */ }; + handleCloseClick = (e) => { + console.log(e); + this.setState({ address: '' }); + } + render() { return ( { return (
- +
+ + {this.state.address.length > 0 && ( + + )} +
{suggestions.map( suggestion => ( diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 3f057822..76b6189a 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -310,8 +310,8 @@ class PlacesAutocomplete extends React.Component { render() { return this.props.children({ getInputProps: this.getInputProps, - suggestions: this.state.suggestions, getSuggestionItemProps: this.getSuggestionItemProps, + suggestions: this.state.suggestions, }); } } From 26ecce096a68a9387ebc772890ffa95715466cd1 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Mar 2018 08:11:43 +0900 Subject: [PATCH 130/165] Add test for onChange prop --- src/tests/helpers/setup.js | 28 ++++++++++++++++++++++++++++ src/tests/onChangeProp.test.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/tests/onChangeProp.test.js diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index 9e8b34b4..b92c622f 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -1,3 +1,6 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import PlacesAutocomplete from '../..'; import { GEOCODE_RESULT } from './googlePayloads'; class GeocoderMock { @@ -58,3 +61,28 @@ export const setupGoogleMock = () => { }; global.window.google = google; }; + +export const mountComponent = props => { + const { value, onChange } = props; + const wrapper = mount( + + {({ getInputProps, suggestions, getSuggestionItemProps }) => ( +
+ +
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.description} +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+ )} +
+ ); + return wrapper; +}; diff --git a/src/tests/onChangeProp.test.js b/src/tests/onChangeProp.test.js new file mode 100644 index 00000000..4e4db51c --- /dev/null +++ b/src/tests/onChangeProp.test.js @@ -0,0 +1,32 @@ +import { mountComponent, setupGoogleMock } from './helpers/setup'; + +beforeAll(() => { + setupGoogleMock(); +}); + +describe('onChange prop', () => { + it('handles user typing in input field', () => { + const onChangeHandler = jest.fn(); + const wrapper = mountComponent({ + value: '', + onChange: onChangeHandler, + }); + const input = wrapper.find('input'); + input.simulate('change', { target: { value: 's' } }); + expect(onChangeHandler).toHaveBeenCalledTimes(1); + expect(onChangeHandler).toBeCalledWith('s'); + }); + + it('handles user pasting multiple characters in input field', () => { + const onChangeHandler = jest.fn(); + const wrapper = mountComponent({ + value: '', + onChange: onChangeHandler, + }); + const input = wrapper.find('input'); + // simulate pasting + input.simulate('change', { target: { value: 'New York' } }); + expect(onChangeHandler).toHaveBeenCalledTimes(1); + expect(onChangeHandler).toBeCalledWith('New York'); + }); +}); From 9f6d5c1dec5942e2d75d5380a9af344c7cbcba2c Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Mar 2018 10:17:48 +0900 Subject: [PATCH 131/165] Add tests for keyboard event handlers --- src/tests/helpers/testHelpers.js | 115 +++++++++++++++++++++++++++++++ src/tests/keyboardEvents.test.js | 29 ++++++++ 2 files changed, 144 insertions(+) create mode 100644 src/tests/helpers/testHelpers.js create mode 100644 src/tests/keyboardEvents.test.js diff --git a/src/tests/helpers/testHelpers.js b/src/tests/helpers/testHelpers.js new file mode 100644 index 00000000..c95f19a7 --- /dev/null +++ b/src/tests/helpers/testHelpers.js @@ -0,0 +1,115 @@ +/* eslint-disable quotes */ +/* + * Simulates User typing 'San Francisco' in input, + * and getting results back from Google Maps API, + * populating `suggesions` state. + */ +export const simulateSearch = wrapper => { + const input = wrapper.find('input'); + // simulate user typing query + input.simulate('change', { target: { value: 'San Francisco' } }); + // simulate fetching predictions + wrapper.setState({ + suggestions: [ + { + active: false, + description: 'San Francisco, CA, USA', + id: '1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a', + index: 0, + placeId: 'ChIJIQBpAG2ahYAR_6128GcTUEo', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: 'San Francisco', + secondaryText: 'CA, USA', + }, + terms: [ + { offset: 0, value: 'San Francisco' }, + { offset: 15, value: 'CA' }, + { offset: 19, value: 'USA' }, + ], + types: ['locality', 'political', 'geocode'], + }, + { + active: false, + description: + 'San Francisco International Airport (SFO), San Francisco, CA, USA', + id: '9c9fb107d7a776c3f6a26791b07982d7db079113', + index: 1, + placeId: 'ChIJVVVVVYx3j4ARP-3NGldc8qQ', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: 'San Francisco International Airport (SFO)', + secondaryText: 'San Francisco, CA, USA', + }, + terms: [ + { offset: 0, value: 'San Francisco International Airport (SFO)' }, + { offset: 43, value: 'San Francisco' }, + { offset: 58, value: 'CA' }, + { offset: 62, value: 'USA' }, + ], + types: ['establishment'], + }, + { + active: false, + description: 'Coacalco, State of Mexico, Mexico', + id: '33fd014a14255500805e49d7de6b7ed439d890a9', + index: 2, + placeId: 'ChIJmz3ukEbx0YUR_iiKUJOxHUA', + matchedSubstrings: [{ length: 8, offset: 0 }], + formattedSuggestion: { + mainText: 'Coacalco', + secondaryText: 'State of Mexico, Mexico', + }, + terms: [ + { offset: 0, value: 'Coacalco' }, + { offset: 10, value: 'State of Mexico' }, + { offset: 27, value: 'Mexico' }, + ], + types: ['locality', 'political', 'geocode'], + }, + { + active: false, + description: + "San Francisco Int'l Airport Station, San Francisco, CA, USA", + id: 'fd59fa62088bda5c2747abbae2614bd7f6525154', + index: 3, + placeId: 'ChIJVVVVVYx3j4ARyN7qnq2JceQ', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: "San Francisco Int'l Airport Station", + secondaryText: 'San Francisco, CA, USA', + }, + terms: [ + { offset: 0, value: "San Francisco Int'l Airport Station" }, + { offset: 37, value: 'San Francisco' }, + { offset: 52, value: 'CA' }, + { offset: 56, value: 'USA' }, + ], + types: [ + 'transit_station', + 'point_of_interest', + 'establishment', + 'geocode', + ], + }, + { + active: false, + description: 'San Francisco del Rincón, Guanajuato, Mexico', + id: 'e4007a708341192d1ddd49bce5cff3dd429e3f98', + index: 4, + placeId: 'ChIJ3bwFNq7DK4QR1ZorLLDndeA', + formattedSuggestion: { + mainText: 'San Francisco del Rincón', + secondaryText: 'Guanajuato, Mexico', + }, + matchedSubstrings: [{ length: 13, offset: 0 }], + terms: [ + { offset: 0, value: 'San Francisco del Rincón' }, + { offset: 26, value: 'Guanajuato' }, + { offset: 38, value: 'Mexico' }, + ], + types: ['locality', 'political', 'geocode'], + }, + ], + }); +}; diff --git a/src/tests/keyboardEvents.test.js b/src/tests/keyboardEvents.test.js new file mode 100644 index 00000000..5e5a04fb --- /dev/null +++ b/src/tests/keyboardEvents.test.js @@ -0,0 +1,29 @@ +import { mountComponent, setupGoogleMock } from './helpers/setup'; +import { simulateSearch } from './helpers/testHelpers'; + +beforeAll(() => { + setupGoogleMock(); +}); + +describe('keyboard events handlers', () => { + it('handles ArrowDown key', () => { + const wrapper = mountComponent({ + value: '', + onChange: () => {}, + }); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'ArrowDown' }); + const { suggestions } = wrapper.state(); + expect(suggestions[0].active).toEqual(true); + }); + + // TODO: handler ArrowUp + + // TODO: handle ESC key + + // TODO: handle Enter key + + // TODO: handle Tab key +}); From 427555eb33a4c7f2d770efc0e03ea562c4737df6 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Mar 2018 10:38:38 +0900 Subject: [PATCH 132/165] Use suggesion.id for key --- src/PlacesAutocomplete.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 76b6189a..01f6d6a0 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -258,7 +258,7 @@ class PlacesAutocomplete extends React.Component { const whitelistedOptions = pick(options, 'className', 'style'); return { ...whitelistedOptions, - key: suggestion.placeId, + key: suggestion.id, id: this.getActiveSuggestionId(), role: 'option', onMouseEnter: this.handleSuggestionMouseEnter.bind( From 3d50f88412d626a3508de21dfb153f4fca7a68c9 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Mar 2018 11:04:28 +0900 Subject: [PATCH 133/165] Add more tests --- src/tests/helpers/setup.js | 10 +++- src/tests/helpers/testHelpers.js | 3 +- src/tests/keyboardEvents.test.js | 92 ++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index b92c622f..8fe6afa9 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -62,8 +62,14 @@ export const setupGoogleMock = () => { global.window.google = google; }; -export const mountComponent = props => { - const { value, onChange } = props; +const DEFAULT_PROPS = { + value: '', + onChange: () => {}, +}; + +export const mountComponent = (props = {}) => { + const _props = { ...DEFAULT_PROPS, ...props }; + const { value, onChange } = _props; const wrapper = mount( {({ getInputProps, suggestions, getSuggestionItemProps }) => ( diff --git a/src/tests/helpers/testHelpers.js b/src/tests/helpers/testHelpers.js index c95f19a7..87c06ea1 100644 --- a/src/tests/helpers/testHelpers.js +++ b/src/tests/helpers/testHelpers.js @@ -1,5 +1,6 @@ /* eslint-disable quotes */ -/* + +/** * Simulates User typing 'San Francisco' in input, * and getting results back from Google Maps API, * populating `suggesions` state. diff --git a/src/tests/keyboardEvents.test.js b/src/tests/keyboardEvents.test.js index 5e5a04fb..a8bb4007 100644 --- a/src/tests/keyboardEvents.test.js +++ b/src/tests/keyboardEvents.test.js @@ -6,11 +6,8 @@ beforeAll(() => { }); describe('keyboard events handlers', () => { - it('handles ArrowDown key', () => { - const wrapper = mountComponent({ - value: '', - onChange: () => {}, - }); + test('pressing ArrowDown key will make the first suggestion active', () => { + const wrapper = mountComponent(); simulateSearch(wrapper); const input = wrapper.find('input'); @@ -19,11 +16,88 @@ describe('keyboard events handlers', () => { expect(suggestions[0].active).toEqual(true); }); - // TODO: handler ArrowUp + test('pressing ArrowUp key will make the last suggestion active', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'ArrowUp' }); + const { suggestions } = wrapper.state(); + expect(suggestions[suggestions.length - 1].active).toEqual(true); + }); + + test('pressing ArrowUp/ArrowDown will make activate correct suggestion item', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'ArrowDown' }); // index 0 active + input.simulate('keydown', { key: 'ArrowDown' }); // index 1 active + input.simulate('keydown', { key: 'ArrowDown' }); // index 2 active + input.simulate('keydown', { key: 'ArrowUp' }); // index 1 active + const { suggestions } = wrapper.state(); + expect(suggestions[1].active).toEqual(true); + }); + + test('wraps with ArrowDown key', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + let { suggestions } = wrapper.state(); + for (let i = 0; i < suggestions.length; i++) { + input.simulate('keydown', { key: 'ArrowDown' }); + } + suggestions = wrapper.state().suggestions; + expect(suggestions[suggestions.length - 1].active).toEqual(true); + + input.simulate('keydown', { key: 'ArrowDown' }); + suggestions = wrapper.state().suggestions; + expect(suggestions.find(s => s.active)).toBeUndefined(); + + input.simulate('keydown', { key: 'ArrowDown' }); + suggestions = wrapper.state().suggestions; + expect(suggestions[0].active).toEqual(true); + }); + + test('wraps with ArrowUp key', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + let { suggestions } = wrapper.state(); + for (let i = 0; i < suggestions.length; i++) { + input.simulate('keydown', { key: 'ArrowUp' }); + } + suggestions = wrapper.state().suggestions; + expect(suggestions[0].active).toEqual(true); - // TODO: handle ESC key + input.simulate('keydown', { key: 'ArrowUp' }); + suggestions = wrapper.state().suggestions; + expect(suggestions.find(s => s.active)).toBeUndefined(); - // TODO: handle Enter key + input.simulate('keydown', { key: 'ArrowUp' }); + suggestions = wrapper.state().suggestions; + expect(suggestions[suggestions.length - 1].active).toEqual(true); + }); + + test('pressing ESC key will clear suggestions', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); - // TODO: handle Tab key + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'Escape' }); + const { suggestions } = wrapper.state(); + expect(suggestions.length).toEqual(0); + }); + + test('pressing Enter key will clear suggestions', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'Enter' }); + const { suggestions } = wrapper.state(); + expect(suggestions.length).toEqual(0); + }); }); From 76093778bc3ba50b80cc704e9be5a1f9f61798dd Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 30 Mar 2018 20:56:28 +0900 Subject: [PATCH 134/165] Change travis CI config --- .babelrc | 4 + .travis.yml | 6 +- package-lock.json | 143 ++++++++++++++++++++++++++++----- package.json | 1 + src/tests/helpers/jestSetup.js | 8 +- 5 files changed, 136 insertions(+), 26 deletions(-) diff --git a/.babelrc b/.babelrc index 0174190b..8add46ff 100644 --- a/.babelrc +++ b/.babelrc @@ -4,6 +4,10 @@ "presets": ["env", "stage-0", "react"], "plugins": ["transform-class-properties"] }, + "test": { + "presets": ["env", "stage-0", "react"], + "plugins": ["transform-class-properties"] + }, "production": { "presets": ["env", "stage-0", "react"], "plugins": [ diff --git a/.travis.yml b/.travis.yml index 7e9b5f03..4b3e6c83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,16 +6,14 @@ cache: notifications: email: false node_js: - - '4' + - '8' before_install: - - npm i -g npm@^2.0.0 + - npm i -g npm@^5.8.0 before_script: - npm prune script: - npm run test - npm run build -after_success: - - npm run semantic-release branches: except: - /^v\d+\.\d+\.\d+$/ diff --git a/package-lock.json b/package-lock.json index d834c31b..85a48ac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -669,7 +669,7 @@ "requires": { "babel-core": "6.24.1", "babel-polyfill": "6.23.0", - "babel-register": "6.24.1", + "babel-register": "6.26.0", "babel-runtime": "6.23.0", "chokidar": "1.6.1", "commander": "2.9.0", @@ -752,7 +752,7 @@ "babel-generator": "6.24.1", "babel-helpers": "6.24.1", "babel-messages": "6.23.0", - "babel-register": "6.24.1", + "babel-register": "6.26.0", "babel-runtime": "6.23.0", "babel-template": "6.24.1", "babel-traverse": "6.24.1", @@ -4761,34 +4761,137 @@ } }, "babel-register": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", - "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", "dev": true, "requires": { - "babel-core": "6.24.1", - "babel-runtime": "6.23.0", - "core-js": "2.4.0", + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.4", "home-or-tmp": "2.0.0", "lodash": "4.17.4", "mkdirp": "0.5.1", - "source-map-support": "0.4.14" + "source-map-support": "0.4.18" }, "dependencies": { + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.6" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", - "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.4.0", - "regenerator-runtime": "0.10.3" + "core-js": "2.5.4", + "regenerator-runtime": "0.11.1" } }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "core-js": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.4.tgz", + "integrity": "sha1-8si/GB8qgLkvNgEhQpzmOi8K6uA=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, "regenerator-runtime": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz", - "integrity": "sha1-jENnqQS1HqYqkIrDEL+Z/5CoKj4=", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true } } @@ -17026,9 +17129,9 @@ } }, "source-map-support": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.14.tgz", - "integrity": "sha1-nURjdyWYuGJxtPUj9sH04Cp9au8=", + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { "source-map": "0.5.6" diff --git a/package.json b/package.json index 9618447d..39c17a2f 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "babel-preset-env": "1.6.1", "babel-preset-react": "^6.23.1", "babel-preset-stage-0": "^6.22.0", + "babel-register": "6.26.0", "commitizen": "2.8.2", "copy-webpack-plugin": "^4.0.1", "cz-conventional-changelog": "1.1.6", diff --git a/src/tests/helpers/jestSetup.js b/src/tests/helpers/jestSetup.js index 5cc61361..9eefcad7 100644 --- a/src/tests/helpers/jestSetup.js +++ b/src/tests/helpers/jestSetup.js @@ -1,4 +1,8 @@ -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; +// Register babel so that it will transpile ES6 to ES5 +// before our tests run. +require('babel-register')(); + +const Enzyme = require('enzyme'); +const Adapter = require('enzyme-adapter-react-16'); // React 16 Enzyme adapter Enzyme.configure({ adapter: new Adapter() }); From d90439e62f377b6bcf7d0ef08104d95beacd3afe Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 31 Mar 2018 09:54:17 +0900 Subject: [PATCH 135/165] Update readme --- README.md | 404 +++++++++++++++++++++++------------------------------- 1 file changed, 168 insertions(+), 236 deletions(-) diff --git a/README.md b/README.md index bc9dcb9f..d5c68238 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) 2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) -3. Pass through arbitrary props to the input element to integrate well with other libraries (e.g. Redux-Form) +3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form) 4. Mobile friendly UX 5. WAI-ARIA compliant @@ -24,13 +24,7 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib To install the stable version ```sh -yarn add react-places-autocomplete -``` - -or - -```sh -npm install react-places-autocomplete --save +npm install --save react-places-autocomplete ``` React component is exported as a default export @@ -39,10 +33,10 @@ React component is exported as a default export import PlacesAutocomplete from 'react-places-autocomplete' ``` -`geocodeByAddress` and `geocodeByPlaceId` utility functions are named exports +utility functions are named exports ```js -import { geocodeByAddress, geocodeByPlaceId } from 'react-places-autocomplete' +import { geocodeByAddress, geocodeByPlaceId, getLatLng } from 'react-places-autocomplete' ``` @@ -62,235 +56,193 @@ Create your component import React from 'react' import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete' -class SimpleForm extends React.Component { +class LocationSearchInput extends React.Component { constructor(props) { - super(props) - this.state = { address: 'San Francisco, CA' } - this.onChange = (address) => this.setState({ address }) + super(props); + this.state = { address: '' } } - handleFormSubmit = (event) => { - event.preventDefault() + handleChange = (address) => { + this.setState({ address }) + } - geocodeByAddress(this.state.address) + handleSelect = (address) => { + geocodeByAddress(address) .then(results => getLatLng(results[0])) .then(latLng => console.log('Success', latLng)) .catch(error => console.error('Error', error)) } render() { - const inputProps = { - value: this.state.address, - onChange: this.onChange, - } - return ( -
- - - - ) + + {({ getInputProps, suggestions, getSuggestionItemProps }) => ( +
+ +
+ {suggestions.map(suggestion => ( +
+ + {suggestion.description} + +
+ ))} +
+
+ )} +
+ ); } } - -export default SimpleForm ``` ## Props +PlacesAutocomplete is a [Controlled Component](https://facebook.github.io/react/docs/forms.html#controlled-components) with a [Render Prop](https://reactjs.org/docs/render-props.html). Therefore, you MUST pass at least `value` and `onChange` callback to the input element, and render function via `children`. + | Prop | Type | Required | Description | | ------------- |:-------------:| :-----: |-------| -| [`inputProps`](#inputProps) | object | :white_check_mark: | Arbitrary props to input element, `value` and `onChange` are required keys | -| [`renderSuggestion`](#renderSuggestion) | function | | Functional react component to render dropdown list item | -| [`renderFooter`](#renderFooter) | function | | Functional react component to render footer at the bottom of the dropdown list | -| [`classNames`](#classNames) | object | | Pass CSS classes to rendered elements | -| [`styles`](#styles) | object | | Pass CSS styles to rendered elements | +| [`value`](#value) | string | :white_check_mark: | `value` for the input element | +| [`onChange`](#onChange) | function | :white_check_mark: | `onChange` function for the input element | +| [`children`](#children) | function | :white_check_mark: | Render function to specify the rendering | | [`onSelect`](#onSelect) | function | | Event handler to handle user's select event | -| [`onEnterKeyDown`](#onEnterKeyDown) | function || Event handler that gets called when user presses Enter key while input is focused | | [`onError`](#onError) | function | | Error handler function that gets called when Google Maps API responds with an error | -| [`options`](#options) | object | | Options to Google Maps API (i.e. bounds, radius) | +| [`searchOptions`](#searchOptions) | object | | Options to Google Maps API (i.e. bounds, radius) | |[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | | [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | -|[`shouldFetchSuggestions`](#shouldFetchSuggestions)| function | | Component will fetch suggestions from Google Maps API only when this function returns `true` | +|[`shouldFetchSuggestions`](#shouldFetchSuggestions)| boolean | | Component will hit Google Maps API only if this flag is set `true` | - -#### inputProps -Type: `Object`, + +#### value +Type: `string`, Required: `true` -PlacesAutocomplete is a [controlled component](https://facebook.github.io/react/docs/forms.html#controlled-components). Therefore, you MUST pass at least `value` and `onChange` callback to the input element. - -You can pass arbitrary props to the input element thorough `inputProps` object (NOTE: `className` and `style` props for the input element should be passed through `classNames.input` and `styles.input` respectively). -```js - const inputProps = { - value, // `value` is required - onChange, // `onChange` is required - onBlur: () => { - console.log('blur!') - }, - type: 'search', - placeholder: 'Search Places...', - autoFocus: true, - } -``` - - -#### renderSuggestion -Type: `Functional React Component`, -Required: `false` + +#### onChange +Type: `function`, +Required: `true` -The function takes props with `suggestion`, `formattedSuggestion` keys (see the example below). -We highly recommend that you create your own custom list item component and pass it as a prop. +Typically this event handler will update `value` state. ```js -/*********************************************** - Example #1 - List item example with `suggestion` -************************************************/ -render() { - const renderSuggestion = ({ suggestion }) => (
{suggestion}
) - - return ( - - ) -} - -/*************************************************** - Example #2 - List item example with `formattedSuggestion` -****************************************************/ -render() { - const renderSuggestion = ({ formattedSuggestion }) => ( -
- { formattedSuggestion.mainText }{' '} - { formattedSuggestion.secondaryText } -
- ) - - return ( - - ) -} + this.setState({ value })} +> + {/* custom render function */} + ``` - -#### renderFooter -Type: `Functional React Component` -Required: `false` + +#### children +Type: `function` +Required: `true` -You can provide a component that will get rendered at the bottom of dropdown. -For example, you can provide a component to show "Powered by Google" logo. +This is where you render whatever you want to based on the state of `PlacesAutocomplete`. +The function will take an object with the following keys. +- `getInputProps` : function +- `getSuggestionItemProps` : function +- `suggestions` : array +Simple example ```js -const renderFooter = () => ( -
-
- +const renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions }) => ( +
+ +
+ {suggestions.map(suggestion => ( +
+ {suggestion.description} +
+ ))}
-) +); // In render function + value={this.state.value} + onChange={this.handleChange} +> + {renderFunc} + ``` - -#### classNames -Type: `Object`, -Required: `false` - -You can give a custom css classes to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. -If you pass `classNames` props, none of the default inline styles nor inline styles from `styles` prop will -be applied to the element, and you will have full control over styling via CSS. +#### getInputProps +This function will return the props that you can spread over the `` element. +You can optionally call the function with an object to pass other props to the input. ```js -// classNames example -render() { - const cssClasses = { - root: 'form-group', - input: 'form-control', - autocompleteContainer: 'my-autocomplete-container' - } - - return ( - - ) -} +// In render function + ``` -Now you can easily apply custom CSS styles using the classNames! - - -#### styles -Type `Object`, -Required: `false` -You can provide custom inline styles to elements. -Accepted keys are `root`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`. +#### getSuggestionItemProps +This function will return the props that you can spread over each suggestion item in your +autocomplete dropdown. You MUST call it with `suggestion` object as an argument, and optionally pass an object to pass other props to the element. ```js -const defaultStyles = { - root: { - position: 'relative', - paddingBottom: '0px', - }, - input: { - display: 'inline-block', - width: '100%', - padding: '10px', - }, - autocompleteContainer: { - position: 'absolute', - top: '100%', - backgroundColor: 'white', - border: '1px solid #555555', - width: '100%', - }, - autocompleteItem: { - backgroundColor: '#ffffff', - padding: '10px', - color: '#555555', - cursor: 'pointer', - }, - autocompleteItemActive: { - backgroundColor: '#fafafa' - }, -} +// Simple example +
+ {suggestions.map(suggestion => ( +
+ {suggesion.description} +
+ ))} +
+ +// Pass options as a second argument +
+ {suggestions.map(suggestion => { + const className = suggestion.active ? 'suggestion-item--active' : 'suggesion-item'; + return ( +
+ {suggestion.description} +
+ ); + })} +
+ ``` -Object passed via `styles` prop will be merged in with the above defaults and applied to their respective elements. -NOTE: Passing `classNames` will disable any inline styling for respective elements. +#### suggestions +This is an array of suggestion objects each containing all the data from Google Maps API and other metadata. -```js -// custom style examples -render() { - const myStyles = { - root: { position: 'absolute' }, - input: { width: '100%' }, - autocompleteContainer: { backgroundColor: 'green' }, - autocompleteItem: { color: 'black' }, - autocompleteItemActive: { color: 'blue' } - } +An example of a suggestion object. - return ( - - ) +```js +{ + active: false, + description: "San Francisco, CA, USA", + formattedSuggestion: { mainText: "San Francisco", secondaryText: "CA, USA" }, + id: "1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a", + index: 0, + matchedSubstrings: [ {length: 8, offset: 0} ], + placeId: "ChIJIQBpAG2ahYAR_6128GcTUEo", + terms: [ + { offset: 0, value: "San Francisco" }, + { offset: 15, value: "CA" }, + { offset: 19, value: "USA" } + ], + types: ["locality", "political", "geocode"] } ``` @@ -314,33 +266,12 @@ const handleSelect = (address, placeId) => { // Pass this function via onSelect prop. -``` - - -#### onEnterKeyDown -Type: `Function` -Required: `false` -Deafult: `noop` - -You can pass a callback function that gets called when pressing down Enter key when no item in the dropdown is selected. -The function takes one argument, the value in the input field. - -```js -const handleEnter = (address) => { - geocodeByAddress(address) - .then(results => { - console.log('results', results) - }) -} - -// Pass this function via onEnterKeyDown prop. - +> + {/* Custom render function */} + ``` @@ -359,38 +290,42 @@ const onError = (status, clearSuggestions) => { clearSuggestions() } -// In render function +> + {/* Custom render function */} + ``` - -#### options + +#### searchOptions Type: `Object` Required: `false` Default: `{}` -You can fine-tune the settings passed to the AutocompleteService class with `options` prop. +You can fine-tune the settings passed to the AutocompleteService class with `searchOptions` prop. This prop accepts an object following the same format as [google.maps.places.AutocompletionRequest](https://developers.google.com/maps/documentation/javascript/reference#AutocompletionRequest) (except for `input`, which comes from the value of the input field). ```js // these options will bias the autocomplete predictions toward Sydney, Australia with a radius of 2000 meters, // and limit the results to addresses only -const options = { +const searchOptions = { location: new google.maps.LatLng(-34, 151), radius: 2000, types: ['address'] } -// In render function + value={this.state.value} + onChange={this.handleChange} + searchOptions={searchOptions} +> + {/* Custom render function */} + ``` @@ -403,7 +338,7 @@ The number of milliseconds to delay before making a call to Google Maps API. #### highlightFirstSuggestion -Type: `Boolean` +Type: `boolean` Required: `false` Default: `false` @@ -411,22 +346,19 @@ If set to `true`, first suggestion in the dropdown will be automatically highlig #### shouldFetchSuggestions -Type: `Function` +Type: `boolean` Required: `false` -Default: `() => true` - -You can pass a function to tell when to fetch suggestions from Google Maps API. -It takes an input `{ value }` and should return a boolean. +Default: `true` ```js // Only fetch suggestions when the input text is longer than 3 characters. -const shouldFetchSuggestions = ({ value }) => value.length > 3 - -// In render function + value={this.state.address} + onChange={this.handleChange} + shouldFetchSuggestions={this.state.address.length > 3} +> + {/* custom render function */} + ``` From 66fe0d78da6c3bad321592e0bf70ee2e9c81c842 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 1 Apr 2018 16:13:40 +0900 Subject: [PATCH 136/165] Add tests for mouse event handlers --- src/PlacesAutocomplete.js | 7 ++++--- src/tests/helpers/setup.js | 13 +++++++++--- src/tests/keyboardEvents.test.js | 2 +- src/tests/mouseEvents.test.js | 36 ++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 src/tests/mouseEvents.test.js diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 01f6d6a0..0da31baa 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -7,7 +7,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import debounce from 'lodash.debounce'; -import { compose, pick } from './helpers'; +import { compose } from './helpers'; // transform snake_case to camelCase const formattedSuggestion = structured_formatting => ({ @@ -255,9 +255,10 @@ class PlacesAutocomplete extends React.Component { }; getSuggestionItemProps = (suggestion, options = {}) => { - const whitelistedOptions = pick(options, 'className', 'style'); + // TODO: whitelist options OR allow all options and compose + // event handlers return { - ...whitelistedOptions, + ...options, key: suggestion.id, id: this.getActiveSuggestionId(), role: 'option', diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index 8fe6afa9..a51ef350 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -65,13 +65,16 @@ export const setupGoogleMock = () => { const DEFAULT_PROPS = { value: '', onChange: () => {}, + onSelect: () => {}, + debounce: 200, + highlightFirstSuggestion: true, + shouldFetchSuggestions: true, }; export const mountComponent = (props = {}) => { const _props = { ...DEFAULT_PROPS, ...props }; - const { value, onChange } = _props; const wrapper = mount( - + {({ getInputProps, suggestions, getSuggestionItemProps }) => (
@@ -79,7 +82,11 @@ export const mountComponent = (props = {}) => { {suggestions.map( suggestion => ( /* eslint-disable react/jsx-key */ -
+
{suggestion.description}
) diff --git a/src/tests/keyboardEvents.test.js b/src/tests/keyboardEvents.test.js index a8bb4007..e0f76686 100644 --- a/src/tests/keyboardEvents.test.js +++ b/src/tests/keyboardEvents.test.js @@ -34,7 +34,7 @@ describe('keyboard events handlers', () => { input.simulate('keydown', { key: 'ArrowDown' }); // index 0 active input.simulate('keydown', { key: 'ArrowDown' }); // index 1 active input.simulate('keydown', { key: 'ArrowDown' }); // index 2 active - input.simulate('keydown', { key: 'ArrowUp' }); // index 1 active + input.simulate('keydown', { key: 'ArrowUp' }); // index 1 active const { suggestions } = wrapper.state(); expect(suggestions[1].active).toEqual(true); }); diff --git a/src/tests/mouseEvents.test.js b/src/tests/mouseEvents.test.js new file mode 100644 index 00000000..d0ca63e0 --- /dev/null +++ b/src/tests/mouseEvents.test.js @@ -0,0 +1,36 @@ +import { mountComponent, setupGoogleMock } from './helpers/setup'; +import { simulateSearch } from './helpers/testHelpers'; + +beforeAll(() => { + setupGoogleMock(); +}); + +describe('mouse event handlers', () => { + test('suggesion item handles mouse enter and leave event', () => { + const wrapper = mountComponent(); + simulateSearch(wrapper); + + const suggestionItem = wrapper + .find('[data-test="suggestion-item"]') + .first(); + suggestionItem.simulate('mouseenter'); + let { suggestions } = wrapper.state(); + expect(suggestions[0].active).toEqual(true); + + suggestionItem.simulate('mouseleave'); + suggestions = wrapper.state().suggestions; + expect(suggestions[0].active).toEqual(false); + }); + + test('suggesion item handles click event', () => { + const onSelectHandler = jest.fn(); + const wrapper = mountComponent({ onSelect: onSelectHandler }); + simulateSearch(wrapper); + + const suggestionItem = wrapper + .find('[data-test="suggestion-item"]') + .first(); + suggestionItem.simulate('click'); + expect(onSelectHandler).toHaveBeenCalledTimes(1); + }) +}); From 8d9028a4843f26dba971b67e02b2998ff787b42d Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 1 Apr 2018 16:47:44 +0900 Subject: [PATCH 137/165] Add tests for onSelect prop --- src/tests/helpers/testHelpers.js | 204 +++++++++++++++---------------- src/tests/mouseEvents.test.js | 12 -- src/tests/onSelectProp.test.js | 64 ++++++++++ 3 files changed, 166 insertions(+), 114 deletions(-) create mode 100644 src/tests/onSelectProp.test.js diff --git a/src/tests/helpers/testHelpers.js b/src/tests/helpers/testHelpers.js index 87c06ea1..71265562 100644 --- a/src/tests/helpers/testHelpers.js +++ b/src/tests/helpers/testHelpers.js @@ -1,5 +1,105 @@ /* eslint-disable quotes */ - +export const mockSuggestions = [ + { + active: false, + description: 'San Francisco, CA, USA', + id: '1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a', + index: 0, + placeId: 'ChIJIQBpAG2ahYAR_6128GcTUEo', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: 'San Francisco', + secondaryText: 'CA, USA', + }, + terms: [ + { offset: 0, value: 'San Francisco' }, + { offset: 15, value: 'CA' }, + { offset: 19, value: 'USA' }, + ], + types: ['locality', 'political', 'geocode'], + }, + { + active: false, + description: + 'San Francisco International Airport (SFO), San Francisco, CA, USA', + id: '9c9fb107d7a776c3f6a26791b07982d7db079113', + index: 1, + placeId: 'ChIJVVVVVYx3j4ARP-3NGldc8qQ', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: 'San Francisco International Airport (SFO)', + secondaryText: 'San Francisco, CA, USA', + }, + terms: [ + { offset: 0, value: 'San Francisco International Airport (SFO)' }, + { offset: 43, value: 'San Francisco' }, + { offset: 58, value: 'CA' }, + { offset: 62, value: 'USA' }, + ], + types: ['establishment'], + }, + { + active: false, + description: 'Coacalco, State of Mexico, Mexico', + id: '33fd014a14255500805e49d7de6b7ed439d890a9', + index: 2, + placeId: 'ChIJmz3ukEbx0YUR_iiKUJOxHUA', + matchedSubstrings: [{ length: 8, offset: 0 }], + formattedSuggestion: { + mainText: 'Coacalco', + secondaryText: 'State of Mexico, Mexico', + }, + terms: [ + { offset: 0, value: 'Coacalco' }, + { offset: 10, value: 'State of Mexico' }, + { offset: 27, value: 'Mexico' }, + ], + types: ['locality', 'political', 'geocode'], + }, + { + active: false, + description: + "San Francisco Int'l Airport Station, San Francisco, CA, USA", + id: 'fd59fa62088bda5c2747abbae2614bd7f6525154', + index: 3, + placeId: 'ChIJVVVVVYx3j4ARyN7qnq2JceQ', + matchedSubstrings: [{ length: 13, offset: 0 }], + formattedSuggestion: { + mainText: "San Francisco Int'l Airport Station", + secondaryText: 'San Francisco, CA, USA', + }, + terms: [ + { offset: 0, value: "San Francisco Int'l Airport Station" }, + { offset: 37, value: 'San Francisco' }, + { offset: 52, value: 'CA' }, + { offset: 56, value: 'USA' }, + ], + types: [ + 'transit_station', + 'point_of_interest', + 'establishment', + 'geocode', + ], + }, + { + active: false, + description: 'San Francisco del Rincón, Guanajuato, Mexico', + id: 'e4007a708341192d1ddd49bce5cff3dd429e3f98', + index: 4, + placeId: 'ChIJ3bwFNq7DK4QR1ZorLLDndeA', + formattedSuggestion: { + mainText: 'San Francisco del Rincón', + secondaryText: 'Guanajuato, Mexico', + }, + matchedSubstrings: [{ length: 13, offset: 0 }], + terms: [ + { offset: 0, value: 'San Francisco del Rincón' }, + { offset: 26, value: 'Guanajuato' }, + { offset: 38, value: 'Mexico' }, + ], + types: ['locality', 'political', 'geocode'], + }, +]; /** * Simulates User typing 'San Francisco' in input, * and getting results back from Google Maps API, @@ -11,106 +111,6 @@ export const simulateSearch = wrapper => { input.simulate('change', { target: { value: 'San Francisco' } }); // simulate fetching predictions wrapper.setState({ - suggestions: [ - { - active: false, - description: 'San Francisco, CA, USA', - id: '1b9ea3c094d3ac23c9a3afa8cd4d8a41f05de50a', - index: 0, - placeId: 'ChIJIQBpAG2ahYAR_6128GcTUEo', - matchedSubstrings: [{ length: 13, offset: 0 }], - formattedSuggestion: { - mainText: 'San Francisco', - secondaryText: 'CA, USA', - }, - terms: [ - { offset: 0, value: 'San Francisco' }, - { offset: 15, value: 'CA' }, - { offset: 19, value: 'USA' }, - ], - types: ['locality', 'political', 'geocode'], - }, - { - active: false, - description: - 'San Francisco International Airport (SFO), San Francisco, CA, USA', - id: '9c9fb107d7a776c3f6a26791b07982d7db079113', - index: 1, - placeId: 'ChIJVVVVVYx3j4ARP-3NGldc8qQ', - matchedSubstrings: [{ length: 13, offset: 0 }], - formattedSuggestion: { - mainText: 'San Francisco International Airport (SFO)', - secondaryText: 'San Francisco, CA, USA', - }, - terms: [ - { offset: 0, value: 'San Francisco International Airport (SFO)' }, - { offset: 43, value: 'San Francisco' }, - { offset: 58, value: 'CA' }, - { offset: 62, value: 'USA' }, - ], - types: ['establishment'], - }, - { - active: false, - description: 'Coacalco, State of Mexico, Mexico', - id: '33fd014a14255500805e49d7de6b7ed439d890a9', - index: 2, - placeId: 'ChIJmz3ukEbx0YUR_iiKUJOxHUA', - matchedSubstrings: [{ length: 8, offset: 0 }], - formattedSuggestion: { - mainText: 'Coacalco', - secondaryText: 'State of Mexico, Mexico', - }, - terms: [ - { offset: 0, value: 'Coacalco' }, - { offset: 10, value: 'State of Mexico' }, - { offset: 27, value: 'Mexico' }, - ], - types: ['locality', 'political', 'geocode'], - }, - { - active: false, - description: - "San Francisco Int'l Airport Station, San Francisco, CA, USA", - id: 'fd59fa62088bda5c2747abbae2614bd7f6525154', - index: 3, - placeId: 'ChIJVVVVVYx3j4ARyN7qnq2JceQ', - matchedSubstrings: [{ length: 13, offset: 0 }], - formattedSuggestion: { - mainText: "San Francisco Int'l Airport Station", - secondaryText: 'San Francisco, CA, USA', - }, - terms: [ - { offset: 0, value: "San Francisco Int'l Airport Station" }, - { offset: 37, value: 'San Francisco' }, - { offset: 52, value: 'CA' }, - { offset: 56, value: 'USA' }, - ], - types: [ - 'transit_station', - 'point_of_interest', - 'establishment', - 'geocode', - ], - }, - { - active: false, - description: 'San Francisco del Rincón, Guanajuato, Mexico', - id: 'e4007a708341192d1ddd49bce5cff3dd429e3f98', - index: 4, - placeId: 'ChIJ3bwFNq7DK4QR1ZorLLDndeA', - formattedSuggestion: { - mainText: 'San Francisco del Rincón', - secondaryText: 'Guanajuato, Mexico', - }, - matchedSubstrings: [{ length: 13, offset: 0 }], - terms: [ - { offset: 0, value: 'San Francisco del Rincón' }, - { offset: 26, value: 'Guanajuato' }, - { offset: 38, value: 'Mexico' }, - ], - types: ['locality', 'political', 'geocode'], - }, - ], + suggestions: mockSuggestions, }); }; diff --git a/src/tests/mouseEvents.test.js b/src/tests/mouseEvents.test.js index d0ca63e0..5f7f761d 100644 --- a/src/tests/mouseEvents.test.js +++ b/src/tests/mouseEvents.test.js @@ -21,16 +21,4 @@ describe('mouse event handlers', () => { suggestions = wrapper.state().suggestions; expect(suggestions[0].active).toEqual(false); }); - - test('suggesion item handles click event', () => { - const onSelectHandler = jest.fn(); - const wrapper = mountComponent({ onSelect: onSelectHandler }); - simulateSearch(wrapper); - - const suggestionItem = wrapper - .find('[data-test="suggestion-item"]') - .first(); - suggestionItem.simulate('click'); - expect(onSelectHandler).toHaveBeenCalledTimes(1); - }) }); diff --git a/src/tests/onSelectProp.test.js b/src/tests/onSelectProp.test.js new file mode 100644 index 00000000..71ea6002 --- /dev/null +++ b/src/tests/onSelectProp.test.js @@ -0,0 +1,64 @@ +import { mountComponent, setupGoogleMock } from './helpers/setup'; +import { simulateSearch, mockSuggestions } from './helpers/testHelpers'; + +beforeAll(() => { + setupGoogleMock(); +}); + +describe('onSelect prop', () => { + test('click on suggestion item will call onSelect handler', () => { + const onSelectHandler = jest.fn(); + const wrapper = mountComponent({ onSelect: onSelectHandler }); + simulateSearch(wrapper); + + const suggestionItem = wrapper + .find('[data-test="suggestion-item"]') + .first(); + suggestionItem.simulate('click'); + expect(onSelectHandler).toHaveBeenCalledTimes(1); + }); + + test('pressing Enter key will call onSelect handler', () => { + const onSelectHandler = jest.fn(); + const wrapper = mountComponent({ + value: 'San Francisco', + onSelect: onSelectHandler, + }); + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'Enter' }); + expect(onSelectHandler).toHaveBeenCalledTimes(1); + // first argument is input value, + // second argument is placeId, null in this case. + expect(onSelectHandler).toBeCalledWith('San Francisco', null); + }); + + test('pressing Enter when one of the suggestion items is active', () => { + const onSelectHandler = jest.fn(); + const wrapper = mountComponent({ + onSelect: onSelectHandler, + }); + simulateSearch(wrapper); // suggestions state is populated by mockSuggestions + + const input = wrapper.find('input'); + input.simulate('keydown', { key: 'ArrowDown' }); // index 0 active + input.simulate('keydown', { key: 'Enter' }); + expect(onSelectHandler).toHaveBeenCalledTimes(1); + expect(onSelectHandler).toBeCalledWith(mockSuggestions[0].description, mockSuggestions[0].placeId); + }); + + test('pressing Enter when mouse hovers over one of the suggestion items', () => { + const onSelectHandler = jest.fn(); + const wrapper = mountComponent({ + onSelect: onSelectHandler, + }); + simulateSearch(wrapper); + + const suggestionItem = wrapper.find('[data-test="suggestion-item"]').first(); + const input = wrapper.find('input'); + suggestionItem.simulate('mouseenter'); + input.simulate('keydown', { key: 'Enter' }); + expect(onSelectHandler).toHaveBeenCalledTimes(1); + expect(onSelectHandler).toBeCalledWith(mockSuggestions[0].description, mockSuggestions[0].placeId); + }); +}) From d4508e611d9c36b7bf72335224053ffe223bbd36 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 1 Apr 2018 17:00:01 +0900 Subject: [PATCH 138/165] Update readme example --- README.md | 61 ++++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index d5c68238..f7170331 100644 --- a/README.md +++ b/README.md @@ -81,31 +81,24 @@ class LocationSearchInput extends React.Component { onSelect={this.handleSelect} > {({ getInputProps, suggestions, getSuggestionItemProps }) => ( -
- -
- {suggestions.map(suggestion => ( -
- - {suggestion.description} - -
- ))} -
+
+ +
+ {suggestions.map(suggestion => { + const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item'; + return ( +
+ {suggestion.description} +
+ ) + })}
+
)} ); @@ -130,13 +123,13 @@ PlacesAutocomplete is a [Controlled Component](https://facebook.github.io/react/ |[`shouldFetchSuggestions`](#shouldFetchSuggestions)| boolean | | Component will hit Google Maps API only if this flag is set `true` | -#### value +### value Type: `string`, Required: `true` -#### onChange +### onChange Type: `function`, Required: `true` @@ -152,7 +145,7 @@ Typically this event handler will update `value` state. ``` -#### children +### children Type: `function` Required: `true` @@ -247,7 +240,7 @@ An example of a suggestion object. ``` -#### onSelect +### onSelect Type: `Function` Required: `false`, Default: `null` @@ -275,7 +268,7 @@ const handleSelect = (address, placeId) => { ``` -#### onError +### onError Type: `Function` Required: `false` @@ -301,7 +294,7 @@ const onError = (status, clearSuggestions) => { -#### searchOptions +### searchOptions Type: `Object` Required: `false` Default: `{}` @@ -329,7 +322,7 @@ const searchOptions = { ``` -#### debounce +### debounce Type: `Number` Required: `false` Default: `200` @@ -337,15 +330,15 @@ Default: `200` The number of milliseconds to delay before making a call to Google Maps API. -#### highlightFirstSuggestion +### highlightFirstSuggestion Type: `boolean` Required: `false` Default: `false` -If set to `true`, first suggestion in the dropdown will be automatically highlighted. +If set to `true`, first suggestion in the dropdown will be automatically set to be active. -#### shouldFetchSuggestions +### shouldFetchSuggestions Type: `boolean` Required: `false` Default: `true` From 0b1a12a1111f892f45fac74711e5f5b0bfd55da5 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 1 Apr 2018 17:31:39 +0900 Subject: [PATCH 139/165] Fix test setup file --- src/tests/helpers/setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index a51ef350..d3416490 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -67,7 +67,7 @@ const DEFAULT_PROPS = { onChange: () => {}, onSelect: () => {}, debounce: 200, - highlightFirstSuggestion: true, + highlightFirstSuggestion: false, shouldFetchSuggestions: true, }; From 0311c95c29a2bcbbaade499d56acd82b0a575364 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 8 Apr 2018 11:19:39 +0900 Subject: [PATCH 140/165] Update readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f7170331..beb8a583 100644 --- a/README.md +++ b/README.md @@ -91,8 +91,12 @@ class LocationSearchInput extends React.Component {
{suggestions.map(suggestion => { const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item'; + // inline style for demonstration purpose + const style = suggestion.active + ? { backgroundColor: '#fafafa', cursor: 'pointer' } + : { backgroundColor: '#ffffff', cursor: 'pointer' }; return ( -
+
{suggestion.description}
) From d1cbc5ebf3589f525527f1ca24d6f928ae62220e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 8 Apr 2018 11:34:07 +0900 Subject: [PATCH 141/165] Update demo SearchBar component --- demo/components/SearchBar.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index ce231258..2e019e36 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -7,9 +7,12 @@ class SearchBar extends React.Component { this.state = { address: '', }; - this.handleChange = address => this.setState({ address }); } + handleChange = address => { + this.setState({ address }); + }; + handleSelect = selected => { /* eslint-disable no-console */ console.log('selected', selected); @@ -21,10 +24,9 @@ class SearchBar extends React.Component { /* eslint-enable no-console */ }; - handleCloseClick = (e) => { - console.log(e); + handleCloseClick = () => { this.setState({ address: '' }); - } + }; render() { return ( @@ -51,7 +53,9 @@ class SearchBar extends React.Component { + > + x + )}
From ac81e781aa24255d86d0aca3cfc9b51d299a6651 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 8 Apr 2018 13:51:48 +0900 Subject: [PATCH 142/165] Update readme --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index beb8a583..c96b2951 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ [![travis build](https://img.shields.io/travis/kenny-hibino/react-places-autocomplete.svg?style=flat-square)](https://travis-ci.org/kenny-hibino/react-places-autocomplete) [![MIT-License](https://img.shields.io/npm/l/react-places-autocomplete.svg?style=flat-square)]() [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/react-places-autocomplete/Lobby) -[![Open Source Helpers](https://www.codetriage.com/kenny-hibino/react-places-autocomplete/badges/users.svg)](https://www.codetriage.com/kenny-hibino/react-places-autocomplete) # React Places Autocomplete @@ -245,20 +244,19 @@ An example of a suggestion object. ### onSelect -Type: `Function` +Type: `function` Required: `false`, Default: `null` You can pass a function that gets called instead of `onChange` function when user -hits the Enter key or clicks on an autocomplete item. +hits the Enter key or clicks on a suggestion item. The function takes two positional arguments. First argument is `address`, second is `placeId`. ```js -const handleSelect = (address, placeId) => { - this.setState({ address, placeId }) - - // You can do other things with address string or placeId. For example, geocode :) +// NOTE: `placeId` is null when user hits Enter key with no suggestion item selected. +const handleSelect = (address: string, placeId: ?string) => { + // Do something with address and placeId } // Pass this function via onSelect prop. @@ -273,7 +271,7 @@ const handleSelect = (address, placeId) => { ### onError -Type: `Function` +Type: `function` Required: `false` You can pass `onError` prop to customize the behavior when [google.maps.places.PlacesServiceStatus](https://developers.google.com/maps/documentation/javascript/places#place_details_responses) is not `OK` (e.g., no predictions are found) @@ -327,7 +325,7 @@ const searchOptions = { ### debounce -Type: `Number` +Type: `number` Required: `false` Default: `200` From 2cc448df3a5968959cfaa616a23af9ca3a03cec3 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 12 Apr 2018 11:35:46 +0900 Subject: [PATCH 143/165] Update demo SearchBar component --- demo/app.css | 20 +++- demo/components/SearchBar.js | 174 +++++++++++++++++++++++------------ 2 files changed, 129 insertions(+), 65 deletions(-) diff --git a/demo/app.css b/demo/app.css index c2ae20f9..646e12fd 100644 --- a/demo/app.css +++ b/demo/app.css @@ -13,11 +13,6 @@ body, #root, .page-wrapper { background-color: #fcfcfc; } -.btn:hover { - background-color: #e53935; - border-color: #e53935; -} - .Demo__github-icon { font-size: 24px; } @@ -41,6 +36,12 @@ body, #root, .page-wrapper { color: #e53935; } +.Demo__search-bar-container { + width: 90%; + max-width: 500px; + margin: 40px auto 0; +} + .Demo__search-input-container { position: relative; } @@ -108,6 +109,15 @@ body, #root, .page-wrapper { font-size: 30px; } +.Demo__error-message { + color: red; +} + +.Demo__geocode-result-header { + font-size: 20px; + color: #222222; +} + @media (max-width: 480px) { .autocomplete-container { text-align: left; diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 2e019e36..1336af24 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,89 +1,143 @@ import React from 'react'; -import PlacesAutocomplete, { geocodeByAddress } from '../../src'; +import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src'; class SearchBar extends React.Component { constructor(props) { super(props); this.state = { address: '', + errorMessage: '', + latitude: null, + longitude: null, + isGeocoding: false, }; } handleChange = address => { - this.setState({ address }); + this.setState({ + address, + latitude: null, + longitude: null, + errorMessage: '', + }); }; handleSelect = selected => { - /* eslint-disable no-console */ - console.log('selected', selected); + this.setState({ isGeocoding: true }); geocodeByAddress(selected) - .then(res => console.log('res', JSON.stringify(res))) + .then(res => getLatLng(res[0])) + .then(({ lat, lng }) => { + this.setState({ + latitude: lat, + longitude: lng, + isGeocoding: false, + }); + }) .catch(error => { - console.log('error', error); + this.setState({ isGeocoding: false }); + console.log('error', error); // eslint-disable-line no-console }); - /* eslint-enable no-console */ }; handleCloseClick = () => { - this.setState({ address: '' }); + this.setState({ + address: '', + latitude: null, + longitude: null + }); }; + handleError = (status, clearSuggestions) => { + console.log('Error from Google Maps API', status); // eslint-disable-line no-console + this.setState({ errorMessage: status }, () => { + clearSuggestions(); + }); + } + render() { + const { address, errorMessage, latitude, longitude, isGeocoding } = this.state; + return ( - {}} - searchOptions={{}} - debounce={300} - shouldFetchSuggestions={this.state.address.length > 3} - > - {({ getInputProps, suggestions, getSuggestionItemProps }) => { - return ( -
-
- - {this.state.address.length > 0 && ( - - )} -
-
- {suggestions.map( - suggestion => ( - /* eslint-disable react/jsx-key */ -
+ 2} + > + {({ getInputProps, suggestions, getSuggestionItemProps }) => { + return ( +
+
+ + {this.state.address.length > 0 && ( +
- ) - /* eslint-enable react/jsx-key */ - )} + x + + )} +
+
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ {suggestion.formattedSuggestion.mainText}{' '} + + {suggestion.formattedSuggestion.secondaryText} + +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+ +
+ ); + }} + + {errorMessage.length > 0 && ( +
+ {this.state.errorMessage} +
+ )} + + {((latitude && longitude) || (isGeocoding)) && ( +
+

Geocode result

+ {isGeocoding ? ( +
+ +
+ ) : ( +
+
+ {latitude} +
+
+ {longitude} +
-
- ); - }} - + )} +
+ )} +
); } } From c22c3b8ce422bedb7a20f835c018030d741f688d Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Fri, 13 Apr 2018 10:10:44 +0900 Subject: [PATCH 144/165] Run prettier --- demo/components/SearchBar.js | 29 ++++++++++++++++++----------- src/tests/helpers/testHelpers.js | 10 ++-------- src/tests/onSelectProp.test.js | 16 ++++++++++++---- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 1336af24..d7890ce0 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -43,7 +43,7 @@ class SearchBar extends React.Component { this.setState({ address: '', latitude: null, - longitude: null + longitude: null, }); }; @@ -52,10 +52,16 @@ class SearchBar extends React.Component { this.setState({ errorMessage: status }, () => { clearSuggestions(); }); - } + }; render() { - const { address, errorMessage, latitude, longitude, isGeocoding } = this.state; + const { + address, + errorMessage, + latitude, + longitude, + isGeocoding, + } = this.state; return (
@@ -98,7 +104,9 @@ class SearchBar extends React.Component { }`, })} > - {suggestion.formattedSuggestion.mainText}{' '} + + {suggestion.formattedSuggestion.mainText} + {' '} {suggestion.formattedSuggestion.secondaryText} @@ -107,18 +115,15 @@ class SearchBar extends React.Component { /* eslint-enable react/jsx-key */ )}
-
); }} {errorMessage.length > 0 && ( -
- {this.state.errorMessage} -
+
{this.state.errorMessage}
)} - {((latitude && longitude) || (isGeocoding)) && ( + {((latitude && longitude) || isGeocoding) && (

Geocode result

{isGeocoding ? ( @@ -128,10 +133,12 @@ class SearchBar extends React.Component { ) : (
- {latitude} + + {latitude}
- {longitude} + + {longitude}
)} diff --git a/src/tests/helpers/testHelpers.js b/src/tests/helpers/testHelpers.js index 71265562..467dee53 100644 --- a/src/tests/helpers/testHelpers.js +++ b/src/tests/helpers/testHelpers.js @@ -58,8 +58,7 @@ export const mockSuggestions = [ }, { active: false, - description: - "San Francisco Int'l Airport Station, San Francisco, CA, USA", + description: "San Francisco Int'l Airport Station, San Francisco, CA, USA", id: 'fd59fa62088bda5c2747abbae2614bd7f6525154', index: 3, placeId: 'ChIJVVVVVYx3j4ARyN7qnq2JceQ', @@ -74,12 +73,7 @@ export const mockSuggestions = [ { offset: 52, value: 'CA' }, { offset: 56, value: 'USA' }, ], - types: [ - 'transit_station', - 'point_of_interest', - 'establishment', - 'geocode', - ], + types: ['transit_station', 'point_of_interest', 'establishment', 'geocode'], }, { active: false, diff --git a/src/tests/onSelectProp.test.js b/src/tests/onSelectProp.test.js index 71ea6002..d0380226 100644 --- a/src/tests/onSelectProp.test.js +++ b/src/tests/onSelectProp.test.js @@ -44,7 +44,10 @@ describe('onSelect prop', () => { input.simulate('keydown', { key: 'ArrowDown' }); // index 0 active input.simulate('keydown', { key: 'Enter' }); expect(onSelectHandler).toHaveBeenCalledTimes(1); - expect(onSelectHandler).toBeCalledWith(mockSuggestions[0].description, mockSuggestions[0].placeId); + expect(onSelectHandler).toBeCalledWith( + mockSuggestions[0].description, + mockSuggestions[0].placeId + ); }); test('pressing Enter when mouse hovers over one of the suggestion items', () => { @@ -54,11 +57,16 @@ describe('onSelect prop', () => { }); simulateSearch(wrapper); - const suggestionItem = wrapper.find('[data-test="suggestion-item"]').first(); + const suggestionItem = wrapper + .find('[data-test="suggestion-item"]') + .first(); const input = wrapper.find('input'); suggestionItem.simulate('mouseenter'); input.simulate('keydown', { key: 'Enter' }); expect(onSelectHandler).toHaveBeenCalledTimes(1); - expect(onSelectHandler).toBeCalledWith(mockSuggestions[0].description, mockSuggestions[0].placeId); + expect(onSelectHandler).toBeCalledWith( + mockSuggestions[0].description, + mockSuggestions[0].placeId + ); }); -}) +}); From 14bd8506e812b39dbca4310e325038eede9478c4 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sat, 14 Apr 2018 08:09:57 -0700 Subject: [PATCH 145/165] Add footer to dropdown in Demo --- demo/Demo.js | 2 +- demo/app.css | 39 ++++--------------------- demo/components/SearchBar.js | 56 +++++++++++++++++++++--------------- demo/index.html | 2 +- 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index ed878d50..904535a9 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -5,7 +5,7 @@ const Demo = () => (

- react-places-autocomplete + react-places-autocomplete

A React component to build a customized UI for Google Maps Places diff --git a/demo/app.css b/demo/app.css index 646e12fd..7e6a4311 100644 --- a/demo/app.css +++ b/demo/app.css @@ -13,6 +13,10 @@ body, #root, .page-wrapper { background-color: #fcfcfc; } +.Demo__map-maker-icon { + color: #FD6C6C; +} + .Demo__github-icon { font-size: 24px; } @@ -32,10 +36,6 @@ body, #root, .page-wrapper { margin-right: 8px; } -.fa.fa-map-marker.header { - color: #e53935; -} - .Demo__search-bar-container { width: 90%; max-width: 500px; @@ -83,7 +83,7 @@ body, #root, .page-wrapper { } .Demo__suggestion-item { - padding: 6px; + padding: 8px; text-align: left; background-color: #fff; cursor: pointer; @@ -148,32 +148,3 @@ body, #root, .page-wrapper { width: 50%; } } - -.geocoding-results { - text-align: left; -} - -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -@-moz-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -@-webkit-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -@-ms-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} - -@-o-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index d7890ce0..6cc02a8c 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -91,30 +91,40 @@ class SearchBar extends React.Component { )}

-
- {suggestions.map( - suggestion => ( - /* eslint-disable react/jsx-key */ -
- - {suggestion.formattedSuggestion.mainText} - {' '} - - {suggestion.formattedSuggestion.secondaryText} - + {suggestions.length > 0 && ( +
+ {suggestions.map( + suggestion => ( + /* eslint-disable react/jsx-key */ +
+ + {suggestion.formattedSuggestion.mainText} + {' '} + + {suggestion.formattedSuggestion.secondaryText} + +
+ ) + /* eslint-enable react/jsx-key */ + )} +
+
+
- ) - /* eslint-enable react/jsx-key */ - )} -
+
+
+ )}
); }} diff --git a/demo/index.html b/demo/index.html index c26ef979..ff5c36f6 100644 --- a/demo/index.html +++ b/demo/index.html @@ -13,7 +13,7 @@ - Fork me on GitHub +
From 6628ce3bae5ee76c8b10ab2e07b0fe83d003c558 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 15 Apr 2018 18:53:16 -0700 Subject: [PATCH 146/165] Add prepublish script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 39c17a2f..c18b71a5 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "demo:test": "mocha demo/tests/index.spec.js --compilers js:babel-register", "demo:build": "rimraf demo/dist && webpack --config demo/webpack.config.js -p", "demo:deploy": "gh-pages -d demo/dist", + "prepublish": "npm run build", "postpublish": "npm run demo:deploy", "prettier": "prettier --write \"src/**/*.js\" \"demo/**/*.js\"", "lint": "eslint .", From 3ddbedb8f19cc5543cefa42fac7674e465fac793 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 15 Apr 2018 19:01:28 -0700 Subject: [PATCH 147/165] v7.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c18b71a5..b6ffd0ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "6.1.3", + "version": "7.0.0", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From dab7533b643a6b9f15f7af30e1f4be8966f80e69 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 15 Apr 2018 19:28:14 -0700 Subject: [PATCH 148/165] Run prettier --- demo/Demo.js | 3 ++- src/PlacesAutocomplete.js | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/demo/Demo.js b/demo/Demo.js index 904535a9..498c80ad 100644 --- a/demo/Demo.js +++ b/demo/Demo.js @@ -5,7 +5,8 @@ const Demo = () => (

- react-places-autocomplete + react-places-autocomplete{' '} +

A React component to build a customized UI for Google Maps Places diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 0da31baa..7f6e403e 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -255,8 +255,6 @@ class PlacesAutocomplete extends React.Component { }; getSuggestionItemProps = (suggestion, options = {}) => { - // TODO: whitelist options OR allow all options and compose - // event handlers return { ...options, key: suggestion.id, From 4f9d628e7cc918457312e73114c41ef7a3af2073 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 16 Apr 2018 07:15:30 -0700 Subject: [PATCH 149/165] Add classnames helper to demo --- demo/components/SearchBar.js | 42 +++++++++++++++++++----------------- demo/helpers.js | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 demo/helpers.js diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 6cc02a8c..92a938cc 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -1,5 +1,6 @@ import React from 'react'; import PlacesAutocomplete, { geocodeByAddress, getLatLng } from '../../src'; +import { classnames } from '../helpers'; class SearchBar extends React.Component { constructor(props) { @@ -94,26 +95,27 @@ class SearchBar extends React.Component { {suggestions.length > 0 && (

{suggestions.map( - suggestion => ( - /* eslint-disable react/jsx-key */ -
- - {suggestion.formattedSuggestion.mainText} - {' '} - - {suggestion.formattedSuggestion.secondaryText} - -
- ) - /* eslint-enable react/jsx-key */ + suggestion => { + const className = classnames( + 'Demo__suggestion-item', + { 'Demo__suggestion-item--active': suggestion.active } + ); + + return ( + /* eslint-disable react/jsx-key */ +
+ + {suggestion.formattedSuggestion.mainText} + {' '} + + {suggestion.formattedSuggestion.secondaryText} + +
+ ) + /* eslint-enable react/jsx-key */ + } )}
diff --git a/demo/helpers.js b/demo/helpers.js new file mode 100644 index 00000000..9bcefb71 --- /dev/null +++ b/demo/helpers.js @@ -0,0 +1,22 @@ +const isObject = (val) => { + return typeof val === 'object' && val !== null; +}; + +export const classnames = (...args) => { + const classes = []; + args.forEach((arg) => { + if (typeof arg === 'string') { + classes.push(arg); + } else if (isObject(arg)) { + Object.keys(arg).forEach((key) => { + if (arg[key]) { + classes.push(key); + } + }); + } else { + throw new Error('`classnames` only accepts string or object as arguments'); + } + }); + + return classes.join(' '); +}; From 2a6550f7f97ad40e79878688d574770b625d8c35 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 16 Apr 2018 07:25:33 -0700 Subject: [PATCH 150/165] Compose event handler functions in suggestion item --- demo/components/SearchBar.js | 41 +++++++++++++++++------------------- demo/helpers.js | 10 +++++---- src/PlacesAutocomplete.js | 30 ++++++++++++++++++-------- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index 92a938cc..c2084a75 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -94,29 +94,26 @@ class SearchBar extends React.Component {
{suggestions.length > 0 && (
- {suggestions.map( - suggestion => { - const className = classnames( - 'Demo__suggestion-item', - { 'Demo__suggestion-item--active': suggestion.active } - ); + {suggestions.map(suggestion => { + const className = classnames('Demo__suggestion-item', { + 'Demo__suggestion-item--active': suggestion.active, + }); - return ( - /* eslint-disable react/jsx-key */ -
- - {suggestion.formattedSuggestion.mainText} - {' '} - - {suggestion.formattedSuggestion.secondaryText} - -
- ) - /* eslint-enable react/jsx-key */ - } - )} + return ( + /* eslint-disable react/jsx-key */ +
+ + {suggestion.formattedSuggestion.mainText} + {' '} + + {suggestion.formattedSuggestion.secondaryText} + +
+ ); + /* eslint-enable react/jsx-key */ + })}
{ +const isObject = val => { return typeof val === 'object' && val !== null; }; export const classnames = (...args) => { const classes = []; - args.forEach((arg) => { + args.forEach(arg => { if (typeof arg === 'string') { classes.push(arg); } else if (isObject(arg)) { - Object.keys(arg).forEach((key) => { + Object.keys(arg).forEach(key => { if (arg[key]) { classes.push(key); } }); } else { - throw new Error('`classnames` only accepts string or object as arguments'); + throw new Error( + '`classnames` only accepts string or object as arguments' + ); } }); diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 7f6e403e..00f75330 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -255,21 +255,33 @@ class PlacesAutocomplete extends React.Component { }; getSuggestionItemProps = (suggestion, options = {}) => { + const handleSuggestionMouseEnter = this.handleSuggestionMouseEnter.bind( + this, + suggestion.index + ); + const handleSuggestionClick = this.handleSuggestionClick.bind( + this, + suggestion + ); + return { ...options, key: suggestion.id, id: this.getActiveSuggestionId(), role: 'option', - onMouseEnter: this.handleSuggestionMouseEnter.bind( - this, - suggestion.index + onMouseEnter: compose(handleSuggestionMouseEnter, options.onMouseEnter), + onMouseLeave: compose( + this.handleSuggestionMouseLeave, + options.onMouseLeave + ), + onMouseDown: compose(this.handleSuggestionMouseDown, options.onMouseDown), + onMouseUp: compose(this.handleSuggestionMouseUp, options.onMouseUp), + onTouchStart: compose( + this.handleSuggestionTouchStart, + options.onTouchStart ), - onMouseLeave: this.handleSuggestionMouseLeave, - onMouseDown: this.handleSuggestionMouseDown, - onMouseUp: this.handleSuggestionMouseUp, - onTouchStart: this.handleSuggestionTouchStart, - onTouchEnd: this.handleSuggestionMouseUp, - onClick: this.handleSuggestionClick.bind(this, suggestion), + onTouchEnd: compose(this.handleSuggestionMouseUp, options.onTouchEnd), + onClick: compose(handleSuggestionClick, options.onClick), }; }; From cca5f044ee4f951838255bfff79d3b2fea23e336 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Mon, 16 Apr 2018 07:42:02 -0700 Subject: [PATCH 151/165] v7.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b6ffd0ca..75230e33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "7.0.0", + "version": "7.0.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From e111669ebcc3caa67a9dcf3823357333a0e1a335 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 24 Apr 2018 07:40:02 -0700 Subject: [PATCH 152/165] Add googleCallbackName prop to enable async mode --- README.md | 30 +++++++++++++++++ src/PlacesAutocomplete.js | 32 ++++++++++++++++++- .../__snapshots__/initialRender.test.js.snap | 3 ++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c96b2951..c8786a67 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib 3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form) 4. Mobile friendly UX 5. WAI-ARIA compliant +6. Support Asynchronous Google script loading ### Installation To install the stable version @@ -124,6 +125,8 @@ PlacesAutocomplete is a [Controlled Component](https://facebook.github.io/react/ |[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | | [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | |[`shouldFetchSuggestions`](#shouldFetchSuggestions)| boolean | | Component will hit Google Maps API only if this flag is set `true` | +|[`googleCallbackName`](#googleCallbackName)| string | | You can provide a callback name to initialize `PlacesAutocomplete` after google script is loaded | + ### value @@ -356,6 +359,33 @@ Default: `true` ``` + +### googleCallbackName +Type: `string` +Required: `false` +Default: `undefined` + +If provided, component will initialize after the browser has finished downloading google script. + +**IMPORTANT**: To enable this async mode, you need to provide the same callback name to google script via `callback=[YOUR CALLBACK NAME]`. + +Example: +```html + +``` + +Then, provide `googleCallbackName` prop to `PlacesAutocomplete`. + +```js + + {/* custom render function */} + +``` + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 00f75330..906d55f9 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -22,6 +22,7 @@ class PlacesAutocomplete extends React.Component { this.state = { suggestions: [], userInputValue: props.value, + ready: !props.googleCallbackName, }; this.debouncedFetchPredictions = debounce( @@ -31,6 +32,26 @@ class PlacesAutocomplete extends React.Component { } componentDidMount() { + const { googleCallbackName } = this.props; + if (googleCallbackName) { + if (!window.google) { + window[googleCallbackName] = this.init; + } else { + this.init(); + } + } else { + this.init(); + } + } + + componentWillUnmount() { + const { googleCallbackName } = this.props; + if (googleCallbackName && window[googleCallbackName]) { + delete window[googleCallbackName]; + } + } + + init = () => { if (!window.google) { throw new Error( '[react-places-autocomplete]: Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library' @@ -45,7 +66,14 @@ class PlacesAutocomplete extends React.Component { this.autocompleteService = new window.google.maps.places.AutocompleteService(); this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK; - } + this.setState(state => { + if (state.ready) { + return null; + } else { + return { ready: true }; + } + }); + }; autocompleteCallback = (predictions, status) => { if (status !== this.autocompleteOK) { @@ -240,6 +268,7 @@ class PlacesAutocomplete extends React.Component { 'aria-autocomplete': 'list', 'aria-expanded': this.getIsExpanded(), 'aria-activedescendant': this.getActiveSuggestionId(), + disabled: !this.state.ready, }; return { @@ -344,6 +373,7 @@ PlacesAutocomplete.propTypes = { debounce: PropTypes.number, highlightFirstSuggestion: PropTypes.bool, shouldFetchSuggestions: PropTypes.bool, + googleCallbackName: PropTypes.string, }; PlacesAutocomplete.defaultProps = { diff --git a/src/tests/__snapshots__/initialRender.test.js.snap b/src/tests/__snapshots__/initialRender.test.js.snap index 99470dd8..e42f4aaf 100644 --- a/src/tests/__snapshots__/initialRender.test.js.snap +++ b/src/tests/__snapshots__/initialRender.test.js.snap @@ -16,6 +16,7 @@ exports[`initial render 1`] = ` aria-autocomplete="list" aria-expanded={false} autoComplete="off" + disabled={false} onBlur={[Function]} onChange={[Function]} onKeyDown={[Function]} @@ -44,6 +45,7 @@ exports[`initial render with initial input value 1`] = ` aria-autocomplete="list" aria-expanded={false} autoComplete="off" + disabled={false} onBlur={[Function]} onChange={[Function]} onKeyDown={[Function]} @@ -73,6 +75,7 @@ exports[`initial render with options to props-getter 1`] = ` aria-expanded={false} autoComplete="off" className="my-input-classname" + disabled={false} onBlur={[Function]} onChange={[Function]} onKeyDown={[Function]} From 00bb41f8771a04c17505246c66a954d0d95b3714 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 26 Apr 2018 07:32:36 -0700 Subject: [PATCH 153/165] Update readme --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index c8786a67..2bd469d8 100644 --- a/README.md +++ b/README.md @@ -386,6 +386,40 @@ Then, provide `googleCallbackName` prop to `PlacesAutocomplete`. ``` +**NOTE**: If there are more than one `PlacesAutocomplete` components rendered in the page, +set up a callback function that calls a callback function for each component. + +Example: +```html + + +``` + +```js + + {/* custom render function */} + + + + {/* custom render function */} + + +``` + ## Utility Functions * [`geocodeByAddress`](#geocode-by-address) From 85ca2a52bbd252cab4128ce47a07097cac4f119e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Thu, 26 Apr 2018 07:39:49 -0700 Subject: [PATCH 154/165] v7.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75230e33..176f212f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "7.0.1", + "version": "7.1.1", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From 40fa9bbbef29d73a9f428d6105083382880017cd Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 27 May 2018 12:35:20 -0700 Subject: [PATCH 155/165] Fix handler for select event --- src/PlacesAutocomplete.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 906d55f9..7acda42d 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -124,8 +124,11 @@ class PlacesAutocomplete extends React.Component { handleSelect = (address, placeId) => { this.clearSuggestions(); - this.props.onChange(address); - this.props.onSelect && this.props.onSelect(address, placeId); + if (this.props.onSelect) { + this.props.onSelect(address, placeId); + } else { + this.props.onChange(address); + } }; getActiveSuggestion = () => { From 62747988907be70b044d7fe7fe1b59132560ad96 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 27 May 2018 12:36:17 -0700 Subject: [PATCH 156/165] Fix demo app's select handler function --- demo/components/SearchBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/components/SearchBar.js b/demo/components/SearchBar.js index c2084a75..95c5041f 100644 --- a/demo/components/SearchBar.js +++ b/demo/components/SearchBar.js @@ -24,7 +24,7 @@ class SearchBar extends React.Component { }; handleSelect = selected => { - this.setState({ isGeocoding: true }); + this.setState({ isGeocoding: true, address: selected }); geocodeByAddress(selected) .then(res => getLatLng(res[0])) .then(({ lat, lng }) => { From b053aaf76e445c854f3a6dd0d6170067e70fe22e Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Sun, 27 May 2018 12:44:27 -0700 Subject: [PATCH 157/165] v7.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 176f212f..4dd9b19f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-places-autocomplete", - "version": "7.1.1", + "version": "7.1.2", "description": "A React component for Google Maps Places Autocomplete", "main": "dist/index.js", "scripts": { From bb6d3f8d2e7ce45af2582676f7dfc7eb80cab37a Mon Sep 17 00:00:00 2001 From: Christie Williams Date: Thu, 7 Jun 2018 13:16:47 -0400 Subject: [PATCH 158/165] Fixup --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2bd469d8..20986234 100644 --- a/README.md +++ b/README.md @@ -202,8 +202,8 @@ autocomplete dropdown. You MUST call it with `suggestion` object as an argument, // Simple example
{suggestions.map(suggestion => ( -
- {suggesion.description} +
+ {suggestion.description}
))}
@@ -211,7 +211,7 @@ autocomplete dropdown. You MUST call it with `suggestion` object as an argument, // Pass options as a second argument
{suggestions.map(suggestion => { - const className = suggestion.active ? 'suggestion-item--active' : 'suggesion-item'; + const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item'; return (
{suggestion.description} From f25dcc7447476c849723717fe2bb56d9c34eac03 Mon Sep 17 00:00:00 2001 From: Jarrod Ruhland Date: Wed, 20 Jun 2018 14:16:22 -0700 Subject: [PATCH 159/165] add loading property to render prop * Bump to version 7.2.0 * Add loading to internal state * Expose loading status to render prop * Add hooks for modifying loading status Exposing loading status to render so that users can easily add spinners/etc during loading --- src/PlacesAutocomplete.js | 4 ++++ src/tests/helpers/setup.js | 8 +++++++- src/tests/loading.test.js | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/tests/loading.test.js diff --git a/src/PlacesAutocomplete.js b/src/PlacesAutocomplete.js index 7acda42d..57463a55 100644 --- a/src/PlacesAutocomplete.js +++ b/src/PlacesAutocomplete.js @@ -20,6 +20,7 @@ class PlacesAutocomplete extends React.Component { super(props); this.state = { + loading: false, suggestions: [], userInputValue: props.value, ready: !props.googleCallbackName, @@ -76,6 +77,7 @@ class PlacesAutocomplete extends React.Component { }; autocompleteCallback = (predictions, status) => { + this.setState({ loading: false }); if (status !== this.autocompleteOK) { this.props.onError(status, this.clearSuggestions); return; @@ -99,6 +101,7 @@ class PlacesAutocomplete extends React.Component { fetchPredictions = () => { const { value } = this.props; if (value.length) { + this.setState({ loading: true }); this.autocompleteService.getPlacePredictions( { ...this.props.searchOptions, @@ -354,6 +357,7 @@ class PlacesAutocomplete extends React.Component { return this.props.children({ getInputProps: this.getInputProps, getSuggestionItemProps: this.getSuggestionItemProps, + loading: this.state.loading, suggestions: this.state.suggestions, }); } diff --git a/src/tests/helpers/setup.js b/src/tests/helpers/setup.js index d3416490..be36de30 100644 --- a/src/tests/helpers/setup.js +++ b/src/tests/helpers/setup.js @@ -31,12 +31,18 @@ class GeocoderMock { } } +class AutocompleteServiceMock { + getPlacePredictions(_filters, callback) { + callback([], 'OK'); + } +} + export const setupGoogleMock = () => { /*** Mock Google Maps JavaScript API ***/ const google = { maps: { places: { - AutocompleteService: () => {}, + AutocompleteService: AutocompleteServiceMock, PlacesServiceStatus: { INVALID_REQUEST: 'INVALID_REQUEST', NOT_FOUND: 'NOT_FOUND', diff --git a/src/tests/loading.test.js b/src/tests/loading.test.js new file mode 100644 index 00000000..d5df1be7 --- /dev/null +++ b/src/tests/loading.test.js @@ -0,0 +1,40 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import PlacesAutocomplete from '../index'; +import { setupGoogleMock } from './helpers/setup'; + +beforeAll(() => { + setupGoogleMock(); +}); + +test('loading prop check', () => { + const childProp = jest.fn(); + childProp.mockReturnValue( +
+ + Test Render +
+ ); + const component = mount( + {}} + onSelect={() => {}} + shouldFetchSuggestions={true} + value="test" + > + {childProp} + + ); + + // simulate fetching predictions + const el = component.find(PlacesAutocomplete); + el.instance().fetchPredictions(); + + // there are 2 setStates in the callback, so we end up with 4 renders + expect(childProp).toHaveBeenCalledTimes(4); + const expected = [false, true, false, false]; + childProp.mock.calls.forEach((call, i) => { + expect(call[0]).toMatchObject({ loading: expected[i] }); + }); +}); From 830457b959a9cc553b86412fecc4d44e4caa7427 Mon Sep 17 00:00:00 2001 From: Jarrod Ruhland Date: Tue, 26 Jun 2018 09:57:50 -0700 Subject: [PATCH 160/165] update README.md with loading prop --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 20986234..8a0aedcb 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib ### Features 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) 2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) -3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form) +3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form) 4. Mobile friendly UX 5. WAI-ARIA compliant 6. Support Asynchronous Google script loading @@ -58,7 +58,7 @@ import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-au class LocationSearchInput extends React.Component { constructor(props) { - super(props); + super(props); this.state = { address: '' } } @@ -80,7 +80,7 @@ class LocationSearchInput extends React.Component { onChange={this.handleChange} onSelect={this.handleSelect} > - {({ getInputProps, suggestions, getSuggestionItemProps }) => ( + {({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
+ { loading &&
Loading...
} {suggestions.map(suggestion => { const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item'; // inline style for demonstration purpose @@ -159,6 +160,7 @@ This is where you render whatever you want to based on the state of `PlacesAutoc The function will take an object with the following keys. - `getInputProps` : function - `getSuggestionItemProps` : function +- `loading` : boolean - `suggestions` : array Simple example @@ -167,10 +169,11 @@ const renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions }) => (
+ {loading &&
Loading...
} {suggestions.map(suggestion => (
{suggestion.description} -
+
))}
@@ -222,6 +225,9 @@ autocomplete dropdown. You MUST call it with `suggestion` object as an argument, ``` +#### loading +This is a boolean flag indicating whether or not the request is pending, or has completed. + #### suggestions This is an array of suggestion objects each containing all the data from Google Maps API and other metadata. From ee2c2ed2254639a39e06090ac358b517766c19fd Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Tue, 26 Jun 2018 10:05:53 -0700 Subject: [PATCH 161/165] Fix readme link --- README.md | 166 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 8a0aedcb..e5a89dc2 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,16 @@ [![MIT-License](https://img.shields.io/npm/l/react-places-autocomplete.svg?style=flat-square)]() [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/react-places-autocomplete/Lobby) - # React Places Autocomplete A React component to build a customized UI for Google Maps Places Autocomplete - ### Demo -Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hibino.github.io/react-places-autocomplete/) +Live demo: [hibiken.github.io/react-places-autocomplete/](https://hibiken.github.io/react-places-autocomplete/) ### Features + 1. Enable you to easily build a customized autocomplete dropdown powered by [Google Maps Places Library](https://developers.google.com/maps/documentation/javascript/places) 2. [Utility functions](#utility-functions) to geocode and get latitude and longitude using [Google Maps Geocoder API](https://developers.google.com/maps/documentation/javascript/geocoding) 3. Full control over rendering to integrate well with other libraries (e.g. Redux-Form) @@ -21,6 +20,7 @@ Live demo: [kenny-hibino.github.io/react-places-autocomplete/](https://kenny-hib 6. Support Asynchronous Google script loading ### Installation + To install the stable version ```sh @@ -30,17 +30,21 @@ npm install --save react-places-autocomplete React component is exported as a default export ```js -import PlacesAutocomplete from 'react-places-autocomplete' +import PlacesAutocomplete from 'react-places-autocomplete'; ``` utility functions are named exports ```js -import { geocodeByAddress, geocodeByPlaceId, getLatLng } from 'react-places-autocomplete' +import { + geocodeByAddress, + geocodeByPlaceId, + getLatLng, +} from 'react-places-autocomplete'; ``` - ### Getting Started + To use this component, you are going to need to load [Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript/) @@ -53,25 +57,28 @@ Load the library in your project Create your component ```js -import React from 'react' -import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete' +import React from 'react'; +import PlacesAutocomplete, { + geocodeByAddress, + getLatLng, +} from 'react-places-autocomplete'; class LocationSearchInput extends React.Component { constructor(props) { super(props); - this.state = { address: '' } + this.state = { address: '' }; } - handleChange = (address) => { - this.setState({ address }) - } + handleChange = address => { + this.setState({ address }); + }; - handleSelect = (address) => { + handleSelect = address => { geocodeByAddress(address) .then(results => getLatLng(results[0])) .then(latLng => console.log('Success', latLng)) - .catch(error => console.error('Error', error)) - } + .catch(error => console.error('Error', error)); + }; render() { return ( @@ -85,22 +92,29 @@ class LocationSearchInput extends React.Component {
- { loading &&
Loading...
} + {loading &&
Loading...
} {suggestions.map(suggestion => { - const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item'; + const className = suggestion.active + ? 'suggestion-item--active' + : 'suggestion-item'; // inline style for demonstration purpose const style = suggestion.active - ? { backgroundColor: '#fafafa', cursor: 'pointer' } - : { backgroundColor: '#ffffff', cursor: 'pointer' }; + ? { backgroundColor: '#fafafa', cursor: 'pointer' } + : { backgroundColor: '#ffffff', cursor: 'pointer' }; return ( -
+
{suggestion.description}
- ) + ); })}
@@ -115,28 +129,30 @@ class LocationSearchInput extends React.Component { PlacesAutocomplete is a [Controlled Component](https://facebook.github.io/react/docs/forms.html#controlled-components) with a [Render Prop](https://reactjs.org/docs/render-props.html). Therefore, you MUST pass at least `value` and `onChange` callback to the input element, and render function via `children`. -| Prop | Type | Required | Description | -| ------------- |:-------------:| :-----: |-------| -| [`value`](#value) | string | :white_check_mark: | `value` for the input element | -| [`onChange`](#onChange) | function | :white_check_mark: | `onChange` function for the input element | -| [`children`](#children) | function | :white_check_mark: | Render function to specify the rendering | -| [`onSelect`](#onSelect) | function | | Event handler to handle user's select event | -| [`onError`](#onError) | function | | Error handler function that gets called when Google Maps API responds with an error | -| [`searchOptions`](#searchOptions) | object | | Options to Google Maps API (i.e. bounds, radius) | -|[`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | -| [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | -|[`shouldFetchSuggestions`](#shouldFetchSuggestions)| boolean | | Component will hit Google Maps API only if this flag is set `true` | -|[`googleCallbackName`](#googleCallbackName)| string | | You can provide a callback name to initialize `PlacesAutocomplete` after google script is loaded | - +| Prop | Type | Required | Description | +| ------------------------------------------------------- | :------: | :----------------: | ------------------------------------------------------------------------------------------------ | +| [`value`](#value) | string | :white_check_mark: | `value` for the input element | +| [`onChange`](#onChange) | function | :white_check_mark: | `onChange` function for the input element | +| [`children`](#children) | function | :white_check_mark: | Render function to specify the rendering | +| [`onSelect`](#onSelect) | function | | Event handler to handle user's select event | +| [`onError`](#onError) | function | | Error handler function that gets called when Google Maps API responds with an error | +| [`searchOptions`](#searchOptions) | object | | Options to Google Maps API (i.e. bounds, radius) | +| [`debounce`](#debounce) | number | | Number of milliseconds to delay before making a call to Google Maps API | +| [`highlightFirstSuggestion`](#highlightFirstSuggestion) | boolean | | If set to `true`, first list item in the dropdown will be automatically highlighted | +| [`shouldFetchSuggestions`](#shouldFetchSuggestions) | boolean | | Component will hit Google Maps API only if this flag is set `true` | +| [`googleCallbackName`](#googleCallbackName) | string | | You can provide a callback name to initialize `PlacesAutocomplete` after google script is loaded | + ### value + Type: `string`, Required: `true` - + ### onChange + Type: `function`, Required: `true` @@ -152,18 +168,22 @@ Typically this event handler will update `value` state. ``` + ### children + Type: `function` Required: `true` This is where you render whatever you want to based on the state of `PlacesAutocomplete`. The function will take an object with the following keys. -- `getInputProps` : function -- `getSuggestionItemProps` : function -- `loading` : boolean -- `suggestions` : array + +* `getInputProps` : function +* `getSuggestionItemProps` : function +* `loading` : boolean +* `suggestions` : array Simple example + ```js const renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions }) => (
@@ -180,15 +200,13 @@ const renderFunc = ({ getInputProps, getSuggestionItemProps, suggestions }) => ( ); // In render function - + {renderFunc} - +; ``` #### getInputProps + This function will return the props that you can spread over the `` element. You can optionally call the function with an object to pass other props to the input. @@ -198,6 +216,7 @@ You can optionally call the function with an object to pass other props to the i ``` #### getSuggestionItemProps + This function will return the props that you can spread over each suggestion item in your autocomplete dropdown. You MUST call it with `suggestion` object as an argument, and optionally pass an object to pass other props to the element. @@ -222,13 +241,14 @@ autocomplete dropdown. You MUST call it with `suggestion` object as an argument, ); })}
- ``` #### loading + This is a boolean flag indicating whether or not the request is pending, or has completed. #### suggestions + This is an array of suggestion objects each containing all the data from Google Maps API and other metadata. An example of a suggestion object. @@ -252,7 +272,9 @@ An example of a suggestion object. ``` + ### onSelect + Type: `function` Required: `false`, Default: `null` @@ -279,7 +301,9 @@ const handleSelect = (address: string, placeId: ?string) => { ``` + ### onError + Type: `function` Required: `false` @@ -303,9 +327,10 @@ const onError = (status, clearSuggestions) => { ``` - + ### searchOptions + Type: `Object` Required: `false` Default: `{}` @@ -333,7 +358,9 @@ const searchOptions = { ``` + ### debounce + Type: `number` Required: `false` Default: `200` @@ -341,7 +368,9 @@ Default: `200` The number of milliseconds to delay before making a call to Google Maps API. + ### highlightFirstSuggestion + Type: `boolean` Required: `false` Default: `false` @@ -349,7 +378,9 @@ Default: `false` If set to `true`, first suggestion in the dropdown will be automatically set to be active. + ### shouldFetchSuggestions + Type: `boolean` Required: `false` Default: `true` @@ -366,7 +397,9 @@ Default: `true` ``` + ### googleCallbackName + Type: `string` Required: `false` Default: `undefined` @@ -376,6 +409,7 @@ If provided, component will initialize after the browser has finished downloadin **IMPORTANT**: To enable this async mode, you need to provide the same callback name to google script via `callback=[YOUR CALLBACK NAME]`. Example: + ```html ``` @@ -396,6 +430,7 @@ Then, provide `googleCallbackName` prop to `PlacesAutocomplete`. set up a callback function that calls a callback function for each component. Example: + ```html