From 5176df844c63a8afb73f3e4abd87c4f3f28e7ad7 Mon Sep 17 00:00:00 2001 From: Malte Modrow Date: Wed, 7 Feb 2024 16:14:33 +0100 Subject: [PATCH] docs: add new autocomplete example (#198) --- docs/api-reference/hooks/use-autocomplete.md | 61 --------- .../interacting-with-google-maps-api.md | 1 - docs/table-of-contents.json | 3 +- examples/autocomplete/README.md | 58 +++++++++ examples/autocomplete/index.html | 31 +++++ examples/autocomplete/package.json | 15 +++ examples/autocomplete/src/app.tsx | 59 +++++++++ .../autocomplete/src/autocomplete-alpha.tsx | 44 +++++++ .../autocomplete/src/autocomplete-classic.tsx | 39 ++++++ .../src/autocomplete-custom-hybrid.tsx | 120 ++++++++++++++++++ .../autocomplete/src/autocomplete-custom.tsx | 115 +++++++++++++++++ examples/autocomplete/src/control-panel.tsx | 81 ++++++++++++ examples/autocomplete/src/map-control.tsx | 40 ++++++ examples/autocomplete/src/map-handler.tsx | 22 ++++ examples/autocomplete/vite.config.js | 17 +++ examples/examples.css | 44 +++++++ .../__snapshots__/autocomplete.test.tsx.snap | 7 - src/hooks/__tests__/autocomplete.test.tsx | 69 ---------- src/hooks/autocomplete.ts | 66 ---------- src/index.ts | 1 - website/src/examples-sidebar.js | 1 + website/src/examples/autocomplete.mdx | 6 + .../static/images/examples/autocomplete.jpg | Bin 0 -> 55641 bytes 23 files changed, 693 insertions(+), 207 deletions(-) delete mode 100644 docs/api-reference/hooks/use-autocomplete.md create mode 100644 examples/autocomplete/README.md create mode 100644 examples/autocomplete/index.html create mode 100644 examples/autocomplete/package.json create mode 100644 examples/autocomplete/src/app.tsx create mode 100644 examples/autocomplete/src/autocomplete-alpha.tsx create mode 100644 examples/autocomplete/src/autocomplete-classic.tsx create mode 100644 examples/autocomplete/src/autocomplete-custom-hybrid.tsx create mode 100644 examples/autocomplete/src/autocomplete-custom.tsx create mode 100644 examples/autocomplete/src/control-panel.tsx create mode 100644 examples/autocomplete/src/map-control.tsx create mode 100644 examples/autocomplete/src/map-handler.tsx create mode 100644 examples/autocomplete/vite.config.js delete mode 100644 src/hooks/__tests__/__snapshots__/autocomplete.test.tsx.snap delete mode 100644 src/hooks/__tests__/autocomplete.test.tsx delete mode 100644 src/hooks/autocomplete.ts create mode 100644 website/src/examples/autocomplete.mdx create mode 100644 website/static/images/examples/autocomplete.jpg diff --git a/docs/api-reference/hooks/use-autocomplete.md b/docs/api-reference/hooks/use-autocomplete.md deleted file mode 100644 index 4c99a218..00000000 --- a/docs/api-reference/hooks/use-autocomplete.md +++ /dev/null @@ -1,61 +0,0 @@ -# `useAutocomplete` Hook - -React hook to use the Google Maps Platform [Places Autocomplete Widget](https://developers.google.com/maps/documentation/javascript/reference/places-widget) in any component. - -## Usage - -When initializing the ``, include the places library like this: `libraries={['places']}`. - -```tsx -import React, {useRef, useState} from 'react'; -import {useAutocomplete} from '@vis.gl/react-google-maps'; - -const MyComponent = () => { - const inputRef = useRef(null); - const [inputValue, setInputValue] = useState(''); - - const onPlaceChanged = place => { - if (place) { - setInputValue(place.formatted_address || place.name); - } - - // Keep focus on input element - inputRef.current && inputRef.current.focus(); - }; - - useAutocomplete({ - inputField: inputRef && inputRef.current, - onPlaceChanged - }); - - const handleInputChange = event => { - setInputValue(event.target.value); - }; - - return ( - - ); -}; -``` - -## Parameters - -### AutocompleteProps - -Needs a reference to an Input field, some optional [AutocompleteOptions](https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions) and a callback for when a place got changed. - -```TypeScript -interface AutocompleteProps { - inputField: HTMLInputElement | null; - options?: google.maps.places.AutocompleteOptions; - onPlaceChanged: (place: google.maps.places.PlaceResult) => void; -} -``` - -## Return value - -Returns an [`Autocomplete Places Widget`](https://developers.google.com/maps/documentation/javascript/reference/places-widget) instance to use directly. - -```TypeScript -google.maps.places.Autocomplete -``` diff --git a/docs/guides/interacting-with-google-maps-api.md b/docs/guides/interacting-with-google-maps-api.md index bd1a8569..dc69e221 100644 --- a/docs/guides/interacting-with-google-maps-api.md +++ b/docs/guides/interacting-with-google-maps-api.md @@ -51,7 +51,6 @@ Other hooks provide access to different Google Maps API services: - [useDirectionsService](../api-reference/hooks/use-directions-service.md) for the [Directions Service](https://developers.google.com/maps/documentation/javascript/directions) - [useStreetViewPanorama](../api-reference/hooks/use-streetview-panorama.md) for the [Streetview Service](https://developers.google.com/maps/documentation/javascript/streetview) -- [useAutocomplete](../api-reference/hooks/use-autocomplete.md) for the [Places Widget](https://developers.google.com/maps/documentation/javascript/reference/places-widget) The [useMapsLibrary](../api-reference/hooks/use-maps-library.md) hook can be utilized to load other parts of the Google Maps API that are not loaded by default. diff --git a/docs/table-of-contents.json b/docs/table-of-contents.json index 7ff7f79f..b3d2887b 100644 --- a/docs/table-of-contents.json +++ b/docs/table-of-contents.json @@ -52,8 +52,7 @@ "api-reference/hooks/use-api-is-loaded", "api-reference/hooks/use-maps-library", "api-reference/hooks/use-directions-service", - "api-reference/hooks/use-streetview-panorama", - "api-reference/hooks/use-autocomplete" + "api-reference/hooks/use-streetview-panorama" ] } ] diff --git a/examples/autocomplete/README.md b/examples/autocomplete/README.md new file mode 100644 index 00000000..928f7f8d --- /dev/null +++ b/examples/autocomplete/README.md @@ -0,0 +1,58 @@ +# Autocomplete Examples + +Here you can find a few example implementations of the autocomplete functionality utilizing the Google Places API. + +## Examples + +We have three different implementations to demonstrate how to add autocomplete functionality to your application + +### 1) Google Maps Autocomplete Widget + +When using the [Google Maps Autocomplete widget][autocomplete-widget] you provide an HTML input element of your choice and Google handles all the rest. It will fetch predictions when the user types and it will get the details for a place when the user selects a prediction from the list. + +### 2) Custom Build + +When you need complete control over every aspect of your autocomplete you can choose to build your own by utilizing the [Autocomplete Service][autocomplete-service] for fetching query predictions and the [Places Service][place-details] for fetching the place details. + +When building your own you are completely free but also responsible for the user experience of the autocomplete. You are also responsible for handling the autocomplete session with a [Session token][session-token]. This can easily be overlooked and may lead to unexpected surprises when it comes to billing. + +### 3) Third Party Select Widget + +This is basically the same as the custom build, except for not having to implement the list/dropdown/DOM handling yourself. A lot of third party text box widgets provide functionionality for handling keyboard navigation and focus handling. For the demo we used the [Combobox][combobox] from `react-widgets`. + +## Google Maps API key + +This example does not come with an API key. Running the examples locally requires a valid API key for the Google Maps Platform. +See [the official documentation][get-api-key] on how to create and configure your own key. For this example to work you also need to enable the `Places API` in your Google Cloud Console. + +The API key has to be provided via an environment variable `GOOGLE_MAPS_API_KEY`. This can be done by creating a +file named `.env` in the example directory with the following content: + +```shell title=".env" +GOOGLE_MAPS_API_KEY="" +``` + +If you are on the CodeSandbox playground you can also choose to [provide the API key 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-api-key]: https://developers.google.com/maps/documentation/javascript/get-api-key +[autocomplete-widget]: https://developers.google.com/maps/documentation/javascript/place-autocomplete#add-autocomplete +[autocomplete-service]: https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteService.getPlacePredictions +[place-details]: https://developers.google.com/maps/documentation/javascript/reference/places-service#PlacesService.getDetails +[session-token]: https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteSessionToken +[combobox]: https://jquense.github.io/react-widgets/docs/Combobox diff --git a/examples/autocomplete/index.html b/examples/autocomplete/index.html new file mode 100644 index 00000000..139a567e --- /dev/null +++ b/examples/autocomplete/index.html @@ -0,0 +1,31 @@ + + + + + + Autocomplete Examples + + + + +
+ + + diff --git a/examples/autocomplete/package.json b/examples/autocomplete/package.json new file mode 100644 index 00000000..2f810a00 --- /dev/null +++ b/examples/autocomplete/package.json @@ -0,0 +1,15 @@ +{ + "type": "module", + "dependencies": { + "@vis.gl/react-google-maps": "*", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-widgets": "^5.8.4", + "vite": "^5.0.4" + }, + "scripts": { + "start": "vite", + "start-local": "vite --config ../vite.config.local.js", + "build": "vite build" + } +} diff --git a/examples/autocomplete/src/app.tsx b/examples/autocomplete/src/app.tsx new file mode 100644 index 00000000..54656f3c --- /dev/null +++ b/examples/autocomplete/src/app.tsx @@ -0,0 +1,59 @@ +import React, {useState} from 'react'; +import {createRoot} from 'react-dom/client'; +import {APIProvider, ControlPosition, Map} from '@vis.gl/react-google-maps'; + +import ControlPanel from './control-panel'; +import {CustomMapControl} from './map-control'; +import MapHandler from './map-handler'; + +const API_KEY = + globalThis.GOOGLE_MAPS_API_KEY ?? (process.env.GOOGLE_MAPS_API_KEY as string); + +export type AutocompleteMode = {id: string; label: string}; + +const autocompleteModes: Array = [ + {id: 'classic', label: 'Google Autocomplete Widget'}, + {id: 'custom', label: 'Custom Build'}, + {id: 'custom-hybrid', label: 'Custom w/ Select Widget'} +]; + +const App = () => { + const [selectedAutocompleteMode, setSelectedAutocompleteMode] = + useState(autocompleteModes[0]); + + const [selectedPlace, setSelectedPlace] = + useState(null); + + return ( + + + + + + + + + + ); +}; + +export default App; + +export function renderToDom(container: HTMLElement) { + const root = createRoot(container); + + root.render(); +} diff --git a/examples/autocomplete/src/autocomplete-alpha.tsx b/examples/autocomplete/src/autocomplete-alpha.tsx new file mode 100644 index 00000000..7114d363 --- /dev/null +++ b/examples/autocomplete/src/autocomplete-alpha.tsx @@ -0,0 +1,44 @@ +// NOTE: This requires the alpha version of the Google Maps API and is not yet +// recommended to be used in production applications. We will add this to the example map +// when it reaches GA (General Availability). Treat this as a preview of what's to come. + +import React, {useRef, useEffect, useState} from 'react'; +import {useMapsLibrary} from '@vis.gl/react-google-maps'; + +interface Props { + onPlaceSelect: (place: google.maps.places.PlaceResult | null) => void; +} + +// This is an example of the new "PlaceAutocomplete" widget. +// https://developers.google.com/maps/documentation/javascript/place-autocomplete-new +export const PlaceAutocompleteNew = ({onPlaceSelect}: Props) => { + const [placeAutocomplete, setPlaceAutocomplete] = useState(null); + const containerRef = useRef(null); + const places = useMapsLibrary('places'); + + useEffect(() => { + if (!places) return; + // @ts-expect-error Using an alpha feature here. The types are not up to date yet + setPlaceAutocomplete(new places.PlaceAutocompleteElement()); + }, [places]); + + useEffect(() => { + if (!placeAutocomplete) return; + + placeAutocomplete.addEventListener( + 'gmp-placeselect', + // @ts-expect-error This new event has no types yet + async ({place}: {place: google.maps.places.Place}) => { + await place.fetchFields({ + fields: ['displayName', 'formattedAddress', 'location', 'viewport'] + }); + + onPlaceSelect(place.toJSON()); + } + ); + + containerRef.current?.appendChild(placeAutocomplete); + }, [onPlaceSelect, placeAutocomplete]); + + return
; +}; diff --git a/examples/autocomplete/src/autocomplete-classic.tsx b/examples/autocomplete/src/autocomplete-classic.tsx new file mode 100644 index 00000000..49448abf --- /dev/null +++ b/examples/autocomplete/src/autocomplete-classic.tsx @@ -0,0 +1,39 @@ +import React, {useRef, useEffect, useState} from 'react'; +import {useMapsLibrary} from '@vis.gl/react-google-maps'; + +interface Props { + onPlaceSelect: (place: google.maps.places.PlaceResult | null) => void; +} + +// This is an example of the classic "Place Autocomplete" widget. +// https://developers.google.com/maps/documentation/javascript/place-autocomplete +export const PlaceAutocompleteClassic = ({onPlaceSelect}: Props) => { + const [placeAutocomplete, setPlaceAutocomplete] = + useState(null); + const inputRef = useRef(null); + const places = useMapsLibrary('places'); + + useEffect(() => { + if (!places || !inputRef.current) return; + + const options = { + fields: ['geometry', 'name', 'formatted_address'] + }; + + setPlaceAutocomplete(new places.Autocomplete(inputRef.current, options)); + }, [places]); + + useEffect(() => { + if (!placeAutocomplete) return; + + placeAutocomplete.addListener('place_changed', () => { + onPlaceSelect(placeAutocomplete.getPlace()); + }); + }, [onPlaceSelect, placeAutocomplete]); + + return ( +
+ +
+ ); +}; diff --git a/examples/autocomplete/src/autocomplete-custom-hybrid.tsx b/examples/autocomplete/src/autocomplete-custom-hybrid.tsx new file mode 100644 index 00000000..0acd1dcd --- /dev/null +++ b/examples/autocomplete/src/autocomplete-custom-hybrid.tsx @@ -0,0 +1,120 @@ +import React, {useEffect, useState, useCallback} from 'react'; +import {useMap, useMapsLibrary} from '@vis.gl/react-google-maps'; +import Combobox from 'react-widgets/Combobox'; + +import 'react-widgets/styles.css'; + +interface Props { + onPlaceSelect: (place: google.maps.places.PlaceResult | null) => void; +} + +// This uses the Combobox from "react-widgets" (https://jquense.github.io/react-widgets/docs/Combobox) +export const AutocompleteCustomHybrid = ({onPlaceSelect}: Props) => { + const map = useMap(); + const places = useMapsLibrary('places'); + + // https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteSessionToken + const [sessionToken, setSessionToken] = + useState(); + + // https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service + const [autocompleteService, setAutocompleteService] = + useState(null); + + // https://developers.google.com/maps/documentation/javascript/reference/places-service + const [placesService, setPlacesService] = + useState(null); + + const [predictionResults, setPredictionResults] = useState< + Array + >([]); + + const [inputValue, setInputValue] = useState(''); + + const [fetchingData, setFetchingData] = useState(false); + + useEffect(() => { + if (!places || !map) return; + + setAutocompleteService(new places.AutocompleteService()); + setPlacesService(new places.PlacesService(map)); + setSessionToken(new places.AutocompleteSessionToken()); + + return () => setAutocompleteService(null); + }, [map, places]); + + const fetchPredictions = useCallback( + async (inputValue: string) => { + if (!autocompleteService || !inputValue) { + return; + } + + setFetchingData(true); + + const request = {input: inputValue, sessionToken}; + const response = await autocompleteService.getPlacePredictions(request); + + setPredictionResults(response.predictions); + setFetchingData(false); + }, + [autocompleteService, sessionToken] + ); + + const onInputChange = useCallback( + (value: google.maps.places.AutocompletePrediction | string) => { + if (typeof value === 'string') { + setInputValue(value); + fetchPredictions(value); + } + }, + [fetchPredictions] + ); + + const onSelect = useCallback( + (prediction: google.maps.places.AutocompletePrediction | string) => { + if (!places || typeof prediction === 'string') return; + + setFetchingData(true); + + const detailRequestOptions = { + placeId: prediction.place_id, + fields: ['geometry', 'name', 'formatted_address'], + sessionToken + }; + + const detailsRequestCallback = ( + placeDetails: google.maps.places.PlaceResult | null + ) => { + onPlaceSelect(placeDetails); + setInputValue(placeDetails?.formatted_address ?? ''); + setSessionToken(new places.AutocompleteSessionToken()); + + setFetchingData(false); + }; + + placesService?.getDetails(detailRequestOptions, detailsRequestCallback); + }, + [onPlaceSelect, places, placesService, sessionToken] + ); + + return ( +
+ true} + focusFirstItem={true} + hideEmptyPopup + hideCaret + /> +
+ ); +}; diff --git a/examples/autocomplete/src/autocomplete-custom.tsx b/examples/autocomplete/src/autocomplete-custom.tsx new file mode 100644 index 00000000..eff9a05c --- /dev/null +++ b/examples/autocomplete/src/autocomplete-custom.tsx @@ -0,0 +1,115 @@ +import React, {useEffect, useState, useCallback, FormEvent} from 'react'; +import {useMap, useMapsLibrary} from '@vis.gl/react-google-maps'; + +interface Props { + onPlaceSelect: (place: google.maps.places.PlaceResult | null) => void; +} + +// This is a custom built autocomplete component using the "Autocomplete Service" for predictions +// and the "Places Service" for place details +export const AutocompleteCustom = ({onPlaceSelect}: Props) => { + const map = useMap(); + const places = useMapsLibrary('places'); + + // https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteSessionToken + const [sessionToken, setSessionToken] = + useState(); + + // https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service + const [autocompleteService, setAutocompleteService] = + useState(null); + + // https://developers.google.com/maps/documentation/javascript/reference/places-service + const [placesService, setPlacesService] = + useState(null); + + const [predictionResults, setPredictionResults] = useState< + Array + >([]); + + const [inputValue, setInputValue] = useState(''); + + useEffect(() => { + if (!places || !map) return; + + setAutocompleteService(new places.AutocompleteService()); + setPlacesService(new places.PlacesService(map)); + setSessionToken(new places.AutocompleteSessionToken()); + + return () => setAutocompleteService(null); + }, [map, places]); + + const fetchPredictions = useCallback( + async (inputValue: string) => { + if (!autocompleteService || !inputValue) { + setPredictionResults([]); + return; + } + + const request = {input: inputValue, sessionToken}; + const response = await autocompleteService.getPlacePredictions(request); + + setPredictionResults(response.predictions); + }, + [autocompleteService, sessionToken] + ); + + const onInputChange = useCallback( + (event: FormEvent) => { + const value = (event.target as HTMLInputElement)?.value; + + setInputValue(value); + fetchPredictions(value); + }, + [fetchPredictions] + ); + + const handleSuggestionClick = useCallback( + (placeId: string) => { + if (!places) return; + + const detailRequestOptions = { + placeId, + fields: ['geometry', 'name', 'formatted_address'], + sessionToken + }; + + const detailsRequestCallback = ( + placeDetails: google.maps.places.PlaceResult | null + ) => { + onPlaceSelect(placeDetails); + setPredictionResults([]); + setInputValue(placeDetails?.formatted_address ?? ''); + setSessionToken(new places.AutocompleteSessionToken()); + }; + + placesService?.getDetails(detailRequestOptions, detailsRequestCallback); + }, + [onPlaceSelect, places, placesService, sessionToken] + ); + + return ( +
+ ) => onInputChange(event)} + placeholder="Search for a place" + /> + + {predictionResults.length > 0 && ( +
    + {predictionResults.map(({place_id, description}) => { + return ( +
  • handleSuggestionClick(place_id)}> + {description} +
  • + ); + })} +
+ )} +
+ ); +}; diff --git a/examples/autocomplete/src/control-panel.tsx b/examples/autocomplete/src/control-panel.tsx new file mode 100644 index 00000000..4d1dae4c --- /dev/null +++ b/examples/autocomplete/src/control-panel.tsx @@ -0,0 +1,81 @@ +import * as React from 'react'; +import {AutocompleteMode} from './app'; + +interface Props { + autocompleteModes: Array; + selectedAutocompleteMode: AutocompleteMode; + onAutocompleteModeChange: (autocompleteMode: AutocompleteMode) => void; +} + +function ControlPanel({ + autocompleteModes, + selectedAutocompleteMode, + onAutocompleteModeChange +}: Props) { + return ( +
+

Autocomplete Example

+ +

+ This example demonstrates three different methods of adding autocomplete + functionality to your appplication using the Google Maps Places API. +

+ +
+

Choose the example style:

+ +
+ + {selectedAutocompleteMode.id === 'classic' && ( +
+ This is the easiest to setup. You only need an input element and + Google handles the rest. +
+ )} + {selectedAutocompleteMode.id === 'custom' && ( +
+ This is the most flexible solution, but also requires quite a bit + effort to get right. The example only implements a basic working + version for demonstration purposes. +
+ )} + {selectedAutocompleteMode.id === 'custom-hybrid' && ( +
+ This has the benefits of custom look, feel and solid UX out of the + box, but you still have to manage the prediction and details fetching + as well as the session yourself. +
+ )} + +
+ ); +} + +export default React.memo(ControlPanel); diff --git a/examples/autocomplete/src/map-control.tsx b/examples/autocomplete/src/map-control.tsx new file mode 100644 index 00000000..be4368b7 --- /dev/null +++ b/examples/autocomplete/src/map-control.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import {ControlPosition, MapControl} from '@vis.gl/react-google-maps'; + +import {PlaceAutocompleteClassic} from './autocomplete-classic'; +import {AutocompleteCustom} from './autocomplete-custom'; + +import {AutocompleteCustomHybrid} from './autocomplete-custom-hybrid'; +import type {AutocompleteMode} from './app'; + +type CustomAutocompleteControlProps = { + controlPosition: ControlPosition; + selectedAutocompleteMode: AutocompleteMode; + onPlaceSelect: (place: google.maps.places.PlaceResult | null) => void; +}; + +export const CustomMapControl = ({ + controlPosition, + selectedAutocompleteMode, + onPlaceSelect +}: CustomAutocompleteControlProps) => { + const {id} = selectedAutocompleteMode; + + return ( + +
+ {id === 'classic' && ( + + )} + + {id === 'custom' && ( + + )} + + {id === 'custom-hybrid' && ( + + )} +
+
+ ); +}; diff --git a/examples/autocomplete/src/map-handler.tsx b/examples/autocomplete/src/map-handler.tsx new file mode 100644 index 00000000..83c59df7 --- /dev/null +++ b/examples/autocomplete/src/map-handler.tsx @@ -0,0 +1,22 @@ +import {useMap} from '@vis.gl/react-google-maps'; +import React, {useEffect} from 'react'; + +interface Props { + place: google.maps.places.PlaceResult | null; +} + +const MapHandler = ({place}: Props) => { + const map = useMap(); + + useEffect(() => { + if (!map || !place) return; + + if (place.geometry?.viewport) { + map.fitBounds(place.geometry?.viewport); + } + }, [map, place]); + + return null; +}; + +export default React.memo(MapHandler); diff --git a/examples/autocomplete/vite.config.js b/examples/autocomplete/vite.config.js new file mode 100644 index 00000000..522c6cb9 --- /dev/null +++ b/examples/autocomplete/vite.config.js @@ -0,0 +1,17 @@ +import {defineConfig, loadEnv} from 'vite'; + +export default defineConfig(({mode}) => { + const {GOOGLE_MAPS_API_KEY = ''} = loadEnv(mode, process.cwd(), ''); + + return { + define: { + 'process.env.GOOGLE_MAPS_API_KEY': JSON.stringify(GOOGLE_MAPS_API_KEY) + }, + resolve: { + alias: { + '@vis.gl/react-google-maps/examples.js': + 'https://visgl.github.io/react-google-maps/scripts/examples.js' + } + } + }; +}); diff --git a/examples/examples.css b/examples/examples.css index e9bcddf3..d2f7f47c 100644 --- a/examples/examples.css +++ b/examples/examples.css @@ -20,6 +20,11 @@ margin: 8px 0; } +.control-panel h4 { + font-weight: 500; + margin: 8px 0; +} + .control-panel p { margin-bottom: 16px; } @@ -43,3 +48,42 @@ html[data-theme='dark'] .control-panel { html[data-theme='dark'] .gm-style { color: var(--ifm-color-black); } +.autocomplete-container input, +.autocomplete-control { + box-sizing: border-box; +} + +.autocomplete-control { + margin: 24px; + background: #fff; +} + +.autocomplete-container { + width: 300px; +} +.autocomplete-container input { + width: 100%; + height: 40px; + padding: 0 12px; + font-size: 18px; +} + +.autocomplete-container .custom-list { + width: 100%; + list-style: none; + padding: 0; + margin: 0; +} + +.autocomplete-container .custom-list-item { + padding: 8px; +} + +.autocomplete-container .custom-list-item:hover { + background: lightgrey; + cursor: pointer; +} + +.autocomplete-mode { + margin: 8px 0; +} diff --git a/src/hooks/__tests__/__snapshots__/autocomplete.test.tsx.snap b/src/hooks/__tests__/__snapshots__/autocomplete.test.tsx.snap deleted file mode 100644 index 790011a7..00000000 --- a/src/hooks/__tests__/__snapshots__/autocomplete.test.tsx.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`it throws an error if the places library is missing 1`] = ` -[ - "Google Maps Places library is missing. Please add the places library to the props of the component.", -] -`; diff --git a/src/hooks/__tests__/autocomplete.test.tsx b/src/hooks/__tests__/autocomplete.test.tsx deleted file mode 100644 index fb99e6e7..00000000 --- a/src/hooks/__tests__/autocomplete.test.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React from 'react'; -import {renderHook, waitFor} from '@testing-library/react'; -import {Autocomplete, initialize} from '@googlemaps/jest-mocks'; - -import {APIProvider} from '../../components/api-provider'; -import {useAutocomplete} from '../autocomplete'; - -import {waitForMockInstance} from './__utils__/wait-for-mock-instance'; - -jest.mock('../../libraries/google-maps-api-loader'); - -let wrapper: ({children}: {children: React.ReactNode}) => JSX.Element | null; -let onPlaceChanged: jest.Mock; -let inputField: HTMLInputElement; - -beforeEach(() => { - initialize(); - - onPlaceChanged = jest.fn(); - inputField = document.createElement('input'); - - wrapper = ({children}: {children: React.ReactNode}) => ( - {children} - ); -}); - -test('it should initialize an autocomplete instance', async () => { - const {result} = renderHook( - () => useAutocomplete({inputField, onPlaceChanged}), - {wrapper} - ); - - const service = await waitForMockInstance(Autocomplete); - - expect(result.current).toBe(service); - expect(service).toBeInstanceOf(google.maps.places.Autocomplete); -}); - -test('it throws an error if the places library is missing', async () => { - // pretend the places library wasn't loaded - // @ts-expect-error - testing error case - delete google.maps.places; - - const consoleErrorSpy = jest - .spyOn(console, 'error') - .mockImplementation(() => {}); - - const {result} = renderHook( - () => useAutocomplete({inputField, onPlaceChanged}), - {wrapper} - ); - - await waitFor(() => expect(consoleErrorSpy).toHaveBeenCalled()); - - expect(result.current).toBe(null); - expect(consoleErrorSpy.mock.lastCall).toMatchSnapshot(); -}); - -test('it adds place_changed listener to autocomplete', async () => { - const {result} = renderHook( - () => useAutocomplete({inputField, onPlaceChanged}), - {wrapper} - ); - - const service = await waitForMockInstance(Autocomplete); - - expect(result.current).toBe(service); - expect(service.addListener).toHaveBeenCalled(); -}); diff --git a/src/hooks/autocomplete.ts b/src/hooks/autocomplete.ts deleted file mode 100644 index c624c12d..00000000 --- a/src/hooks/autocomplete.ts +++ /dev/null @@ -1,66 +0,0 @@ -import {useState, useRef, useEffect} from 'react'; - -import {useApiIsLoaded} from './use-api-is-loaded'; - -export interface AutocompleteProps { - inputField: HTMLInputElement | null; - options?: google.maps.places.AutocompleteOptions; - onPlaceChanged: (place: google.maps.places.PlaceResult) => void; -} - -/** - * Hook to get a Google Maps Places Autocomplete instance - * monitoring an input field - */ -export const useAutocomplete = ( - props: AutocompleteProps -): google.maps.places.Autocomplete | null => { - const {inputField, options, onPlaceChanged} = props; - - const googleMapsAPIIsLoaded = useApiIsLoaded(); - - const placeChangedHandler = useRef(onPlaceChanged); - - const [autocomplete, setAutocomplete] = - useState(null); - - // Initializes the Google Maps Places Autocomplete - useEffect(() => { - // Wait for the Google Maps API and input element to be initialized - if (!googleMapsAPIIsLoaded || !inputField) return; - - // FIXME: add dynamic loading for required libraries - if (!google.maps.places) { - console.error( - 'Google Maps Places library is missing. ' + - 'Please add the places library to the props of the ' + - 'component.' - ); - - return; - } - - // Create Autocomplete instance - const autocompleteInstance = new google.maps.places.Autocomplete( - inputField, - options - ); - - setAutocomplete(autocompleteInstance); - - // Add places change listener to Autocomplete - autocompleteInstance.addListener('place_changed', () => { - const place = autocompleteInstance.getPlace(); - if (placeChangedHandler.current) placeChangedHandler.current(place); - }); - - // Clear listeners on unmount - return () => { - if (autocompleteInstance && typeof google.maps === 'object') { - google.maps.event.clearInstanceListeners(autocompleteInstance); - } - }; - }, [googleMapsAPIIsLoaded, inputField, options]); - - return autocomplete; -}; diff --git a/src/index.ts b/src/index.ts index cd3ec628..269ccbb4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,6 @@ export * from './hooks/use-api-loading-status'; export * from './hooks/use-api-is-loaded'; export * from './hooks/use-maps-library'; export * from './hooks/use-map'; -export * from './hooks/autocomplete'; export * from './hooks/directions-service'; export * from './hooks/street-view-panorama'; diff --git a/website/src/examples-sidebar.js b/website/src/examples-sidebar.js index 31bcf963..6f96fdc8 100644 --- a/website/src/examples-sidebar.js +++ b/website/src/examples-sidebar.js @@ -15,6 +15,7 @@ const sidebars = { 'marker-clustering', 'geometry', 'change-map-styles', + 'autocomplete', 'map-control', 'directions', 'deckgl-overlay' diff --git a/website/src/examples/autocomplete.mdx b/website/src/examples/autocomplete.mdx new file mode 100644 index 00000000..64b28bd2 --- /dev/null +++ b/website/src/examples/autocomplete.mdx @@ -0,0 +1,6 @@ +# Autocomplete + +import BrowserOnly from '@docusaurus/BrowserOnly'; +import App from 'website-examples/autocomplete/src/app'; + +{() => } diff --git a/website/static/images/examples/autocomplete.jpg b/website/static/images/examples/autocomplete.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2adef070fb2ba482082eca99bad838ce98d1f2e2 GIT binary patch literal 55641 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

}P^=OCX_3pC1EmifK$Q-XOm>;6`*6l~N;vku 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 AWdHyG literal 0 HcmV?d00001