UNPKG

wix-style-react

Version:
415 lines (329 loc) • 14.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.GoogleAddressInputHandler = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 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; }; }(); var _class, _temp; /* eslint-disable no-console */ var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _castArray = require('lodash/castArray'); var _castArray2 = _interopRequireDefault(_castArray); var _Input = require('../Input'); var _Input2 = _interopRequireDefault(_Input); var _InputWithOptions = require('../InputWithOptions'); var _InputWithOptions2 = _interopRequireDefault(_InputWithOptions); var _google2address = require('./google2address'); var _GoogleAddressInput = require('./GoogleAddressInput.scss'); var _GoogleAddressInput2 = _interopRequireDefault(_GoogleAddressInput); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 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 GoogleAddressInputHandler = exports.GoogleAddressInputHandler = { geocode: 'geocode', places: 'places' }; /** * Address input box (using Google Maps) */ var GoogleAddressInput = (_temp = _class = function (_React$Component) { _inherits(GoogleAddressInput, _React$Component); function GoogleAddressInput(props) { _classCallCheck(this, GoogleAddressInput); var _this = _possibleConstructorReturn(this, (GoogleAddressInput.__proto__ || Object.getPrototypeOf(GoogleAddressInput)).call(this, props)); _this.state = { suggestions: [], value: props.value || '' }; _this.autoCompleteRequestId = 0; _this.geocodeRequestId = 0; _this.client = new props.Client(); _this.onChange = _this.onChange.bind(_this); _this.onBlur = _this.onBlur.bind(_this); _this.onFocus = _this.onFocus.bind(_this); _this.onSet = _this.onSet.bind(_this); _this.onManuallyInput = _this.onManuallyInput.bind(_this); return _this; } _createClass(GoogleAddressInput, [{ key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var _this2 = this; if (nextProps.value !== this.props.value) { this._getSuggestions(nextProps.value).then(function (suggestions) { _this2.setState({ suggestions: suggestions }); }).catch(function () { // Nothing really to do... _this2.setState({ suggestions: [] }); }); } } }, { key: 'render', value: function render() { var _this3 = this; var _state = this.state, suggestions = _state.suggestions, value = _state.value; var options = [].concat(_toConsumableArray(suggestions.map(function (_ref) { var description = _ref.description, id = _ref.id; return { id: id, value: description }; })), _toConsumableArray(this.props.footer ? [_extends({ id: suggestions.length, value: this.props.footer }, this.props.footerOptions)] : [])); return _react2.default.createElement( 'div', null, _react2.default.createElement(_InputWithOptions2.default, _extends({ ref: function ref(autocomplete) { return _this3.autocomplete = autocomplete; } }, this.props, { onInput: this.onChange, onBlur: this.onBlur, onFocus: this.onFocus, onSelect: function onSelect(option) { return _this3.onSet(option.value); }, onManuallyInput: this.onManuallyInput, value: value, options: options, fixedFooter: suggestions.length && this.props.poweredByGoogle ? GoogleAddressInput.getGoogleFooter() : null, selectedHighlight: false })) ); } }, { key: 'focus', value: function focus() { this.autocomplete.focus(); } }, { key: 'select', value: function select() { this.autocomplete.select(); } }, { key: 'onChange', value: function onChange(e) { var _this4 = this; var value = e.target.value; this.props.onChange && this.props.onChange(e); this.props.onSet && this.props.onSet(null); if (typeof this.props.value !== 'undefined') { // Controlled mode return; } this._getSuggestions(value).then(function (suggestions) { _this4.setState({ suggestions: suggestions }); }).catch(function () { // Nothing really to do... _this4.setState({ suggestions: [] }); }); } }, { key: 'onBlur', value: function onBlur() { var _this5 = this; this.props.onBlur && this.props.onBlur(); if (this.props.clearSuggestionsOnBlur) { this.timer = setTimeout(function () { _this5.setState({ suggestions: [] }); }, 250); } } }, { key: 'onFocus', value: function onFocus() { this.props.onFocus && this.props.onFocus(); } }, { key: 'onSet', value: function onSet(value) { var _this6 = this; var _props = this.props, countryCode = _props.countryCode, handler = _props.handler; var suggestion = this.state.suggestions.find(function (s) { return s.description === value; }); this.setState({ suggestions: [], value: this.props.value || value }); var requestId = ++this.geocodeRequestId; var handlerCall = void 0; if (handler === GoogleAddressInputHandler.places && suggestion && suggestion.place_id) { handlerCall = this.client.placeDetails({ request: { placeId: suggestion.place_id } }); } else { handlerCall = this.client.geocode({ request: _defineProperty({ region: countryCode }, suggestion ? 'placeId' : 'address', suggestion ? suggestion.place_id : value) }); } handlerCall.then(function (results) { results = (0, _castArray2.default)(results).filter(Boolean); if (requestId !== _this6.geocodeRequestId) { return; } if (results.length === 0) { console.error('[GoogleAddressInput] handler (' + handler + ') returned no results on', value); _this6.props.onSet && _this6.props.onSet(null); // This shouldn't happen since we're running geocode on exactly the same // value returned by suggestions list return; } var firstResult = (0, _google2address.trySetStreetNumberIfNotReceived)(results[0], _this6.state.value); var result = { originValue: value, googleResult: firstResult, address: (0, _google2address.google2address)(firstResult) }; _this6.props.onSet && _this6.props.onSet(result); }).catch(function (e) { console.error('[GoogleAddressInput] handler (' + handler + ') failed on', value, e.message); _this6.props.onSet && _this6.props.onSet(null); }); } }, { key: 'onManuallyInput', value: function onManuallyInput(inputValue) { var _this7 = this; var _props2 = this.props, value = _props2.value, fallbackToManual = _props2.fallbackToManual, onSet = _props2.onSet; if (fallbackToManual) { this._getSuggestions(inputValue, typeof value !== 'undefined').then(function (suggestions) { if (suggestions.length === 0) { // No suggestion to the text entered if (inputValue) { _this7.onSet(inputValue); } else { onSet && onSet(null); } } }); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this.timer) { clearTimeout(this.timer); } } }, { key: '_getSuggestions', value: function _getSuggestions(value, skipSetState) { var _this8 = this; var _props3 = this.props, _props3$valuePrefix = _props3.valuePrefix, valuePrefix = _props3$valuePrefix === undefined ? '' : _props3$valuePrefix, countryCode = _props3.countryCode, types = _props3.types, filterTypes = _props3.filterTypes; var requestId = ++this.autoCompleteRequestId; return new Promise(function (resolve) { if (skipSetState) { // Controlled mode resolve(); return; } _this8.setState({ value: value }, function () { return resolve(); }); }).then(function () { if (value === '') { return Promise.resolve([]); } var request = { types: types, componentRestrictions: { country: countryCode }, input: valuePrefix + value }; return _this8.client.autocomplete({ request: request }); }).then(function (results) { if (results.length === 0) { return Promise.resolve([]); } if (requestId !== _this8.autoCompleteRequestId) { return Promise.resolve([]); } if (filterTypes) { results = results.filter(function (result) { return (0, _google2address.includes)(result.types, filterTypes); }); } return Promise.resolve(results); }); } }]); return GoogleAddressInput; }(_react2.default.Component), _class.getGoogleFooter = function () { return _react2.default.createElement('div', { className: _GoogleAddressInput2.default.googleFooter, 'data-hook': 'google-footer' }); }, _temp); GoogleAddressInput.displayName = 'GoogleAddressInput'; GoogleAddressInput.defaultProps = { magnifyingGlass: true, theme: _Input2.default.defaultProps.theme, autoSelect: true, footerOptions: {}, clearSuggestionsOnBlur: true, fallbackToManual: false, poweredByGoogle: false, handler: GoogleAddressInputHandler.geocode }; GoogleAddressInput.propTypes = { /** Placeholder for the input box */ placeholder: _propTypes2.default.string, /** Value to place before every search term (normally should not be used) */ valuePrefix: _propTypes2.default.string, /** Country code used to help with suggestions and geocoding */ countryCode: _propTypes2.default.string, /** Controlled mode - value to display */ value: _propTypes2.default.string, /** Limit the autocomplete to specific types (see [here](https://developers.google.com/places/supported_types#table3) for list) */ types: _propTypes2.default.array, /** Lower level filtering of autocomplete result types (see [here](https://developers.google.com/places/supported_types) for list) */ filterTypes: _propTypes2.default.array, /** Should display error marker */ error: _propTypes2.default.bool, onChange: _propTypes2.default.func, onBlur: _propTypes2.default.func, onFocus: _propTypes2.default.func, onKeyDown: _propTypes2.default.func, /** Callback for results. Will return an object containing: originValue (value in the search), googleResult (google geocode result for the search), address (which will include: formatted (google formatted address), country, countryCode, street, number, postalCode, latLng (lat, lng)) */ onSet: _propTypes2.default.func, /** Google map client implementation (should implement autocomplete and geocode functions). Normally you would use wix-style-react/clients/GoogleMapsClient */ Client: _propTypes2.default.func.isRequired, /** Show or hide magnifying glass icon */ magnifyingGlass: _propTypes2.default.bool, theme: _Input2.default.propTypes.theme, /** Sets the input to readOnly */ readOnly: _propTypes2.default.bool, autoSelect: _propTypes2.default.bool, /** Display a footer as the last suggestion in the list */ footer: _propTypes2.default.any, /** Set the footer's options (e.g. disabled, overrideStyles, etc. ) */ footerOptions: _propTypes2.default.object, /** Clear the suggestions list upon input blur */ clearSuggestionsOnBlur: _propTypes2.default.bool, /** If set to `true`, we will attempt to get a Google location from the input's text if there are no suggestions. This is useful when looking for locations for which google does not give suggestions - for example: Apartment/Apt */ fallbackToManual: _propTypes2.default.bool, /** Shows the Powered By Google credit in a fixed footer */ poweredByGoogle: _propTypes2.default.bool, /** Sets how to get more details for a place (e.g. geocode, places, etc) */ handler: _propTypes2.default.oneOf([GoogleAddressInputHandler.geocode, GoogleAddressInputHandler.places]) }; exports.default = GoogleAddressInput;