UNPKG

@react-google-maps/api

Version:
1,597 lines (1,561 loc) 332 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { createContext, useContext, memo, useState, useRef, useEffect, PureComponent, useMemo, Children, isValidElement, cloneElement, createRef } from 'react'; import * as ReactDOM from 'react-dom'; import { createPortal } from 'react-dom'; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function toPropertyKey(t) { var i = toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _defineProperty(e, r, t) { return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function getDefaultExportFromCjs$1 (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var invariant_1; var hasRequiredInvariant; function requireInvariant() { if (hasRequiredInvariant) return invariant_1; hasRequiredInvariant = 1; /** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production. */ var NODE_ENV = process.env.NODE_ENV; var invariant = function invariant(condition, format, a, b, c, d, e, f) { if (NODE_ENV !== 'production') { if (format === undefined) { throw new Error('invariant requires an error message argument'); } } if (!condition) { var error; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } }; invariant_1 = invariant; return invariant_1; } var invariantExports = requireInvariant(); var invariant = /*@__PURE__*/getDefaultExportFromCjs$1(invariantExports); var MapContext = createContext(null); function useGoogleMap() { invariant(!!useContext, 'useGoogleMap is React hook and requires React version 16.8+'); var map = useContext(MapContext); invariant(!!map, 'useGoogleMap needs a GoogleMap available up in the tree'); return map; } // eslint-disable-next-line @typescript-eslint/no-explicit-any function reduce(obj, fn, acc) { return Object.keys(obj).reduce(function reducer(newAcc, key) { return fn(newAcc, obj[key], key); }, acc); } // eslint-disable-next-line @typescript-eslint/no-explicit-any function forEach(obj, fn) { Object.keys(obj).forEach(key => { return fn(obj[key], key); }); } /* global google */ /* eslint-disable filenames/match-regex */ function applyUpdaterToNextProps( // eslint-disable-next-line @typescript-eslint/no-explicit-any updaterMap, // eslint-disable-next-line @typescript-eslint/no-explicit-any prevProps, // eslint-disable-next-line @typescript-eslint/no-explicit-any nextProps, // eslint-disable-next-line @typescript-eslint/no-explicit-any instance // eslint-disable-next-line @typescript-eslint/no-explicit-any ) { // eslint-disable-next-line @typescript-eslint/no-explicit-any var map = {}; // eslint-disable-next-line @typescript-eslint/no-explicit-any var iter = (fn, key) => { var nextValue = nextProps[key]; if (nextValue !== prevProps[key]) { map[key] = nextValue; fn(instance, nextValue); } }; forEach(updaterMap, iter); return map; } function registerEvents( // eslint-disable-next-line @typescript-eslint/no-explicit-any props, // eslint-disable-next-line @typescript-eslint/no-explicit-any instance, eventMap) { var registeredList = reduce(eventMap, function reducer(acc, googleEventName, // eslint-disable-next-line @typescript-eslint/no-explicit-any onEventName) { if (typeof props[onEventName] === 'function') { acc.push(google.maps.event.addListener(instance, googleEventName, props[onEventName])); } return acc; }, []); return registeredList; } function unregisterEvent(registered) { google.maps.event.removeListener(registered); } function unregisterEvents() { var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; events.forEach(unregisterEvent); } function applyUpdatersToPropsAndRegisterEvents(_ref) { var { updaterMap, eventMap, prevProps, nextProps, instance } = _ref; var registeredEvents = registerEvents(nextProps, instance, eventMap); applyUpdaterToNextProps(updaterMap, prevProps, nextProps, instance); return registeredEvents; } var eventMap$i = { onDblClick: 'dblclick', onDragEnd: 'dragend', onDragStart: 'dragstart', onMapTypeIdChanged: 'maptypeid_changed', onMouseMove: 'mousemove', onMouseOut: 'mouseout', onMouseOver: 'mouseover', onMouseDown: 'mousedown', onMouseUp: 'mouseup', onRightClick: 'rightclick', onTilesLoaded: 'tilesloaded', onBoundsChanged: 'bounds_changed', onCenterChanged: 'center_changed', onClick: 'click', onDrag: 'drag', onHeadingChanged: 'heading_changed', onIdle: 'idle', onProjectionChanged: 'projection_changed', onResize: 'resize', onTiltChanged: 'tilt_changed', onZoomChanged: 'zoom_changed' }; var updaterMap$i = { extraMapTypes(map, extra) { extra.forEach(function forEachExtra(it, i) { map.mapTypes.set(String(i), it); }); }, center(map, center) { map.setCenter(center); }, clickableIcons(map, clickable) { map.setClickableIcons(clickable); }, heading(map, heading) { map.setHeading(heading); }, mapTypeId(map, mapTypeId) { map.setMapTypeId(mapTypeId); }, options(map, options) { map.setOptions(options); }, streetView(map, streetView) { map.setStreetView(streetView); }, tilt(map, tilt) { map.setTilt(tilt); }, zoom(map, zoom) { map.setZoom(zoom); } }; // TODO: unfinished! function GoogleMapFunctional(_ref) { var { children, options, id, mapContainerStyle, mapContainerClassName, center, // clickableIcons, // extraMapTypes, // heading, // mapTypeId, onClick, onDblClick, onDrag, onDragEnd, onDragStart, onMouseMove, onMouseOut, onMouseOver, onMouseDown, onMouseUp, onRightClick, // onMapTypeIdChanged, // onTilesLoaded, // onBoundsChanged, onCenterChanged, // onHeadingChanged, // onIdle, // onProjectionChanged, // onResize, // onTiltChanged, // onZoomChanged, onLoad, onUnmount } = _ref; var [map, setMap] = useState(null); var ref = useRef(null); // const [extraMapTypesListener, setExtraMapTypesListener] = useState<google.maps.MapsEventListener | null>(null) var [centerChangedListener, setCenterChangedListener] = useState(null); var [dblclickListener, setDblclickListener] = useState(null); var [dragendListener, setDragendListener] = useState(null); var [dragstartListener, setDragstartListener] = useState(null); var [mousedownListener, setMousedownListener] = useState(null); var [mousemoveListener, setMousemoveListener] = useState(null); var [mouseoutListener, setMouseoutListener] = useState(null); var [mouseoverListener, setMouseoverListener] = useState(null); var [mouseupListener, setMouseupListener] = useState(null); var [rightclickListener, setRightclickListener] = useState(null); var [clickListener, setClickListener] = useState(null); var [dragListener, setDragListener] = useState(null); // Order does matter useEffect(() => { if (options && map !== null) { map.setOptions(options); } }, [map, options]); useEffect(() => { if (map !== null && typeof center !== 'undefined') { map.setCenter(center); } }, [map, center]); useEffect(() => { if (map && onDblClick) { if (dblclickListener !== null) { google.maps.event.removeListener(dblclickListener); } setDblclickListener(google.maps.event.addListener(map, 'dblclick', onDblClick)); } }, [onDblClick]); useEffect(() => { if (map && onDragEnd) { if (dragendListener !== null) { google.maps.event.removeListener(dragendListener); } setDragendListener(google.maps.event.addListener(map, 'dragend', onDragEnd)); } }, [onDragEnd]); useEffect(() => { if (map && onDragStart) { if (dragstartListener !== null) { google.maps.event.removeListener(dragstartListener); } setDragstartListener(google.maps.event.addListener(map, 'dragstart', onDragStart)); } }, [onDragStart]); useEffect(() => { if (map && onMouseDown) { if (mousedownListener !== null) { google.maps.event.removeListener(mousedownListener); } setMousedownListener(google.maps.event.addListener(map, 'mousedown', onMouseDown)); } }, [onMouseDown]); useEffect(() => { if (map && onMouseMove) { if (mousemoveListener !== null) { google.maps.event.removeListener(mousemoveListener); } setMousemoveListener(google.maps.event.addListener(map, 'mousemove', onMouseMove)); } }, [onMouseMove]); useEffect(() => { if (map && onMouseOut) { if (mouseoutListener !== null) { google.maps.event.removeListener(mouseoutListener); } setMouseoutListener(google.maps.event.addListener(map, 'mouseout', onMouseOut)); } }, [onMouseOut]); useEffect(() => { if (map && onMouseOver) { if (mouseoverListener !== null) { google.maps.event.removeListener(mouseoverListener); } setMouseoverListener(google.maps.event.addListener(map, 'mouseover', onMouseOver)); } }, [onMouseOver]); useEffect(() => { if (map && onMouseUp) { if (mouseupListener !== null) { google.maps.event.removeListener(mouseupListener); } setMouseupListener(google.maps.event.addListener(map, 'mouseup', onMouseUp)); } }, [onMouseUp]); useEffect(() => { if (map && onRightClick) { if (rightclickListener !== null) { google.maps.event.removeListener(rightclickListener); } setRightclickListener(google.maps.event.addListener(map, 'rightclick', onRightClick)); } }, [onRightClick]); useEffect(() => { if (map && onClick) { if (clickListener !== null) { google.maps.event.removeListener(clickListener); } setClickListener(google.maps.event.addListener(map, 'click', onClick)); } }, [onClick]); useEffect(() => { if (map && onDrag) { if (dragListener !== null) { google.maps.event.removeListener(dragListener); } setDragListener(google.maps.event.addListener(map, 'drag', onDrag)); } }, [onDrag]); useEffect(() => { if (map && onCenterChanged) { if (centerChangedListener !== null) { google.maps.event.removeListener(centerChangedListener); } setCenterChangedListener(google.maps.event.addListener(map, 'center_changed', onCenterChanged)); } }, [onClick]); useEffect(() => { var map = ref.current === null ? null : new google.maps.Map(ref.current, options); setMap(map); if (map !== null && onLoad) { onLoad(map); } return () => { if (map !== null) { if (onUnmount) { onUnmount(map); } } }; }, []); return jsx("div", { id: id, ref: ref, style: mapContainerStyle, className: mapContainerClassName, children: jsx(MapContext.Provider, { value: map, children: map !== null ? children : null }) }); } memo(GoogleMapFunctional); class GoogleMap extends PureComponent { constructor() { super(...arguments); _defineProperty(this, "state", { map: null }); _defineProperty(this, "registeredEvents", []); _defineProperty(this, "mapRef", null); _defineProperty(this, "getInstance", () => { if (this.mapRef === null) { return null; } return new google.maps.Map(this.mapRef, this.props.options); }); _defineProperty(this, "panTo", latLng => { var map = this.getInstance(); if (map) { map.panTo(latLng); } }); _defineProperty(this, "setMapCallback", () => { if (this.state.map !== null) { if (this.props.onLoad) { this.props.onLoad(this.state.map); } } }); _defineProperty(this, "getRef", ref => { this.mapRef = ref; }); } componentDidMount() { var map = this.getInstance(); this.registeredEvents = applyUpdatersToPropsAndRegisterEvents({ updaterMap: updaterMap$i, eventMap: eventMap$i, prevProps: {}, nextProps: this.props, instance: map }); this.setState(function setMap() { return { map }; }, this.setMapCallback); } componentDidUpdate(prevProps) { if (this.state.map !== null) { unregisterEvents(this.registeredEvents); this.registeredEvents = applyUpdatersToPropsAndRegisterEvents({ updaterMap: updaterMap$i, eventMap: eventMap$i, prevProps, nextProps: this.props, instance: this.state.map }); } } componentWillUnmount() { if (this.state.map !== null) { if (this.props.onUnmount) { this.props.onUnmount(this.state.map); } unregisterEvents(this.registeredEvents); } } render() { return jsx("div", { id: this.props.id, ref: this.getRef, style: this.props.mapContainerStyle, className: this.props.mapContainerClassName, children: jsx(MapContext.Provider, { value: this.state.map, children: this.state.map !== null ? this.props.children : null }) }); } } function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); } function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } function makeLoadScriptUrl(_ref) { var { googleMapsApiKey, googleMapsClientId, version = 'weekly', language, region, libraries, channel, mapIds, authReferrerPolicy } = _ref; var params = []; invariant(googleMapsApiKey && googleMapsClientId || !(googleMapsApiKey && googleMapsClientId), 'You need to specify either googleMapsApiKey or googleMapsClientId for @react-google-maps/api load script to work. You cannot use both at the same time.'); if (googleMapsApiKey) { params.push("key=".concat(googleMapsApiKey)); } else if (googleMapsClientId) { params.push("client=".concat(googleMapsClientId)); } if (version) { params.push("v=".concat(version)); } if (language) { params.push("language=".concat(language)); } if (region) { params.push("region=".concat(region)); } if (libraries && libraries.length) { params.push("libraries=".concat(libraries.sort().join(','))); } if (channel) { params.push("channel=".concat(channel)); } if (mapIds && mapIds.length) { params.push("map_ids=".concat(mapIds.join(','))); } if (authReferrerPolicy) { params.push("auth_referrer_policy=".concat(authReferrerPolicy)); } params.push('loading=async'); params.push('callback=initMap'); return "https://maps.googleapis.com/maps/api/js?".concat(params.join('&')); } var isBrowser = typeof document !== 'undefined'; function injectScript(_ref) { var { url, id, nonce // eslint-disable-next-line @typescript-eslint/no-explicit-any } = _ref; if (!isBrowser) { return Promise.reject(new Error('document is undefined')); } return new Promise(function injectScriptCallback(resolve, reject) { var existingScript = document.getElementById(id); var windowWithGoogleMap = window; if (existingScript) { // Same script id/url: keep same script var dataStateAttribute = existingScript.getAttribute('data-state'); if (existingScript.src === url && dataStateAttribute !== 'error') { if (dataStateAttribute === 'ready') { return resolve(id); } else { var originalInitMap = windowWithGoogleMap.initMap; var originalErrorCallback = existingScript.onerror; windowWithGoogleMap.initMap = function initMap() { if (originalInitMap) { originalInitMap(); } resolve(id); }; existingScript.onerror = function (err) { if (originalErrorCallback) { originalErrorCallback(err); } reject(err); }; return; } } // Same script id, but either // 1. requested URL is different // 2. script failed to load else { existingScript.remove(); } } var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; script.id = id; script.async = true; script.nonce = nonce || ''; script.onerror = function onerror(err) { script.setAttribute('data-state', 'error'); reject(err); }; windowWithGoogleMap.initMap = function onload() { script.setAttribute('data-state', 'ready'); resolve(id); }; document.head.appendChild(script); }).catch(err => { console.error('injectScript error: ', err); throw err; }); } function isGoogleFontStyle(element) { // 'Roboto' or 'Google Sans Text' font download var href = element.href; if (href && (href.indexOf('https://fonts.googleapis.com/css?family=Roboto') === 0 || href.indexOf('https://fonts.googleapis.com/css?family=Google+Sans+Text') === 0)) { return true; } // font style elements if ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.tagName.toLowerCase() === 'style' && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.styleSheet && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.styleSheet.cssText && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.styleSheet.cssText.replace('\r\n', '').indexOf('.gm-style') === 0) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.styleSheet.cssText = ''; return true; } // font style elements for other browsers if ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.tagName.toLowerCase() === 'style' && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.innerHTML && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.innerHTML.replace('\r\n', '').indexOf('.gm-style') === 0) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.innerHTML = ''; return true; } // when google tries to add empty style if ( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore element.tagName.toLowerCase() === 'style' && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore !element.styleSheet && // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore !element.innerHTML) { return true; } return false; } // Preventing the Google Maps library from downloading an extra font function preventGoogleFonts() { // we override these methods only for one particular head element // default methods for other elements are not affected var head = document.getElementsByTagName('head')[0]; if (head) { var trueInsertBefore = head.insertBefore.bind(head); // TODO: adding return before reflect solves the TS issue head.insertBefore = function insertBefore(newElement, referenceElement) { if (!isGoogleFontStyle(newElement)) { Reflect.apply(trueInsertBefore, head, [newElement, referenceElement]); } return newElement; }; var trueAppend = head.appendChild.bind(head); // TODO: adding return before reflect solves the TS issue head.appendChild = function appendChild(textNode) { if (!isGoogleFontStyle(textNode)) { Reflect.apply(trueAppend, head, [textNode]); } return textNode; }; } } var cleaningUp = false; function DefaultLoadingElement() { return jsx("div", { children: "Loading..." }); } var defaultLoadScriptProps = { id: 'script-loader', version: 'weekly' }; class LoadScript extends PureComponent { constructor() { super(...arguments); _defineProperty(this, "check", null); _defineProperty(this, "state", { loaded: false }); _defineProperty(this, "cleanupCallback", () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore delete window.google.maps; this.injectScript(); }); _defineProperty(this, "isCleaningUp", /*#__PURE__*/_asyncToGenerator(function* () { function promiseCallback(resolve) { if (!cleaningUp) { resolve(); } else { if (isBrowser) { var timer = window.setInterval(function interval() { if (!cleaningUp) { window.clearInterval(timer); resolve(); } }, 1); } } return; } return new Promise(promiseCallback); })); _defineProperty(this, "cleanup", () => { cleaningUp = true; var script = document.getElementById(this.props.id); if (script && script.parentNode) { script.parentNode.removeChild(script); } Array.prototype.slice.call(document.getElementsByTagName('script')).filter(function filter(script) { return typeof script.src === 'string' && script.src.includes('maps.googleapis'); }).forEach(function forEach(script) { if (script.parentNode) { script.parentNode.removeChild(script); } }); Array.prototype.slice.call(document.getElementsByTagName('link')).filter(function filter(link) { return link.href === 'https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Google+Sans'; }).forEach(function forEach(link) { if (link.parentNode) { link.parentNode.removeChild(link); } }); Array.prototype.slice.call(document.getElementsByTagName('style')).filter(function filter(style) { return style.innerText !== undefined && style.innerText.length > 0 && style.innerText.includes('.gm-'); }).forEach(function forEach(style) { if (style.parentNode) { style.parentNode.removeChild(style); } }); }); _defineProperty(this, "injectScript", () => { if (this.props.preventGoogleFontsLoading) { preventGoogleFonts(); } invariant(!!this.props.id, 'LoadScript requires "id" prop to be a string: %s', this.props.id); var injectScriptOptions = { id: this.props.id, nonce: this.props.nonce, url: makeLoadScriptUrl(this.props) }; injectScript(injectScriptOptions).then(() => { if (this.props.onLoad) { this.props.onLoad(); } this.setState(function setLoaded() { return { loaded: true }; }); return; }).catch(err => { if (this.props.onError) { this.props.onError(err); } console.error("\n There has been an Error with loading Google Maps API script, please check that you provided correct google API key (".concat(this.props.googleMapsApiKey || '-', ") or Client ID (").concat(this.props.googleMapsClientId || '-', ") to <LoadScript />\n Otherwise it is a Network issue.\n ")); }); }); _defineProperty(this, "getRef", el => { this.check = el; }); } componentDidMount() { if (isBrowser) { if (window.google && window.google.maps && !cleaningUp) { console.error('google api is already presented'); return; } this.isCleaningUp().then(this.injectScript).catch(function error(err) { console.error('Error at injecting script after cleaning up: ', err); }); } } componentDidUpdate(prevProps) { if (this.props.libraries !== prevProps.libraries) { console.warn('Performance warning! LoadScript has been reloaded unintentionally! You should not pass `libraries` prop as new array. Please keep an array of libraries as static class property for Components and PureComponents, or just a const variable outside of component, or somewhere in config files or ENV variables'); } if (isBrowser && prevProps.language !== this.props.language) { this.cleanup(); // TODO: refactor to use gDSFP maybe... wait for hooks refactoring. this.setState(function setLoaded() { return { loaded: false }; }, this.cleanupCallback); } } componentWillUnmount() { if (isBrowser) { this.cleanup(); var timeoutCallback = () => { if (!this.check) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore delete window.google; cleaningUp = false; } }; window.setTimeout(timeoutCallback, 1); if (this.props.onUnmount) { this.props.onUnmount(); } } } render() { return jsxs(Fragment, { children: [jsx("div", { ref: this.getRef }), this.state.loaded ? this.props.children : this.props.loadingElement || jsx(DefaultLoadingElement, {})] }); } } _defineProperty(LoadScript, "defaultProps", defaultLoadScriptProps); function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } /* eslint-disable filenames/match-regex */ var previouslyLoadedUrl; function useLoadScript(_ref) { var { id = defaultLoadScriptProps.id, version = defaultLoadScriptProps.version, nonce, googleMapsApiKey, googleMapsClientId, language, region, libraries, preventGoogleFontsLoading, channel, mapIds, authReferrerPolicy } = _ref; var isMounted = useRef(false); var [isLoaded, setLoaded] = useState(false); var [loadError, setLoadError] = useState(undefined); useEffect(function trackMountedState() { isMounted.current = true; return () => { isMounted.current = false; }; }, []); useEffect(function applyPreventGoogleFonts() { if (isBrowser && preventGoogleFontsLoading) { preventGoogleFonts(); } }, [preventGoogleFontsLoading]); useEffect(function validateLoadedState() { if (isLoaded) { invariant(!!window.google, 'useLoadScript was marked as loaded, but window.google is not present. Something went wrong.'); } }, [isLoaded]); var url = makeLoadScriptUrl({ version, googleMapsApiKey, googleMapsClientId, language, region, libraries, channel, mapIds, authReferrerPolicy }); useEffect(function loadScriptAndModifyLoadedState() { if (!isBrowser) { return; } function setLoadedIfMounted() { if (isMounted.current) { setLoaded(true); previouslyLoadedUrl = url; } } if (window.google && window.google.maps && previouslyLoadedUrl === url) { setLoadedIfMounted(); return; } injectScript({ id, url, nonce }).then(setLoadedIfMounted).catch(function handleInjectError(err) { if (isMounted.current) { setLoadError(err); } console.warn("\n There has been an Error with loading Google Maps API script, please check that you provided correct google API key (".concat(googleMapsApiKey || '-', ") or Client ID (").concat(googleMapsClientId || '-', ")\n Otherwise it is a Network issue.\n ")); console.error(err); }); }, [id, url, nonce]); var prevLibraries = useRef(undefined); useEffect(function checkPerformance() { if (prevLibraries.current && libraries !== prevLibraries.current) { console.warn('Performance warning! LoadScript has been reloaded unintentionally! You should not pass `libraries` prop as new array. Please keep an array of libraries as static class property for Components and PureComponents, or just a const variable outside of component, or somewhere in config files or ENV variables'); } prevLibraries.current = libraries; }, [libraries]); return { isLoaded, loadError, url }; } var _excluded$1 = ["loadingElement", "onLoad", "onError", "onUnmount", "children"]; var defaultLoadingElement = jsx(DefaultLoadingElement, {}); function LoadScriptNext(_ref) { var { loadingElement, onLoad, onError, onUnmount, children } = _ref, hookOptions = _objectWithoutProperties(_ref, _excluded$1); var { isLoaded, loadError } = useLoadScript(hookOptions); useEffect(function handleOnLoad() { if (isLoaded && typeof onLoad === 'function') { onLoad(); } }, [isLoaded, onLoad]); useEffect(function handleOnError() { if (loadError && typeof onError === 'function') { onError(loadError); } }, [loadError, onError]); useEffect(function handleOnUnmount() { return () => { if (onUnmount) { onUnmount(); } }; }, [onUnmount]); return isLoaded ? children : loadingElement || defaultLoadingElement; } var LoadScriptNext$1 = memo(LoadScriptNext); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, [])).next()); }); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } // do not edit .js files directly - edit src/index.jst var fastDeepEqual$1 = function equal(a, b) { if (a === b) return true; if (a && b && typeof a == 'object' && typeof b == 'object') { if (a.constructor !== b.constructor) return false; var length, i, keys; if (Array.isArray(a)) { length = a.length; if (length != b.length) return false; for (i = length; i-- !== 0;) if (!equal(a[i], b[i])) return false; return true; } if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags; if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf(); if (a.toString !== Object.prototype.toString) return a.toString() === b.toString(); keys = Object.keys(a); length = keys.length; if (length !== Object.keys(b).length) return false; for (i = length; i-- !== 0;) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false; for (i = length; i-- !== 0;) { var key = keys[i]; if (!equal(a[key], b[key])) return false; } return true; } // true if both NaN, false otherwise return a !== a && b !== b; }; var isEqual = /*@__PURE__*/getDefaultExportFromCjs(fastDeepEqual$1); /** * Copyright 2019 Google LLC. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at. * * Http://www.apache.org/licenses/LICENSE-2.0. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var DEFAULT_ID = "__googleMapsScriptId"; /** * The status of the [[Loader]]. */ var LoaderStatus; (function (LoaderStatus) { LoaderStatus[LoaderStatus["INITIALIZED"] = 0] = "INITIALIZED"; LoaderStatus[LoaderStatus["LOADING"] = 1] = "LOADING"; LoaderStatus[LoaderStatus["SUCCESS"] = 2] = "SUCCESS"; LoaderStatus[LoaderStatus["FAILURE"] = 3] = "FAILURE"; })(LoaderStatus || (LoaderStatus = {})); /** * [[Loader]] makes it easier to add Google Maps JavaScript API to your application * dynamically using * [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). * It works by dynamically creating and appending a script node to the the * document head and wrapping the callback function so as to return a promise. * * ``` * const loader = new Loader({ * apiKey: "", * version: "weekly", * libraries: ["places"] * }); * * loader.load().then((google) => { * const map = new google.maps.Map(...) * }) * ``` */ class Loader { /** * Creates an instance of Loader using [[LoaderOptions]]. No defaults are set * using this library, instead the defaults are set by the Google Maps * JavaScript API server. * * ``` * const loader = Loader({apiKey, version: 'weekly', libraries: ['places']}); * ``` */ constructor(_ref) { var { apiKey, authReferrerPolicy, channel, client, id = DEFAULT_ID, language, libraries = [], mapIds, nonce, region, retries = 3, url = "https://maps.googleapis.com/maps/api/js", version } = _ref; this.callbacks = []; this.done = false; this.loading = false; this.errors = []; this.apiKey = apiKey; this.authReferrerPolicy = authReferrerPolicy; this.channel = channel; this.client = client; this.id = id || DEFAULT_ID; // Do not allow empty string this.language = language; this.libraries = libraries; this.mapIds = mapIds; this.nonce = nonce; this.region = region; this.retries = retries; this.url = url; this.version = version; if (Loader.instance) { if (!isEqual(this.options, Loader.instance.options)) { throw new Error("Loader must not be called again with different options. ".concat(JSON.stringify(this.options), " !== ").concat(JSON.stringify(Loader.instance.options))); } return Loader.instance; } Loader.instance = this; } get options() { return { version: this.version, apiKey: this.apiKey, channel: this.channel, client: this.client, id: this.id, libraries: this.libraries, language: this.language, region: this.region, mapIds: this.mapIds, nonce: this.nonce, url: this.url, authReferrerPolicy: this.authReferrerPolicy }; } get status() { if (this.errors.length) { return LoaderStatus.FAILURE; } if (this.done) { return LoaderStatus.SUCCESS; } if (this.loading) { return LoaderStatus.LOADING; } return LoaderStatus.INITIALIZED; } get failed() { return this.done && !this.loading && this.errors.length >= this.retries + 1; } /** * CreateUrl returns the Google Maps JavaScript API script url given the [[LoaderOptions]]. * * @ignore * @deprecated */ createUrl() { var url = this.url; url += "?callback=__googleMapsCallback&loading=async"; if (this.apiKey) { url += "&key=".concat(this.apiKey); } if (this.channel) { url += "&channel=".concat(this.channel); } if (this.client) { url += "&client=".concat(this.client); } if (this.libraries.length > 0) { url += "&libraries=".concat(this.libraries.join(",")); } if (this.language) { url += "&language=".concat(this.language); } if (this.region) { url += "&region=".concat(this.region); } if (this.version) { url += "&v=".concat(this.version); } if (this.mapIds) { url += "&map_ids=".concat(this.mapIds.join(",")); } if (this.authReferrerPolicy) { url += "&auth_referrer_policy=".concat(this.authReferrerPolicy); } return url; } deleteScript() { var script = document.getElementById(this.id); if (script) { script.remove(); } } /** * Load the Google Maps JavaScript API script and return a Promise. * @deprecated, use importLibrary() instead. */ load() { return this.loadPromise(); } /** * Load the Google Maps JavaScript API script and return a Promise. * * @ignore * @deprecated, use importLibrary() instead. */ loadPromise() { return new Promise((resolve, reject) => { this.loadCallback(err => { if (!err) { resolve(window.google); } else { reject(err.error); } }); }); } importLibrary(name) { this.execute(); return google.maps.importLibrary(name); } /** * Load the Google Maps JavaScript API script with a callback. * @deprecated, use importLibrary() instead. */ loadCallback(fn) { this.callbacks.push(fn); this.execute(); } /** * Set the script on document. */ setScript() { var _a, _b; if (document.getElementById(this.id)) { // TODO wrap onerror callback for cases where the script was loaded elsewhere this.callback(); return; } var params = { key: this.apiKey, channel: this.channel, client: this.client, libraries: this.libraries.length && this.libraries, v: this.version, mapIds: this.mapIds, language: this.language, region: this.region, authReferrerPolicy: this.authReferrerPolicy }; // keep the URL minimal: Object.keys(params).forEach( // eslint-disable-next-line @typescript-eslint/no-explicit-any key => !params[key] && delete params[key]); if (!((_b = (_a = window === null || window === void 0 ? void 0 : window.google) === null || _a === void 0 ? void 0 : _a.maps) === null || _b === void 0 ? void 0 : _b.importLibrary)) { // tweaked copy of https://developers.google.com/maps/documentation/javascript/load-maps-js-api#dynamic-library-import // which also sets the base url, the id, and the nonce /* eslint-disable */ (g => { // @ts-ignore var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; // @ts-ignore b = b[c] || (b[c] = {}); // @ts-ignore var d = b.maps || (b.maps = {}), r = new Set(), e = new URLSearchParams(), u = () => // @ts-ignore h || (h = new Promise((f, n) => __awaiter(this, void 0, void 0, function* () { var _a; yield a = m.createElement("script"); a.id = this.id; e.set("libraries", [...r] + ""); // @ts-ignore for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = this.url + "?" + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); // @ts-ignore a.nonce = this.nonce || ((_a = m.querySelector("script[nonce]")) === null || _a === void 0 ? void 0 : _a.nonce) || ""; m.head.append(a); }))); // @ts-ignore d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = function (f) { for (var _len = arguments.length, n = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { n[_key - 1] = arguments[_key]; } return r.add(f) && u().then(() => d[l](f, ...n)); }; })(params); /* eslint-enable */ } // While most libraries populate the global namespace when loaded via bootstrap params, // this is not the case for "marker" when used with the inline bootstrap loader // (and maybe others in the future). So ensure there is an importLibrary for each: var libraryPromises = this.libraries.map(library => this.importLibrary(library)); // ensure at least one library, to kick off loading... if (!libraryPromises.length) { libraryPromises.push(this.importLibrary("core")); } Promise.all(libraryPromises).then(() => this.callback(), error => { var event = new ErrorEvent("error", { error }); // for backwards compat this.loadErrorCallback(event); }); } /** * Reset the loader state. */ reset() { this.deleteScript(); this.done = false; this.loading = false; this.errors = []; this.onerrorEvent = null; } resetIfRetryingFailed() { if (this.failed) { this.reset(); } } loadErrorCallback(e) { this.errors.push(e); if (this.errors.length <= this.retries) { var delay = this.errors.length * Math.pow(2, this.errors.length); console.error("Failed to load Google Maps script, retrying in ".concat(delay, " ms.")); setTimeout(() => { this.deleteScript(); this.setScript(); }, delay); } else { this.onerrorEvent = e; this.callback(); } } callback() { this.done = true; this.loading = false; this.callbacks.forEach(cb => { cb(this.onerrorEvent); }); this.callbacks = []; } execute() { this.resetIfRetryingFailed(); if (this.loading) { // do nothing but wait return; } if (this.done) { this.callback(); } else { // short circuit and warn if google.maps is already loaded if (window.google && window.google.maps && window.google.maps.version) { console.warn("Google Maps already loaded outside @googlemaps/js-api-loader. " + "This may result in undesirable behavior as options and script parameters may not match."); this.callback(); return; } this.loading = true; this.setScript(); } } } var defaultLibraries = ['maps']; function useJsApiLoader(_ref) { var { id = defaultLoadScriptProps.id, version = defaultLoadScriptProps.version, nonce, googleMapsApiKey, // googleMapsClientId, language, region, libraries = defaultLibraries, preventGoogleFontsLoading, // channel, mapIds, authReferrerPolicy } = _ref; var isMounted = useRef(false); var [isLoaded, setLoaded] = useState(false); var [loadError, setLoadError] = useState(undefined); useEffect(function trackMountedState() { isMounted.current = true; return () => { isMounted.current = false; }; }, []); var loader = useMemo(() => { return new Loader({ id, apiKey: googleMapsApiKey, version, libraries, language: language || 'en', region: region || 'US', mapIds: mapIds || [], nonce: nonce || '', authReferrerPolicy: authReferrerPolicy || 'origin' }); }, [id, googleMapsApiKey, version, libraries, language, region, mapIds, nonce, authReferrerPolicy]); useEffect(function effect() { if (isLoaded) { return; } else { loader.load().then(() => { if (isMounted.current) { setLoaded(true); } return; }).catch(error => { setLoadError(error); }); } }, []); useEffect(() => { if (isBrowser && preventGoogleFontsLoading) { preventGoogleFonts(); } }, [preventGoogleFontsLoading]); var prevLibraries = useRef(); useEffect(() => { if (prevLibraries.current && libraries !== prevLibraries.current) { console.warn('Performance warning! LoadScript has been reloaded unintentionally! You should not pass `libraries` prop as new array. Please keep an array of libraries as static class property for Components and PureComponents, or just a const variable outside of component, or somewhere in config files or ENV variables'); } prevLibraries.current = libraries; }, [libraries]); return { isLoaded, loadError }; } function ownKeys$f(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$f(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$f(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$f(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var eventMap$h = {}; var updaterMap$h = { options(instance, options) { instance.setOptions(options); } }; function TrafficLayerFunctional(_ref) { var { options, onLoad, onUnmount } = _ref; var map = useContext(MapContext); var [instance, setInstance] = useState(null); // Order does matter useEffect(() => { if (instance !== null) { instance.setMap(map); } }, [map]); useEffect(() => { if (options && instance !== null) { instance.setOptions(options); } }, [instance, options]); useEffect(() => { var trafficLayer = new google.maps.TrafficLayer(_objectSpread$f(_objectSpread$f({}, options), {}, { map })); setInstance(trafficLayer); if (onLoad) { onLoad(trafficLayer); } return () => { if (instance !== null) { if (onUnmount) { onUnmount(instance); } instance.setMap(null); } }; }, []); return null; } var TrafficLayerF = memo(TrafficLayerFunctional); class TrafficLayer extends PureComponent { constructor() { super(...arguments); _defineProperty(this, "state", { trafficLayer: null }); _defineProperty(this, "setTrafficLayerCallback", () => { if (this.state.trafficLayer !== null && this.props.onLoad) { this.props.onLoad(this.state.trafficLayer); } }); _defineProperty(this, "registeredEvents", []); } componentDidMount() { var trafficLayer = new google.maps.TrafficLayer(_objectSpread$f(_objectSpread$f({}, this.props.options), {}, { map: this.context })); this.registeredEvents = applyUpdatersToPropsAndRegisterEvents({ updaterMap: updaterMap$h, eventMap: eventMap$h, prevProps: {}, nextProps: this.props, instance: trafficLayer }); this.setState(function setTrafficLayer() { return { trafficLayer };