wix-style-react
Version:
wix-style-react
415 lines (329 loc) • 14.8 kB
JavaScript
;
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;