UNPKG

react-google-maps-loader

Version:

React component to use google maps services into your react applications using a render prop

1,015 lines (829 loc) 29 kB
/*! * react-google-maps-loader v4.3.1 - https://github.com/cedricdelpoux/react-google-maps-loader#readme * MIT Licensed */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("prop-types"), require("react")); else if(typeof define === 'function' && define.amd) define(["prop-types", "react"], factory); else if(typeof exports === 'object') exports["ReactDemoPage"] = factory(require("prop-types"), require("react")); else root["ReactDemoPage"] = factory(root["PropTypes"], root["React"]); })(window, function(__WEBPACK_EXTERNAL_MODULE__0__, __WEBPACK_EXTERNAL_MODULE__1__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 4); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE__0__; /***/ }), /* 1 */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE__1__; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { /** * Script loading is difficult thanks to IE. We need callbacks to fire * immediately following the script's execution, with no other scripts * running in between. If other scripts on the page are able to run * between our script and its callback, bad things can happen, such as * `jQuery.noConflict` not being called in time, resulting in plugins * latching onto our version of jQuery, etc. * * For IE<10 we use a relatively well-documented "preloading" strategy, * which ensures that the script is ready to execute *before* appending * it to the DOM. That way when it is finally appended, it is * executed immediately. * * References: * - http://www.html5rocks.com/en/tutorials/speed/script-loading/ * - http://blog.getify.com/ie11-please-bring-real-script-preloading-back/ * - https://github.com/jrburke/requirejs/issues/526 * - https://connect.microsoft.com/IE/feedback/details/729164/ * ie10-dynamic-script-element-fires-loaded-readystate-prematurely */ (function () { // Global state. var pendingScripts = {}; var scriptCounter = 0; /** * Insert script into the DOM * * @param {Object} script Script DOM object * @returns {void} */ var _addScript = function (script) { // Get the first script element, we're just going to use it // as a reference for where to insert ours. Do NOT try to do // this just once at the top and then re-use the same script // as a reference later. Some weird loaders *remove* script // elements after the browser has executed their contents, // so the same reference might not have a parentNode later. var firstScript = document.getElementsByTagName("script")[0]; // Append the script to the DOM, triggering execution. firstScript.parentNode.insertBefore(script, firstScript); }; /** * Load Script. * * @param {String} src URI of script * @param {Function|Object} callback (Optional) Called on script load completion, * or options object * @param {Object} context (Optional) Callback context (`this`) * @returns {void} */ var _lload = function (src, callback, context) { /*eslint max-statements: [2, 32]*/ var setup; if (callback && typeof callback !== "function") { context = callback.context || context; setup = callback.setup; callback = callback.callback; } var script = document.createElement("script"); var done = false; var err; var _cleanup; // _must_ be set below. /** * Final handler for error or completion. * * **Note**: Will only be called _once_. * * @returns {void} */ var _finish = function () { // Only call once. if (done) { return; } done = true; // Internal cleanup. _cleanup(); // Callback. if (callback) { callback.call(context, err); } }; /** * Error handler * * @returns {void} */ var _error = function () { err = new Error(src || "EMPTY"); _finish(); }; if (script.readyState && !("async" in script)) { /*eslint-disable consistent-return*/ // This section is only for IE<10. Some other old browsers may // satisfy the above condition and enter this branch, but we don't // support those browsers anyway. var id = scriptCounter++; var isReady = { loaded: true, complete: true }; var inserted = false; // Clear out listeners, state. _cleanup = function () { script.onreadystatechange = script.onerror = null; pendingScripts[id] = void 0; }; // Attach the handler before setting src, otherwise we might // miss events (consider that IE could fire them synchronously // upon setting src, for example). script.onreadystatechange = function () { var firstState = script.readyState; // Protect against any errors from state change randomness. if (err) { return; } if (!inserted && isReady[firstState]) { inserted = true; // Append to DOM. _addScript(script); } // -------------------------------------------------------------------- // GLORIOUS IE8 HACKAGE!!! // -------------------------------------------------------------------- // // Oh IE8, how you disappoint. IE8 won't call `script.onerror`, so // we have to resort to drastic measures. // See, e.g. http://www.quirksmode.org/dom/events/error.html#t02 // // As with all things development, there's a Stack Overflow comment that // asserts the following combinations of state changes in IE8 indicate a // script load error. And crazily, it seems to work! // // http://stackoverflow.com/a/18840568/741892 // // The `script.readyState` transitions we're interested are: // // * If state starts as `loaded` // * Call `script.children`, which _should_ change state to `complete` // * If state is now `loading`, then **we have a load error** // // For the reader's amusement, here is HeadJS's catalog of various // `readyState` transitions in normal operation for IE: // https://github.com/headjs/headjs/blob/master/src/2.0.0/load.js#L379-L419 if (firstState === "loaded") { // The act of accessing the property should change the script's // `readyState`. // // And, oh yeah, this hack is so hacky-ish we need the following // eslint disable... /*eslint-disable no-unused-expressions*/ script.children; /*eslint-enable no-unused-expressions*/ if (script.readyState === "loading") { // State transitions indicate we've hit the load error. // // **Note**: We are not intending to _return_ a value, just have // a shorter short-circuit code path here. return _error(); } } // It's possible for readyState to be "complete" immediately // after we insert (and execute) the script in the branch // above. So check readyState again here and react without // waiting for another onreadystatechange. if (script.readyState === "complete") { _finish(); } }; // Onerror handler _may_ work here. script.onerror = _error; // Since we're not appending the script to the DOM yet, the // reference to our script element might get garbage collected // when this function ends, without onreadystatechange ever being // fired. This has been witnessed to happen. Adding it to // `pendingScripts` ensures this can't happen. pendingScripts[id] = script; // call the setup callback to mutate the script tag if (setup) { setup.call(context, script); } // This triggers a request for the script, but its contents won't // be executed until we append it to the DOM. script.src = src; // In some cases, the readyState is already "loaded" immediately // after setting src. It's a lie! Don't append to the DOM until // the onreadystatechange event says so. } else { // This section is for modern browsers, including IE10+. // Clear out listeners. _cleanup = function () { script.onload = script.onerror = null; }; script.onerror = _error; script.onload = _finish; script.async = true; script.charset = "utf-8"; // call the setup callback to mutate the script tag if (setup) { setup.call(context, script); } script.src = src; // Append to DOM. _addScript(script); } }; // UMD wrapper. /*global define:false*/ if (true) { // CommonJS module.exports = _lload; } else {} }()); /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const strictUriEncode = __webpack_require__(5); const decodeComponent = __webpack_require__(6); const splitOnFirst = __webpack_require__(7); const isNullOrUndefined = value => value === null || value === undefined; function encoderForArrayFormat(options) { switch (options.arrayFormat) { case 'index': return key => (result, value) => { const index = result.length; if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, [encode(key, options), '[', index, ']'].join('')]; } return [ ...result, [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join('') ]; }; case 'bracket': return key => (result, value) => { if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, [encode(key, options), '[]'].join('')]; } return [...result, [encode(key, options), '[]=', encode(value, options)].join('')]; }; case 'comma': case 'separator': return key => (result, value) => { if (value === null || value === undefined || value.length === 0) { return result; } if (result.length === 0) { return [[encode(key, options), '=', encode(value, options)].join('')]; } return [[result, encode(value, options)].join(options.arrayFormatSeparator)]; }; default: return key => (result, value) => { if ( value === undefined || (options.skipNull && value === null) || (options.skipEmptyString && value === '') ) { return result; } if (value === null) { return [...result, encode(key, options)]; } return [...result, [encode(key, options), '=', encode(value, options)].join('')]; }; } } function parserForArrayFormat(options) { let result; switch (options.arrayFormat) { case 'index': return (key, value, accumulator) => { result = /\[(\d*)\]$/.exec(key); key = key.replace(/\[\d*\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = {}; } accumulator[key][result[1]] = value; }; case 'bracket': return (key, value, accumulator) => { result = /(\[\])$/.exec(key); key = key.replace(/\[\]$/, ''); if (!result) { accumulator[key] = value; return; } if (accumulator[key] === undefined) { accumulator[key] = [value]; return; } accumulator[key] = [].concat(accumulator[key], value); }; case 'comma': case 'separator': return (key, value, accumulator) => { const isArray = typeof value === 'string' && value.split('').indexOf(options.arrayFormatSeparator) > -1; const newValue = isArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : value === null ? value : decode(value, options); accumulator[key] = newValue; }; default: return (key, value, accumulator) => { if (accumulator[key] === undefined) { accumulator[key] = value; return; } accumulator[key] = [].concat(accumulator[key], value); }; } } function validateArrayFormatSeparator(value) { if (typeof value !== 'string' || value.length !== 1) { throw new TypeError('arrayFormatSeparator must be single character string'); } } function encode(value, options) { if (options.encode) { return options.strict ? strictUriEncode(value) : encodeURIComponent(value); } return value; } function decode(value, options) { if (options.decode) { return decodeComponent(value); } return value; } function keysSorter(input) { if (Array.isArray(input)) { return input.sort(); } if (typeof input === 'object') { return keysSorter(Object.keys(input)) .sort((a, b) => Number(a) - Number(b)) .map(key => input[key]); } return input; } function removeHash(input) { const hashStart = input.indexOf('#'); if (hashStart !== -1) { input = input.slice(0, hashStart); } return input; } function getHash(url) { let hash = ''; const hashStart = url.indexOf('#'); if (hashStart !== -1) { hash = url.slice(hashStart); } return hash; } function extract(input) { input = removeHash(input); const queryStart = input.indexOf('?'); if (queryStart === -1) { return ''; } return input.slice(queryStart + 1); } function parseValue(value, options) { if (options.parseNumbers && !Number.isNaN(Number(value)) && (typeof value === 'string' && value.trim() !== '')) { value = Number(value); } else if (options.parseBooleans && value !== null && (value.toLowerCase() === 'true' || value.toLowerCase() === 'false')) { value = value.toLowerCase() === 'true'; } return value; } function parse(input, options) { options = Object.assign({ decode: true, sort: true, arrayFormat: 'none', arrayFormatSeparator: ',', parseNumbers: false, parseBooleans: false }, options); validateArrayFormatSeparator(options.arrayFormatSeparator); const formatter = parserForArrayFormat(options); // Create an object with no prototype const ret = Object.create(null); if (typeof input !== 'string') { return ret; } input = input.trim().replace(/^[?#&]/, ''); if (!input) { return ret; } for (const param of input.split('&')) { let [key, value] = splitOnFirst(options.decode ? param.replace(/\+/g, ' ') : param, '='); // Missing `=` should be `null`: // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters value = value === undefined ? null : ['comma', 'separator'].includes(options.arrayFormat) ? value : decode(value, options); formatter(decode(key, options), value, ret); } for (const key of Object.keys(ret)) { const value = ret[key]; if (typeof value === 'object' && value !== null) { for (const k of Object.keys(value)) { value[k] = parseValue(value[k], options); } } else { ret[key] = parseValue(value, options); } } if (options.sort === false) { return ret; } return (options.sort === true ? Object.keys(ret).sort() : Object.keys(ret).sort(options.sort)).reduce((result, key) => { const value = ret[key]; if (Boolean(value) && typeof value === 'object' && !Array.isArray(value)) { // Sort object keys, not values result[key] = keysSorter(value); } else { result[key] = value; } return result; }, Object.create(null)); } exports.extract = extract; exports.parse = parse; exports.stringify = (object, options) => { if (!object) { return ''; } options = Object.assign({ encode: true, strict: true, arrayFormat: 'none', arrayFormatSeparator: ',' }, options); validateArrayFormatSeparator(options.arrayFormatSeparator); const shouldFilter = key => ( (options.skipNull && isNullOrUndefined(object[key])) || (options.skipEmptyString && object[key] === '') ); const formatter = encoderForArrayFormat(options); const objectCopy = {}; for (const key of Object.keys(object)) { if (!shouldFilter(key)) { objectCopy[key] = object[key]; } } const keys = Object.keys(objectCopy); if (options.sort !== false) { keys.sort(options.sort); } return keys.map(key => { const value = object[key]; if (value === undefined) { return ''; } if (value === null) { return encode(key, options); } if (Array.isArray(value)) { return value .reduce(formatter(key), []) .join('&'); } return encode(key, options) + '=' + encode(value, options); }).filter(x => x.length > 0).join('&'); }; exports.parseUrl = (input, options) => { return { url: removeHash(input).split('?')[0] || '', query: parse(extract(input), options) }; }; exports.stringifyUrl = (input, options) => { const url = removeHash(input.url).split('?')[0] || ''; const queryFromUrl = exports.extract(input.url); const parsedQueryFromUrl = exports.parse(queryFromUrl); const hash = getHash(input.url); const query = Object.assign(parsedQueryFromUrl, input.query); let queryString = exports.stringify(query, options); if (queryString) { queryString = `?${queryString}`; } return `${url}${queryString}${hash}`; }; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(8); /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = str => encodeURIComponent(str).replace(/[!'()*]/g, x => `%${x.charCodeAt(0).toString(16).toUpperCase()}`); /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var token = '%[a-f0-9]{2}'; var singleMatcher = new RegExp(token, 'gi'); var multiMatcher = new RegExp('(' + token + ')+', 'gi'); function decodeComponents(components, split) { try { // Try to decode the entire string first return decodeURIComponent(components.join('')); } catch (err) { // Do nothing } if (components.length === 1) { return components; } split = split || 1; // Split the array in 2 parts var left = components.slice(0, split); var right = components.slice(split); return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); } function decode(input) { try { return decodeURIComponent(input); } catch (err) { var tokens = input.match(singleMatcher); for (var i = 1; i < tokens.length; i++) { input = decodeComponents(tokens, i).join(''); tokens = input.match(singleMatcher); } return input; } } function customDecodeURIComponent(input) { // Keep track of all the replacements and prefill the map with the `BOM` var replaceMap = { '%FE%FF': '\uFFFD\uFFFD', '%FF%FE': '\uFFFD\uFFFD' }; var match = multiMatcher.exec(input); while (match) { try { // Decode as big chunks as possible replaceMap[match[0]] = decodeURIComponent(match[0]); } catch (err) { var result = decode(match[0]); if (result !== match[0]) { replaceMap[match[0]] = result; } } match = multiMatcher.exec(input); } // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else replaceMap['%C2'] = '\uFFFD'; var entries = Object.keys(replaceMap); for (var i = 0; i < entries.length; i++) { // Replace all decoded components var key = entries[i]; input = input.replace(new RegExp(key, 'g'), replaceMap[key]); } return input; } module.exports = function (encodedURI) { if (typeof encodedURI !== 'string') { throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); } try { encodedURI = encodedURI.replace(/\+/g, ' '); // Try the built in decoder first return decodeURIComponent(encodedURI); } catch (err) { // Fallback to a more advanced decoder return customDecodeURIComponent(encodedURI); } }; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; module.exports = (string, separator) => { if (!(typeof string === 'string' && typeof separator === 'string')) { throw new TypeError('Expected the arguments to be of type `string`'); } if (separator === '') { return [string]; } const separatorIndex = string.indexOf(separator); if (separatorIndex === -1) { return [string]; } return [ string.slice(0, separatorIndex), string.slice(separatorIndex + separator.length) ]; }; /***/ }), /* 8 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; // ESM COMPAT FLAG __webpack_require__.r(__webpack_exports__); // EXTERNAL MODULE: external {"root":"PropTypes","commonjs2":"prop-types","commonjs":"prop-types","amd":"prop-types"} var external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_ = __webpack_require__(0); var external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_default = /*#__PURE__*/__webpack_require__.n(external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_); // EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"} var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_require__(1); var external_root_React_commonjs2_react_commonjs_react_amd_react_default = /*#__PURE__*/__webpack_require__.n(external_root_React_commonjs2_react_commonjs_react_amd_react_); // EXTERNAL MODULE: ./node_modules/little-loader/lib/little-loader.js var little_loader = __webpack_require__(2); var little_loader_default = /*#__PURE__*/__webpack_require__.n(little_loader); // EXTERNAL MODULE: ./node_modules/query-string/index.js var query_string = __webpack_require__(3); var query_string_default = /*#__PURE__*/__webpack_require__.n(query_string); // CONCATENATED MODULE: ./src/loadGoogleMapsSdk/index.js var GOOGLE_MAP_PLACES_API = "https://maps.googleapis.com/maps/api/js"; var NOT_LOADED = 0; var LOADING = 1; var LOADED = 2; var queue = []; var state = NOT_LOADED; var googleMaps = null; var error = null; function loadGoogleMapsSdk(params, callback) { if (typeof window !== "undefined") { window.gm_authFailure = function () { callback({ googleMaps: googleMaps, error: "SDK Authentication Error" }); }; if (state === LOADED) { callback({ googleMaps: googleMaps, error: error }); } else if (state === LOADING) { queue.push(callback); } else if (window.google && window.google.maps) { state = LOADED; googleMaps = window.google.maps; callback({ googleMaps: googleMaps, error: error }); } else { state = LOADING; queue.push(callback); little_loader_default()(GOOGLE_MAP_PLACES_API + "?" + query_string_default.a.stringify(params), function (err) { state = LOADED; error = err ? "Network Error" : null; googleMaps = window.google ? window.google.maps : null; while (queue.length > 0) { queue.pop()({ googleMaps: googleMaps, error: error }); } }); } } } /* harmony default export */ var src_loadGoogleMapsSdk = (loadGoogleMapsSdk); // CONCATENATED MODULE: ./src/index.js function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var src_GoogleMapsLoader = /*#__PURE__*/function (_React$Component) { _inheritsLoose(GoogleMapsLoader, _React$Component); function GoogleMapsLoader() { var _this; _this = _React$Component.call(this) || this; _this._isMounted = false; _this.state = { googleMaps: null, error: null }; return _this; } var _proto = GoogleMapsLoader.prototype; _proto.componentDidMount = function componentDidMount() { var _this2 = this; this._isMounted = true; var params = this.props.params; src_loadGoogleMapsSdk(params, function (_ref) { var googleMaps = _ref.googleMaps, error = _ref.error; return _this2._isMounted && _this2.setState({ googleMaps: googleMaps, error: error }); }); }; _proto.componentWillUnmount = function componentWillUnmount() { this._isMounted = false; }; _proto.render = function render() { var _this$state = this.state, googleMaps = _this$state.googleMaps, error = _this$state.error; var render = this.props.render; return render(googleMaps, error); }; return GoogleMapsLoader; }(external_root_React_commonjs2_react_commonjs_react_amd_react_default.a.Component); src_GoogleMapsLoader.propTypes = { params: external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_default.a.shape({ key: external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_default.a.string.isRequired, libraries: external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_default.a.string }).isRequired, render: external_root_PropTypes_commonjs2_prop_types_commonjs_prop_types_amd_prop_types_default.a.func.isRequired }; /* harmony default export */ var src = __webpack_exports__["default"] = (src_GoogleMapsLoader); /***/ }) /******/ ])["default"]; });