react-google-autocomplete
Version:
React component for google autocomplete.
160 lines (135 loc) • 9.24 kB
JavaScript
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = usePlacesWidget;
var _react = _interopRequireWildcard(require("react"));
var _utils = require("./utils");
var _constants = require("./constants");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
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 _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function usePlacesWidget(props) {
var ref = props.ref,
onPlaceSelected = props.onPlaceSelected,
apiKey = props.apiKey,
_props$libraries = props.libraries,
libraries = _props$libraries === void 0 ? "places" : _props$libraries,
_props$inputAutocompl = props.inputAutocompleteValue,
inputAutocompleteValue = _props$inputAutocompl === void 0 ? "new-password" : _props$inputAutocompl,
_props$options = props.options;
_props$options = _props$options === void 0 ? {} : _props$options;
var _props$options$types = _props$options.types,
types = _props$options$types === void 0 ? ["(cities)"] : _props$options$types,
componentRestrictions = _props$options.componentRestrictions,
_props$options$fields = _props$options.fields,
fields = _props$options$fields === void 0 ? ["address_components", "geometry.location", "place_id", "formatted_address"] : _props$options$fields,
bounds = _props$options.bounds,
options = _objectWithoutProperties(_props$options, ["types", "componentRestrictions", "fields", "bounds"]),
_props$googleMapsScri = props.googleMapsScriptBaseUrl,
googleMapsScriptBaseUrl = _props$googleMapsScri === void 0 ? _constants.GOOGLE_MAP_SCRIPT_BASE_URL : _props$googleMapsScri,
language = props.language;
var inputRef = (0, _react.useRef)(null);
var event = (0, _react.useRef)(null);
var autocompleteRef = (0, _react.useRef)(null);
var languageQueryParam = language ? "&language=".concat(language) : "";
var googleMapsScriptUrl = "".concat(googleMapsScriptBaseUrl, "?libraries=").concat(libraries, "&key=").concat(apiKey).concat(languageQueryParam);
var handleLoadScript = (0, _react.useCallback)(function () {
return (0, _utils.loadGoogleMapScript)(googleMapsScriptBaseUrl, googleMapsScriptUrl);
}, [googleMapsScriptBaseUrl, googleMapsScriptUrl]);
(0, _react.useEffect)(function () {
var config = _objectSpread(_objectSpread({}, options), {}, {
fields: fields,
types: types,
bounds: bounds
});
if (componentRestrictions) {
config.componentRestrictions = componentRestrictions;
}
if (autocompleteRef.current || !inputRef.current || !_utils.isBrowser) return;
if (ref && !ref.current) ref.current = inputRef.current;
var handleAutoComplete = function handleAutoComplete() {
var _google$maps;
if (typeof google === "undefined") return console.error("Google has not been found. Make sure your provide apiKey prop.");
if (!((_google$maps = google.maps) !== null && _google$maps !== void 0 && _google$maps.places)) return console.error("Google maps places API must be loaded.");
if (!(inputRef.current instanceof HTMLInputElement)) return console.error("Input ref must be HTMLInputElement.");
autocompleteRef.current = new google.maps.places.Autocomplete(inputRef.current, config);
if (autocompleteRef.current) {
event.current = autocompleteRef.current.addListener("place_changed", function () {
if (onPlaceSelected && autocompleteRef && autocompleteRef.current) {
onPlaceSelected(autocompleteRef.current.getPlace(), inputRef.current, autocompleteRef.current);
}
});
}
};
if (apiKey) {
handleLoadScript().then(function () {
return handleAutoComplete();
});
} else {
handleAutoComplete();
}
return function () {
return event.current ? event.current.remove() : undefined;
};
}, []);
(0, _react.useEffect)(function () {
if (autocompleteRef.current && onPlaceSelected) {
event.current = autocompleteRef.current.addListener("place_changed", function () {
if (onPlaceSelected && autocompleteRef && autocompleteRef.current) {
onPlaceSelected(autocompleteRef.current.getPlace(), inputRef.current, autocompleteRef.current);
}
});
}
return function () {
return event.current ? event.current.remove() : undefined;
};
}, [onPlaceSelected]); // Autofill workaround adapted from https://stackoverflow.com/questions/29931712/chrome-autofill-covers-autocomplete-for-google-maps-api-v3/49161445#49161445
(0, _react.useEffect)(function () {
// TODO find out why react 18(strict mode) hangs the page loading
if (_utils.isBrowser && window.MutationObserver && inputRef.current && inputRef.current instanceof HTMLInputElement) {
var observerHack = new MutationObserver(function () {
observerHack.disconnect();
if (inputRef.current) {
inputRef.current.autocomplete = inputAutocompleteValue;
}
});
observerHack.observe(inputRef.current, {
attributes: true,
attributeFilter: ["autocomplete"]
});
return function () {
observerHack.disconnect(); // Cleanup
};
}
}, [inputAutocompleteValue]);
(0, _react.useEffect)(function () {
if (autocompleteRef.current) {
autocompleteRef.current.setFields(fields);
}
}, [fields]);
(0, _react.useEffect)(function () {
if (autocompleteRef.current) {
autocompleteRef.current.setBounds(bounds);
}
}, [bounds]);
(0, _react.useEffect)(function () {
if (autocompleteRef.current) {
autocompleteRef.current.setComponentRestrictions(componentRestrictions);
}
}, [componentRestrictions]);
(0, _react.useEffect)(function () {
if (autocompleteRef.current) {
autocompleteRef.current.setOptions(options);
}
}, [options]);
return {
ref: inputRef,
autocompleteRef: autocompleteRef
};
}
;