diff --git a/samples/ui-kit-place-details/README.md b/samples/ui-kit-place-details/README.md new file mode 100644 index 00000000..62904810 --- /dev/null +++ b/samples/ui-kit-place-details/README.md @@ -0,0 +1,33 @@ +# Google Maps JavaScript Sample + +This sample is generated from @googlemaps/js-samples located at +https://github.com/googlemaps-samples/js-api-samples. + +## Setup + +### Before starting run: + +`$npm i` + +### Run an example on a local web server + +First `cd` to the folder for the sample to run, then: + +`$npm start` + +### Build an individual example + +From `samples/`: + +`$npm run build --workspace=sample-name/` + +### Build all of the examples. + +From `samples/`: +`$npm run build-all` + +## Feedback + +For feedback related to this sample, please open a new issue on +[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues). + diff --git a/samples/ui-kit-place-details/index.html b/samples/ui-kit-place-details/index.html new file mode 100644 index 00000000..1e4bac58 --- /dev/null +++ b/samples/ui-kit-place-details/index.html @@ -0,0 +1,31 @@ + + + + + + Click on the map to view place details + + + + + +

Click on the map to view place details

+ + + + + + + + + + \ No newline at end of file diff --git a/samples/ui-kit-place-details/index.ts b/samples/ui-kit-place-details/index.ts new file mode 100644 index 00000000..4d7539a9 --- /dev/null +++ b/samples/ui-kit-place-details/index.ts @@ -0,0 +1,76 @@ +/* + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_ui_kit_place_details] */ +// Use querySelector to select elements for interaction. +/* [START maps_ui_kit_place_details_query_selector] */ +const map = document.querySelector('gmp-map') as any; +const placeDetails = document.querySelector('gmp-place-details') as any; +const marker = document.querySelector('gmp-advanced-marker') as any; +/* [END maps_ui_kit_place_details_query_selector] */ + +async function initMap(): Promise { + // Request needed libraries. + const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; + const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; + const { Place } = await google.maps.importLibrary("places") as google.maps.PlacesLibrary; + + // Calls the geolocation helper function to center the map on the current + // device location. + findCurrentLocation(); + + // Hide the map type control. + map.innerMap.setOptions({mapTypeControl: false}); + + /* [START maps_ui_kit_place_details_event] */ + // Add an event listener to handle map clicks. + map.innerMap.addListener('click', async (event) => { + marker.position = null; + event.stop(); + placeDetails.style.visibility = 'visible'; + if (event.placeId) { + // Fire when the user clicks a POI. + await placeDetails.configureFromPlace({id: event.placeId}); + } else { + // Fire when the user clicks the map (not on a POI). + await placeDetails.configureFromLocation(event.latLng); + } + // Show the marker at the selected place. + marker.position = placeDetails.place.location; + marker.style.display = 'block'; + }); +} +/* [END maps_ui_kit_place_details_event] */ + +// Helper function for geolocation. +async function findCurrentLocation() { + const { LatLng } = await google.maps.importLibrary('core') as google.maps.CoreLibrary; + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + (position) => { + const pos = + new LatLng(position.coords.latitude, position.coords.longitude); + map.innerMap.panTo(pos); + map.innerMap.setZoom(16); + }, + () => { + console.log('The Geolocation service failed.'); + map.innerMap.setZoom(16); + }, + ); + } else { + console.log('Your browser doesn\'t support geolocation'); + map.innerMap.setZoom(16); + } +} + +declare global { + interface Window { + initMap: () => void; + } +} +window.initMap = initMap; +/* [END maps_ui_kit_place_details] */ +export {}; \ No newline at end of file diff --git a/samples/ui-kit-place-details/package.json b/samples/ui-kit-place-details/package.json new file mode 100644 index 00000000..4aa81d59 --- /dev/null +++ b/samples/ui-kit-place-details/package.json @@ -0,0 +1,15 @@ +{ + "name": "@js-api-samples/ui-kit-place-details", + "version": "1.0.0", + "scripts": { + "build": "tsc && bash ../jsfiddle.sh ui-kit-place-details && bash ../app.sh ui-kit-place-details && bash ../docs.sh ui-kit-place-details && npm run build:vite --workspace=. && bash ../dist.sh ui-kit-place-details", + "test": "tsc && npm run build:vite --workspace=.", + "start": "tsc && vite build --base './' && vite", + "build:vite": "vite build --base './'", + "preview": "vite preview" + }, + "dependencies": { + + } + } + \ No newline at end of file diff --git a/samples/ui-kit-place-details/style.css b/samples/ui-kit-place-details/style.css new file mode 100644 index 00000000..95d6cc33 --- /dev/null +++ b/samples/ui-kit-place-details/style.css @@ -0,0 +1,37 @@ +/* + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_ui_kit_place_details] */ +/* + * Optional: Makes the sample page fill the window. + */ +html, +body { + height: 100%; + margin: 0; + font-family: Arial, Helvetica, sans-serif; +} + +h1 { + font-size: 16px; + text-align: center; +} + +gmp-map { + height: 400px; +} + +gmp-place-details { + visibility: hidden; + background-color: #fff; + border-radius: 8px; + margin: 20px; + width: 400px; +} + +gmp-advanced-marker { + display: none; +} +/* [END maps_ui_kit_place_details] */ \ No newline at end of file diff --git a/samples/ui-kit-place-details/tsconfig.json b/samples/ui-kit-place-details/tsconfig.json new file mode 100644 index 00000000..09179087 --- /dev/null +++ b/samples/ui-kit-place-details/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "strict": true, + "noImplicitAny": false, + "lib": [ + "es2015", + "esnext", + "es6", + "dom", + "dom.iterable" + ], + "moduleResolution": "Node", + "jsx": "preserve" + } + } \ No newline at end of file diff --git a/samples/ui-kit-place-search/README.md b/samples/ui-kit-place-search/README.md new file mode 100644 index 00000000..62904810 --- /dev/null +++ b/samples/ui-kit-place-search/README.md @@ -0,0 +1,33 @@ +# Google Maps JavaScript Sample + +This sample is generated from @googlemaps/js-samples located at +https://github.com/googlemaps-samples/js-api-samples. + +## Setup + +### Before starting run: + +`$npm i` + +### Run an example on a local web server + +First `cd` to the folder for the sample to run, then: + +`$npm start` + +### Build an individual example + +From `samples/`: + +`$npm run build --workspace=sample-name/` + +### Build all of the examples. + +From `samples/`: +`$npm run build-all` + +## Feedback + +For feedback related to this sample, please open a new issue on +[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues). + diff --git a/samples/ui-kit-place-search/index.html b/samples/ui-kit-place-search/index.html new file mode 100644 index 00000000..d8de3c01 --- /dev/null +++ b/samples/ui-kit-place-search/index.html @@ -0,0 +1,43 @@ + + + + + + Place List Nearby Search with Google Maps + + + + + +

Place List Nearby Search with Google Maps

+ + +
+
+ +
+
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/samples/ui-kit-place-search/index.ts b/samples/ui-kit-place-search/index.ts new file mode 100644 index 00000000..f71fe30c --- /dev/null +++ b/samples/ui-kit-place-search/index.ts @@ -0,0 +1,133 @@ +/* + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_ui_kit_place_search] */ +/* [START maps_ui_kit_place_search_query_selectors] */ +const map = document.querySelector("gmp-map") as any; +const placeList = document.querySelector("gmp-place-list") as any; +const typeSelect = document.querySelector(".type-select") as any; +const placeDetails = document.querySelector("gmp-place-details") as any; +let marker = document.querySelector('gmp-advanced-marker') as any; +/* [END maps_ui_kit_place_search_query_selectors] */ +let markers = {}; +let infowindow; +let mapCenter; + +async function initMap(): Promise { + await google.maps.importLibrary("places"); + const { InfoWindow } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary; + const { spherical } = await google.maps.importLibrary("geometry") as google.maps.GeometryLibrary; + + infowindow = new google.maps.InfoWindow; + + function getContainingCircle(bounds) { + const diameter = spherical.computeDistanceBetween( + bounds.getNorthEast(), + bounds.getSouthWest() + ); + return { center: bounds.getCenter(), radius: diameter / 2 }; + } + + findCurrentLocation(); + + map.innerMap.setOptions({ + mapTypeControl: false, + clickableIcons: false, + }); + + /* [START maps_ui_kit_place_search_event] */ + typeSelect.addEventListener("change", (event) => { + // First remove all existing markers. + for(marker in markers){ + console.log(marker); + markers[marker].map = null; + } + markers = {}; + + if (typeSelect.value) { + placeList.configureFromSearchNearbyRequest({ + locationRestriction: getContainingCircle( + map.innerMap.getBounds() + ), + includedPrimaryTypes: [typeSelect.value], + }).then(addMarkers); + + placeList.addEventListener("gmp-placeselect", ({ place }) => { + markers[place.id].click(); + }); + } + }); + /* [END maps_ui_kit_place_search_event] */ +} + +async function addMarkers(){ + const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary; + const { LatLngBounds } = await google.maps.importLibrary("core") as google.maps.CoreLibrary; + + const bounds = new LatLngBounds(); + + if(placeList.places.length > 0){ + placeList.places.forEach((place) => { + let marker = new AdvancedMarkerElement({ + map: map.innerMap, + position: place.location + }); + + markers[place.id] = marker; + bounds.extend(place.location); + + marker.addListener('gmp-click',(event) => { + if(infowindow.isOpen){ + infowindow.close(); + } + placeDetails.configureFromPlace(place); + placeDetails.style.width = "350px"; + infowindow.setOptions({ + content: placeDetails + }); + infowindow.open({ + anchor: marker, + map: map.innerMap + }); + placeDetails.addEventListener('gmp-load',() => { + map.innerMap.fitBounds(place.viewport, {top: placeDetails.offsetHeight || 206, left: 200}); + }); + + }); + map.innerMap.setCenter(bounds.getCenter()); + map.innerMap.fitBounds(bounds); + }); + } +} + +async function findCurrentLocation(){ + const { LatLng } = await google.maps.importLibrary("core") as google.maps.CoreLibrary; + if (navigator.geolocation) { + navigator.geolocation.getCurrentPosition( + (position) => { + const pos = new LatLng(position.coords.latitude,position.coords.longitude); + map.innerMap.panTo(pos); + map.innerMap.setZoom(14); + }, + () => { + console.log('The Geolocation service failed.'); + map.innerMap.setZoom(14); + }, + ); + } else { + console.log("Your browser doesn't support geolocation"); + map.innerMap.setZoom(14); + } + +} + +declare global { + interface Window { + initMap: () => void; + } + } + window.initMap = initMap; +/* [END maps_ui_kit_place_search] */ +export{}; \ No newline at end of file diff --git a/samples/ui-kit-place-search/package.json b/samples/ui-kit-place-search/package.json new file mode 100644 index 00000000..59d2713a --- /dev/null +++ b/samples/ui-kit-place-search/package.json @@ -0,0 +1,15 @@ +{ + "name": "@js-api-samples/ui-kit-place-search", + "version": "1.0.0", + "scripts": { + "build": "tsc && bash ../jsfiddle.sh ui-kit-place-search && bash ../app.sh ui-kit-place-search && bash ../docs.sh ui-kit-place-search && npm run build:vite --workspace=. && bash ../dist.sh ui-kit-place-search", + "test": "tsc && npm run build:vite --workspace=.", + "start": "tsc && vite build --base './' && vite", + "build:vite": "vite build --base './'", + "preview": "vite preview" + }, + "dependencies": { + + } + } + \ No newline at end of file diff --git a/samples/ui-kit-place-search/style.css b/samples/ui-kit-place-search/style.css new file mode 100644 index 00000000..d432723d --- /dev/null +++ b/samples/ui-kit-place-search/style.css @@ -0,0 +1,66 @@ +/* + * @license + * Copyright 2025 Google LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/* [START maps_ui_kit_place_search] */ +html, + body { + height: 100%; + margin: 0; + } + + body { + display: flex; + flex-direction: column; + font-family: Arial, Helvetica, sans-serif; + } + + h1 { + font-size: 16px; + text-align: center; + } + + gmp-map { + box-sizing: border-box; + padding: 0 20px 20px; + } + + .overlay { + margin: 20px; + width: 400px; + } + + .controls { + display: flex; + gap: 10px; + margin-bottom: 10px; + height: 32px; + } + + .search-button { + background-color: #5491f5; + color: #fff; + border: 1px solid #ccc; + border-radius: 5px; + width: 100px; + cursor: pointer; + } + + .type-select { + border: 1px solid #ccc; + border-radius: 5px; + flex-grow: 1; + padding: 0 10px; + } + + .list-container { + height: 600px; + overflow: auto; + border-radius: 10px; + } + + gmp-place-list { + background-color: #fff; + } +/* [END maps_ui_kit_place_search] */ \ No newline at end of file diff --git a/samples/ui-kit-place-search/tsconfig.json b/samples/ui-kit-place-search/tsconfig.json new file mode 100644 index 00000000..09179087 --- /dev/null +++ b/samples/ui-kit-place-search/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "esnext", + "target": "esnext", + "strict": true, + "noImplicitAny": false, + "lib": [ + "es2015", + "esnext", + "es6", + "dom", + "dom.iterable" + ], + "moduleResolution": "Node", + "jsx": "preserve" + } + } \ No newline at end of file