diff --git a/ReactMapboxAutocomplete.js b/ReactMapboxAutocomplete.js index fb8f228..d44f48c 100644 --- a/ReactMapboxAutocomplete.js +++ b/ReactMapboxAutocomplete.js @@ -1,142 +1,153 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { map } from 'lodash'; +import map from 'lodash/map'; import './index.css'; class ReactMapboxAutocomplete extends React.Component { - state = { - error: false, - errorMsg: '', - query: this.props.query ? this.props.query : '', - queryResults: [], - publicKey: this.props.publicKey, - resetSearch: this.props.resetSearch ? this.props.resetSearch : false - } - - _updateQuery = event => { - this.setState({ query: event.target.value }); - const header = { 'Content-Type': 'application/json' }; - let path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + this.state.query + '.json?access_token=' + this.state.publicKey; - - if(this.props.country) { - path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + this.state.query + '.json?access_token=' + this.state.publicKey + '&country=' + this.props.country; + state = { + error: false, + errorMsg: '', + query: this.props.query ? this.props.query : '', + queryResults: [], + publicKey: this.props.publicKey, + resetSearch: this.props.resetSearch ? this.props.resetSearch : false } - if(this.state.query.length > 2) { - return fetch(path, { - headers: header, - }).then(res => { - if (!res.ok) throw Error(res.statusText); - return res.json(); - }).then(json => { - this.setState({ - error: false, - queryResults: json.features - }); - }).catch(err => { - this.setState({ - error: true, - errorMsg: 'There was a problem retrieving data from mapbox', - queryResults: [] + _updateQuery = event => { + this.setState({query: event.target.value}); + const header = {'Content-Type': 'application/json'}; + let path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + this.state.query + '.json?access_token=' + this.state.publicKey; + + if (this.props.country) { + path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + this.state.query + '.json?access_token=' + this.state.publicKey + '&country=' + this.props.country; + } + + this.props.params.forEach(param => { + path += `&${param.type}=${param.value}`; }); - }) - } else { - this.setState({ - error: false, - queryResults: [] - }); + + if (this.state.query.length > 2) { + return fetch(path, { + headers: header, + }).then(res => { + if (!res.ok) throw Error(res.statusText); + return res.json(); + }).then(json => { + this.setState({ + error: false, + queryResults: json.features + }); + }).catch(err => { + this.setState({ + error: true, + errorMsg: 'There was a problem retrieving data from mapbox', + queryResults: [] + }); + }) + } else { + this.setState({ + error: false, + queryResults: [] + }); + } } - } - - _resetSearch = () => { - if(this.state.resetSearch) { - this.setState({ - query: '', - queryResults: [] - }); - } else { - this.setState({ queryResults: [] }); + + _resetSearch = () => { + if (this.state.resetSearch) { + this.setState({ + query: '', + queryResults: [] + }); + } else { + this.setState({queryResults: []}); + } } - } - _onSuggestionSelect = event => { - if(this.state.resetSearch === false) { - this.setState({ query: event.target.getAttribute('data-suggestion') }); + _onSuggestionSelect = event => { + if (this.state.resetSearch === false) { + this.setState({query: event.target.getAttribute('data-suggestion')}); + } + + this.props.onSuggestionSelect( + event.target.getAttribute('data-suggestion'), + event.target.getAttribute('data-lat'), + event.target.getAttribute('data-lng'), + event.target.getAttribute('data-text'), + event.target.getAttribute('data-place') + ) } - this.props.onSuggestionSelect( - event.target.getAttribute('data-suggestion'), - event.target.getAttribute('data-lat'), - event.target.getAttribute('data-lng'), - event.target.getAttribute('data-text') - ) - } - - render() { - return ( -
- - + render() { + return ( +
+ +
0 || this.state.error ? { display: 'block' } - : { display: 'none' }} + style={this.state.queryResults.length > 0 || this.state.error ? {display: 'block'} + : {display: 'none'}} onClick={this._resetSearch}> { - map(this.state.queryResults, (place, i) => { - return( -
- - {place.place_name} - -
- ) - }) + map(this.state.queryResults, (place, i) => { + return ( +
+ + {place.place_name} + +
+ ) + }) } - {this.state.error &&
{this.state.errorMsg}
} + {this.state.error &&
{this.state.errorMsg}
}
-
- ); - } +
+ ); + } } ReactMapboxAutocomplete.defaultProps = { - inputId: null, - inputOnFocus: null, - inputOnBlur: null, - inputOnClick: null + inputId: null, + inputOnFocus: null, + inputOnBlur: null, + inputOnClick: null, + params: [] }; ReactMapboxAutocomplete.propTypes = { - inputId: PropTypes.string, - inputOnFocus: PropTypes.func, - inputOnBlur: PropTypes.func, - inputOnClick: PropTypes.func, - inputClass: PropTypes.string, - publicKey: PropTypes.string.isRequired, - placeholder: PropTypes.string, - onSuggestionSelect: PropTypes.func.isRequired, - country: PropTypes.string, - query: PropTypes.string, - resetSearch: PropTypes.bool + inputId: PropTypes.string, + inputOnFocus: PropTypes.func, + inputOnBlur: PropTypes.func, + inputOnClick: PropTypes.func, + inputClass: PropTypes.string, + publicKey: PropTypes.string.isRequired, + placeholder: PropTypes.string, + onSuggestionSelect: PropTypes.func.isRequired, + country: PropTypes.string, + params: PropTypes.array, // add optional query params, options include: + // [ country, language, limit, reverseMode, routing, types ] + // More info: https://www.mapbox.com/api-documentation/#retrieve-places-near-a-location + // prop type is array of { type, value } objects, where value is consistent with Mapbox API requirements + query: PropTypes.string, + resetSearch: PropTypes.bool } export default ReactMapboxAutocomplete; diff --git a/index.js b/index.js index a4f65e6..dcc0c3a 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ 'use strict'; Object.defineProperty(exports, "__esModule", { - value: true + value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); @@ -14,7 +14,9 @@ var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); -var _lodash = require('lodash'); +var _map = require('lodash/map'); + +var _map2 = _interopRequireDefault(_map); require('./index.css'); @@ -27,148 +29,149 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var ReactMapboxAutocomplete = function (_React$Component) { - _inherits(ReactMapboxAutocomplete, _React$Component); + _inherits(ReactMapboxAutocomplete, _React$Component); - function ReactMapboxAutocomplete() { - var _ref; + function ReactMapboxAutocomplete() { + var _ref; - var _temp, _this, _ret; + var _temp, _this, _ret; - _classCallCheck(this, ReactMapboxAutocomplete); + _classCallCheck(this, ReactMapboxAutocomplete); - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ReactMapboxAutocomplete.__proto__ || Object.getPrototypeOf(ReactMapboxAutocomplete)).call.apply(_ref, [this].concat(args))), _this), _this.state = { - error: false, - errorMsg: '', - query: _this.props.query ? _this.props.query : '', - queryResults: [], - publicKey: _this.props.publicKey, - resetSearch: _this.props.resetSearch ? _this.props.resetSearch : false - }, _this._updateQuery = function (event) { - _this.setState({ query: event.target.value }); - var header = { 'Content-Type': 'application/json' }; - var path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + _this.state.query + '.json?access_token=' + _this.state.publicKey; - - if (_this.props.country) { - path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + _this.state.query + '.json?access_token=' + _this.state.publicKey + '&country=' + _this.props.country; - } - - if (_this.state.query.length > 2) { - return fetch(path, { - headers: header - }).then(function (res) { - if (!res.ok) throw Error(res.statusText); - return res.json(); - }).then(function (json) { - _this.setState({ + return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ReactMapboxAutocomplete.__proto__ || Object.getPrototypeOf(ReactMapboxAutocomplete)).call.apply(_ref, [this].concat(args))), _this), _this.state = { error: false, - queryResults: json.features - }); - }).catch(function (err) { - _this.setState({ - error: true, - errorMsg: 'There was a problem retrieving data from mapbox', - queryResults: [] - }); - }); - } else { - _this.setState({ - error: false, - queryResults: [] - }); - } - }, _this._resetSearch = function () { - if (_this.state.resetSearch) { - _this.setState({ - query: '', - queryResults: [] - }); - } else { - _this.setState({ queryResults: [] }); - } - }, _this._onSuggestionSelect = function (event) { - if (_this.state.resetSearch === false) { - _this.setState({ query: event.target.getAttribute('data-suggestion') }); - } - - _this.props.onSuggestionSelect(event.target.getAttribute('data-suggestion'), event.target.getAttribute('data-lat'), event.target.getAttribute('data-lng'), event.target.getAttribute('data-text')); - }, _temp), _possibleConstructorReturn(_this, _ret); - } - - _createClass(ReactMapboxAutocomplete, [{ - key: 'render', - value: function render() { - var _this2 = this; - - return _react2.default.createElement( - 'div', - null, - _react2.default.createElement('input', { placeholder: this.props.placeholder || 'Search', - id: this.props.inputId, - onClick: this.props.inputOnClick, - onBlur: this.props.inputOnBlur, - onFocus: this.props.inputOnFocus, - className: this.props.inputClass ? this.props.inputClass + ' react-mapbox-ac-input' : 'react-mapbox-ac-input', - onChange: this._updateQuery, - value: this.state.query, - type: 'text' }), - _react2.default.createElement( - 'span', - null, - _react2.default.createElement( - 'div', - { className: 'react-mapbox-ac-menu', - style: this.state.queryResults.length > 0 || this.state.error ? { display: 'block' } : { display: 'none' }, - onClick: this._resetSearch }, - (0, _lodash.map)(this.state.queryResults, function (place, i) { - return _react2.default.createElement( - 'div', - { className: 'react-mapbox-ac-suggestion', - onClick: _this2._onSuggestionSelect, - key: i, - 'data-suggestion': place.place_name, - 'data-lng': place.center[0], - 'data-lat': place.center[1], - 'data-text': place.text }, - place.place_name - ); - }), - this.state.error && _react2.default.createElement( - 'div', - { className: 'react-mapbox-ac-suggestion' }, - this.state.errorMsg - ) - ) - ) - ); + errorMsg: '', + query: _this.props.query ? _this.props.query : '', + queryResults: [], + publicKey: _this.props.publicKey, + resetSearch: _this.props.resetSearch ? _this.props.resetSearch : false + }, _this._updateQuery = function (event) { + _this.setState({ query: event.target.value }); + var header = { 'Content-Type': 'application/json' }; + var path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + _this.state.query + '.json?access_token=' + _this.state.publicKey; + + if (_this.props.country) { + path = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' + _this.state.query + '.json?access_token=' + _this.state.publicKey + '&country=' + _this.props.country; + } + + if (_this.state.query.length > 2) { + return fetch(path, { + headers: header + }).then(function (res) { + if (!res.ok) throw Error(res.statusText); + return res.json(); + }).then(function (json) { + _this.setState({ + error: false, + queryResults: json.features + }); + }).catch(function (err) { + _this.setState({ + error: true, + errorMsg: 'There was a problem retrieving data from mapbox', + queryResults: [] + }); + }); + } else { + _this.setState({ + error: false, + queryResults: [] + }); + } + }, _this._resetSearch = function () { + if (_this.state.resetSearch) { + _this.setState({ + query: '', + queryResults: [] + }); + } else { + _this.setState({ queryResults: [] }); + } + }, _this._onSuggestionSelect = function (event) { + if (_this.state.resetSearch === false) { + _this.setState({ query: event.target.getAttribute('data-suggestion') }); + } + + _this.props.onSuggestionSelect(event.target.getAttribute('data-place'), event.target.getAttribute('data-suggestion'), event.target.getAttribute('data-lat'), event.target.getAttribute('data-lng'), event.target.getAttribute('data-text')); + }, _temp), _possibleConstructorReturn(_this, _ret); } - }]); - return ReactMapboxAutocomplete; + _createClass(ReactMapboxAutocomplete, [{ + key: 'render', + value: function render() { + var _this2 = this; + + return _react2.default.createElement( + 'div', + null, + _react2.default.createElement('input', { placeholder: this.props.placeholder || 'Search', + id: this.props.inputId, + onClick: this.props.inputOnClick, + onBlur: this.props.inputOnBlur, + onFocus: this.props.inputOnFocus, + className: this.props.inputClass ? this.props.inputClass + ' react-mapbox-ac-input' : 'react-mapbox-ac-input', + onChange: this._updateQuery, + value: this.state.query, + type: 'text' }), + _react2.default.createElement( + 'span', + null, + _react2.default.createElement( + 'div', + { className: 'react-mapbox-ac-menu', + style: this.state.queryResults.length > 0 || this.state.error ? { display: 'block' } : { display: 'none' }, + onClick: this._resetSearch }, + (0, _map2.default)(this.state.queryResults, function (place, i) { + return _react2.default.createElement( + 'div', + { className: 'react-mapbox-ac-suggestion', + onClick: _this2._onSuggestionSelect, + key: i, + 'data-place': place, + 'data-suggestion': place.place_name, + 'data-lng': place.center[0], + 'data-lat': place.center[1], + 'data-text': place.text }, + place.place_name + ); + }), + this.state.error && _react2.default.createElement( + 'div', + { className: 'react-mapbox-ac-suggestion' }, + this.state.errorMsg + ) + ) + ) + ); + } + }]); + + return ReactMapboxAutocomplete; }(_react2.default.Component); ReactMapboxAutocomplete.defaultProps = { - inputId: null, - inputOnFocus: null, - inputOnBlur: null, - inputOnClick: null + inputId: null, + inputOnFocus: null, + inputOnBlur: null, + inputOnClick: null }; ReactMapboxAutocomplete.propTypes = { - inputId: _propTypes2.default.string, - inputOnFocus: _propTypes2.default.func, - inputOnBlur: _propTypes2.default.func, - inputOnClick: _propTypes2.default.func, - inputClass: _propTypes2.default.string, - publicKey: _propTypes2.default.string.isRequired, - placeholder: _propTypes2.default.string, - onSuggestionSelect: _propTypes2.default.func.isRequired, - country: _propTypes2.default.string, - query: _propTypes2.default.string, - resetSearch: _propTypes2.default.bool + inputId: _propTypes2.default.string, + inputOnFocus: _propTypes2.default.func, + inputOnBlur: _propTypes2.default.func, + inputOnClick: _propTypes2.default.func, + inputClass: _propTypes2.default.string, + publicKey: _propTypes2.default.string.isRequired, + placeholder: _propTypes2.default.string, + onSuggestionSelect: _propTypes2.default.func.isRequired, + country: _propTypes2.default.string, + query: _propTypes2.default.string, + resetSearch: _propTypes2.default.bool }; exports.default = ReactMapboxAutocomplete; diff --git a/package.json b/package.json index bf8807b..5524130 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,10 @@ "babel-cli": "^6.18.0", "babel-core": "^6.24.1", "babel-jest": "^18.0.0", + "babel-plugin-external-helpers": "^6.22.0", + "babel-plugin-transform-decorators-legacy": "^1.3.5", "babel-preset-react-app": "^2.2.0", + "babel-preset-stage-0": "^6.24.1", "enzyme": "^2.7.0", "enzyme-to-json": "^1.4.5", "jest": "^18.1.0",