From 8291c1fd04e0393563739eeba058a5f3eb492c74 Mon Sep 17 00:00:00 2001 From: Liam Meier Date: Mon, 7 Aug 2023 11:02:15 -0400 Subject: [PATCH] Make autocomplete consistent with radar sdk js (#243) * onSelect --> onSelection * Remove README, radar.com/documentation is the docs reside * Changes to match web autocomplete SDK * countryCode --> country * Revert "countryCode --> country" This reverts commit 943861dcab12cea94626b8efdc904b3663267d8b. * Take countryCode param * Enable disabled option * Update map logo * Move style to options prop * location --> near --- .../java/io/radar/react/RNRadarModule.java | 2 +- ios/RNRadar.m | 5 +- js/ui/README.md | 157 ------------------ js/ui/autocomplete.jsx | 34 ++-- js/ui/map-logo.png | Bin 11014 -> 9995 bytes 5 files changed, 27 insertions(+), 171 deletions(-) delete mode 100644 js/ui/README.md diff --git a/android/src/main/java/io/radar/react/RNRadarModule.java b/android/src/main/java/io/radar/react/RNRadarModule.java index a146e2b6..a36ab207 100644 --- a/android/src/main/java/io/radar/react/RNRadarModule.java +++ b/android/src/main/java/io/radar/react/RNRadarModule.java @@ -871,7 +871,7 @@ public void autocomplete(ReadableMap optionsMap, final Promise promise) { near.setLatitude(latitude); near.setLongitude(longitude); int limit = optionsMap.hasKey("limit") ? optionsMap.getInt("limit") : 10; - String country = optionsMap.hasKey("country") ? optionsMap.getString("country") : null; + String country = optionsMap.hasKey("countryCode") ? optionsMap.getString("countryCode") : optionsMap.hasKey("country") ? optionsMap.getString("country") : null; String[] layers = optionsMap.hasKey("layers") ? RNRadarUtils.stringArrayForArray(optionsMap.getArray("layers")) : null; Radar.autocomplete(query, near, layers, limit, country, new Radar.RadarGeocodeCallback() { diff --git a/ios/RNRadar.m b/ios/RNRadar.m index 80d44589..28f0a2f1 100644 --- a/ios/RNRadar.m +++ b/ios/RNRadar.m @@ -756,7 +756,10 @@ - (void)didLogMessage:(NSString *)message { } NSArray *layers = optionsDict[@"layers"]; - NSString *country = optionsDict[@"country"]; + NSString *country = optionsDict[@"countryCode"]; + if (country == nil) { + country = optionsDict[@"country"]; + } __block RCTPromiseResolveBlock resolver = resolve; __block RCTPromiseRejectBlock rejecter = reject; diff --git a/js/ui/README.md b/js/ui/README.md deleted file mode 100644 index f8b7a964..00000000 --- a/js/ui/README.md +++ /dev/null @@ -1,157 +0,0 @@ -## Example usage - -We provide UI elements for autocomplete & maps to make building easy. - -### Adding an address autocomplete - -Adding an address search autocomplete is straightforward. Our `` element is comprised of a TextInput and Flatlist with the results. - -The example below provides optional `location` and `onSelect` props to the component. Providing a location will improve autocomplete result quality. Without it, the API utilizes the IP address location to rank results. - -``` -import { View } from 'react-native'; -import { useState, useEffect } from 'react'; -import Radar, { Autocomplete } from 'react-native-radar'; - -export default function App() { - const [location, setLocation] = useState(null); - - useEffect(() => { - Radar.initialize('prj_live_pk_...'); - - Radar.trackOnce().then((result) => { - setLocation({ - latitude: result.location.latitude, - longitude: result.location.longitude, - }); - }); - }, []); - - const onSelect = (selectedAddress) => { - // Do something with the selected address - } - - return ( - - - - ); -} - -``` - -### Adding a map - -If you're using the Map element, you'll need to install [Maplibre React Native](https://github.com/maplibre/maplibre-react-native), which `react-native-radar` has an optional peer dependency. -``` -npm install @maplibre/maplibre-react-native -``` - -Then make sure to complete required [platform specific installation steps](https://github.com/maplibre/maplibre-react-native/blob/main/docs/GettingStarted.md#review-platform-specific-info) as well. - - -We've taken care of linking the map tile server to the map, so all you need to do is make sure you've initialized the Radar SDK and use ``. Here's a minimal example: - -``` -import {View} from 'react-native'; -import Radar, { Map } from 'react-native-radar'; -import MapLibreGL from '@maplibre/maplibre-react-native'; - - -// A quirk of Map Libre requires us to set their deprecated access token to null -MapLibreGL.setAccessToken(null); - -export default function App() { - - useEffect(() => { - Radar.initialize('prj_live_pk_...'); - }, []); - - return ( - - - - ); -} -``` - -And here's how you might add a custom pin to the map and control the camera: -``` - // ... rest of your file - - const [cameraConfig, setCameraConfig] = useState({ - triggerKey: Date.now(), - centerCoordinate: [-73.9911, 40.7342], - animationMode: 'flyTo', - animationDuration: 600, - zoomLevel: 12, - }); - - const onRegionDidChange = (event) => { - // handle region change - } - - const mapOptions = { - onRegionDidChange: onRegionDidChange, - } - - const onSelect = (selectedAddress) => { - // Do something with the selected address - } - - const pointsCollection = { - type: "FeatureCollection", - features: [{ - type: "Feature", - properties: { - _id: '123', - }, - geometry: { - type: "Point", - coordinates: [-73.9911, 40.7342] - } - }] - }; - - const onPressIcon = (event) => { - // do something with the symbol, such as scrolling to the geofence - // associated with the icon in the list - } - - return ( - - - - - - - - - - - ); -``` diff --git a/js/ui/autocomplete.jsx b/js/ui/autocomplete.jsx index 9ba5fc68..6a1a7d33 100644 --- a/js/ui/autocomplete.jsx +++ b/js/ui/autocomplete.jsx @@ -28,14 +28,15 @@ import { import { default as defaultStyles } from './styles'; const defaultAutocompleteOptions = { - debounceMS: 200, - threshold: 3, - limit: 8, - placeholder: "Search address", - showPin: true, + debounceMS: 200, // Debounce time in milliseconds + threshold: 3, // Minimum number of characters to trigger autocomplete + limit: 8, // Maximum number of results to return + placeholder: "Search address", // Placeholder text for the input field + showMarkers: true, + disabled: false, }; -const autocompleteUI = ({ options = {}, onSelect, location, style = {} }) => { +const autocompleteUI = ({ options = {} }) => { const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [isOpen, setIsOpen] = useState(false); @@ -44,19 +45,26 @@ const autocompleteUI = ({ options = {}, onSelect, location, style = {} }) => { const textInputRef = useRef(null); const config = { ...defaultAutocompleteOptions, ...options }; + const style = config.style || {}; const fetchResults = useCallback( async (searchQuery) => { if (searchQuery.length < config.threshold) return; - const params = { query: searchQuery, limit: config.limit }; + const { limit, layers, countryCode } = config; + const params = { query: searchQuery, limit, layers, countryCode }; - if (location && location.latitude && location.longitude) { - params.near = location; + if (config.near && config.near.latitude && config.near.longitude) { + params.near = config.near; } try { const result = await Radar.autocomplete(params); + + if (config.onResults && typeof config.onResults === "function") { + config.onResults(result.addresses); + } + setResults(result.addresses); setIsOpen(true); } catch (error) { @@ -93,8 +101,8 @@ const autocompleteUI = ({ options = {}, onSelect, location, style = {} }) => { setQuery(item.formattedAddress); setIsOpen(false); - if (typeof onSelect === "function") { - onSelect(item); + if (typeof config.onSelection === "function") { + config.onSelection(item); } }; @@ -129,7 +137,7 @@ const autocompleteUI = ({ options = {}, onSelect, location, style = {} }) => { > - {config.showPin ? ( + {config.showMarkers ? ( ) : null} @@ -219,6 +227,8 @@ const autocompleteUI = ({ options = {}, onSelect, location, style = {} }) => { { + if (config.disabled) return; + setIsOpen(true); // Set the focus on the other textinput after it opens setTimeout(() => { diff --git a/js/ui/map-logo.png b/js/ui/map-logo.png index 931178706137ae7f26bf55c58fdd659484699110..d5aca07605b68d0f61cd3bd12c79dcda5bfe1523 100644 GIT binary patch literal 9995 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 QSph&%Rz;>l+BE3@0D-Eb-T(jq