diff --git a/examples/external-js-api/README.md b/examples/external-js-api/README.md new file mode 100644 index 0000000..c2bf052 --- /dev/null +++ b/examples/external-js-api/README.md @@ -0,0 +1,38 @@ +# Externally loaded Google Maps JavaScript API + +![image](https://user-images.githubusercontent.com/39244966/208682692-d5b23518-9e51-4a87-8121-29f71e41c777.png) + +This is an example to show how to set up a simple Google map with the `` with externally loaded Google Maps JavaScript API. +For instance, you can use the Google Maps JavaScript API URL to load the API when you need to use Client ID instead of API Key. + +## Google Maps Platform API URL + +This example does not come with an API URL. Running the examples locally requires a valid Google Maps JavaScript API URL. +See [the official documentation][get-load-maps-js-api] on how to create a URL. + +The API URL has to be provided via an environment variable `GOOGLE_MAPS_API_URL`. This can be done by creating a +file named `.env` in the example directory with the following content: + +```shell title=".env" +GOOGLE_MAPS_API_URL="" +``` + +If you are on the CodeSandbox playground you can also choose to [provide the API URL like this](https://codesandbox.io/docs/learn/environment/secrets) + +## Development + +Go into the example-directory and run + +```shell +npm install +``` + +To start the example with the local library run + +```shell +npm run start-local +``` + +The regular `npm start` task is only used for the standalone versions of the example (CodeSandbox for example) + +[get-load-maps-js-api]: https://developers.google.com/maps/documentation/javascript/load-maps-js-api#direct_script_loading_url_parameters diff --git a/examples/external-js-api/index.html b/examples/external-js-api/index.html new file mode 100644 index 0000000..6e7ddfe --- /dev/null +++ b/examples/external-js-api/index.html @@ -0,0 +1,33 @@ + + + + + + Externally loaded Google Maps JavaScript API + + + + +
+ + + diff --git a/examples/external-js-api/package.json b/examples/external-js-api/package.json new file mode 100644 index 0000000..05765f9 --- /dev/null +++ b/examples/external-js-api/package.json @@ -0,0 +1,14 @@ +{ + "type": "module", + "dependencies": { + "@vis.gl/react-google-maps": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "vite": "^5.0.4" + }, + "scripts": { + "start": "vite", + "start-local": "vite --config ../vite.config.local.js", + "build": "vite build" + } +} diff --git a/examples/external-js-api/src/app.tsx b/examples/external-js-api/src/app.tsx new file mode 100644 index 0000000..a6cf4cf --- /dev/null +++ b/examples/external-js-api/src/app.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import {createRoot} from 'react-dom/client'; + +import {APIProvider, Map} from '@vis.gl/react-google-maps'; +import ControlPanel from './control-panel'; +import {useExternallyLoadedMapsAPI} from './useExternallyLoadedMapsAPI'; + +const API_URL = + globalThis.GOOGLE_MAPS_API_URL ?? (process.env.GOOGLE_MAPS_API_URL as string); + +const App = () => { + const isLoaded = useExternallyLoadedMapsAPI(API_URL); + return ( + isLoaded && ( + + + + + ) + ); +}; +export default App; + +export function renderToDom(container: HTMLElement) { + const root = createRoot(container); + + root.render( + + + + ); +} diff --git a/examples/external-js-api/src/control-panel.tsx b/examples/external-js-api/src/control-panel.tsx new file mode 100644 index 0000000..1f5d0bc --- /dev/null +++ b/examples/external-js-api/src/control-panel.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; + +function ControlPanel() { + return ( +
+

Externally loaded Google Maps JavaScript API

+

+ The example demonstrates how to load the Google Maps API externally. +

+
+ + Try on CodeSandbox ↗ + + + + View Code ↗ + +
+
+ ); +} + +export default React.memo(ControlPanel); diff --git a/examples/external-js-api/src/useExternallyLoadedMapsAPI.ts b/examples/external-js-api/src/useExternallyLoadedMapsAPI.ts new file mode 100644 index 0000000..6677169 --- /dev/null +++ b/examples/external-js-api/src/useExternallyLoadedMapsAPI.ts @@ -0,0 +1,44 @@ +import {useEffect, useRef, useState} from 'react'; + +/** + * Simple hook to load an external Maps API script and check if it is loaded. + * @param {String} url - URL of the script to load. + */ +export function useExternallyLoadedMapsAPI(url: string) { + const [isLoaded, setIsLoaded] = useState(false); + const intervalRef = useRef(null); + const scriptRef = useRef(null); + + useEffect(() => { + if (scriptRef.current?.src !== url) { + const script = document.createElement('script'); + script.src = url; + script.async = true; + script.defer = true; + script.onload = () => { + // Validate if google.maps.importLibrary is loaded, + // it is not enough to check if window.google is loaded.maps + intervalRef.current = setInterval(() => { + if (window.google?.maps?.importLibrary as unknown) { + clearInterval(intervalRef.current as unknown as number); + setIsLoaded(true); + } + }, 10); + }; + + scriptRef.current = script; + document.head.appendChild(script); + } + + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current as unknown as number); + } + if (scriptRef.current) { + document.head.removeChild(scriptRef.current); + } + }; + }, [url]); + + return isLoaded; +} diff --git a/examples/external-js-api/vite.config.js b/examples/external-js-api/vite.config.js new file mode 100644 index 0000000..4792d63 --- /dev/null +++ b/examples/external-js-api/vite.config.js @@ -0,0 +1,17 @@ +import {defineConfig, loadEnv} from 'vite'; + +export default defineConfig(({}) => { + const {GOOGLE_MAPS_API_URL = ''} = loadEnv(mode, process.cwd(), ''); + + return { + define: { + 'process.env.GOOGLE_MAPS_API_URL': JSON.stringify(GOOGLE_MAPS_API_URL) + }, + resolve: { + alias: { + '@vis.gl/react-google-maps/examples.js': + 'https://visgl.github.io/react-google-maps/scripts/examples.js' + } + } + }; +}); diff --git a/website/src/examples-sidebar.js b/website/src/examples-sidebar.js index bea0036..dbff949 100644 --- a/website/src/examples-sidebar.js +++ b/website/src/examples-sidebar.js @@ -25,7 +25,8 @@ const sidebars = { 'directions', 'deckgl-overlay', 'map-3d', - 'extended-component-library' + 'extended-component-library', + 'external-js-api', ] } ] diff --git a/website/src/examples/external-js-api.mdx b/website/src/examples/external-js-api.mdx new file mode 100644 index 0000000..78fcde3 --- /dev/null +++ b/website/src/examples/external-js-api.mdx @@ -0,0 +1,5 @@ +# Deck.gl Overlay + +import App from 'website-examples/external-js-api/src/app'; + +