-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Geolocation component #336
Changes from 3 commits
bb343f5
bd5ce80
146d4f0
aa57cc8
a7a6f7f
265875e
a6b2292
a74100f
09247fe
500f29f
846df83
0337975
e65db00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
|
||
yen-tt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import { Matcher, SelectableStaticFilter, useSearchActions, useSearchState } from '@yext/search-headless-react'; | ||
import { executeSearch } from '../utils/search-operations'; | ||
import { getUserLocation } from '../utils/location-operations'; | ||
import { useCallback } from 'react'; | ||
|
||
const LOCATION_FIELD_ID = 'builtin.location'; | ||
const METERS_PER_MILE = 1609.344; | ||
|
||
/** | ||
* The props for {@link useGeolocationHandler} hook. | ||
* | ||
* @internal | ||
*/ | ||
interface GeolocationhandlerProps { | ||
yen-tt marked this conversation as resolved.
Show resolved
Hide resolved
yen-tt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** A React dispatch function use to update the status of fetching user's location. */ | ||
setIsFetchingLocation: React.Dispatch<React.SetStateAction<boolean>>, | ||
/** Configuration used when collecting the user's location. */ | ||
geolocationOptions?: PositionOptions, | ||
/** | ||
* The radius, in miles, around the user's location to find results. Defaults to 50. | ||
* If location accuracy is low, a larger radius may be used automatically. | ||
*/ | ||
radius?: number, | ||
/** Custom handler function to call after user's position is successfully determined. */ | ||
handleUserPosition?: (position: GeolocationPosition) => void | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small nit: I'm not wild about the names There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
edit: end up moving There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't totally agree with the idea that we should never use the word "on" and always use "handle". I think if done correctly, we could use both and each could convey a different meaning. But, that's a higher-level team convo. |
||
} | ||
|
||
/** | ||
* Returns a function that will collect user's geolocation and, by default, will set | ||
* a built-in location filter and execute a search. | ||
* | ||
* @internal | ||
* | ||
* @param props - {@link GeolocationProps} | ||
yen-tt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @returns A function to collect and process user's geolocation | ||
*/ | ||
export function useGeolocationHandler({ | ||
setIsFetchingLocation, | ||
geolocationOptions, | ||
radius = 50, | ||
handleUserPosition | ||
tmeyer2115 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}: GeolocationhandlerProps): () => Promise<void> { | ||
const searchActions = useSearchActions(); | ||
const staticFilters = useSearchState(s => s.filters.static || []); | ||
|
||
const defaultHandleUserPosition = useCallback((position: GeolocationPosition) => { | ||
const { latitude, longitude, accuracy } = position.coords; | ||
const locationFilter: SelectableStaticFilter = { | ||
displayName: 'Current Location', | ||
selected: true, | ||
filter: { | ||
kind: 'fieldValue', | ||
fieldId: LOCATION_FIELD_ID, | ||
matcher: Matcher.Near, | ||
value: { | ||
lat: latitude, | ||
lng: longitude, | ||
radius: Math.max(accuracy, radius * METERS_PER_MILE) | ||
}, | ||
} | ||
}; | ||
const nonLocationFilters = staticFilters.filter(filter => { | ||
return !(filter.filter.kind === 'fieldValue' | ||
&& filter.filter.fieldId === LOCATION_FIELD_ID); | ||
}); | ||
searchActions.setStaticFilters([...nonLocationFilters, locationFilter]); | ||
executeSearch(searchActions); | ||
}, [radius, searchActions, staticFilters]); | ||
|
||
return useCallback(async () => { | ||
setIsFetchingLocation(true); | ||
try { | ||
const position = await getUserLocation(geolocationOptions); | ||
(handleUserPosition ?? defaultHandleUserPosition)(position); | ||
} catch (e) { | ||
console.warn(e); | ||
} finally { | ||
setIsFetchingLocation(false); | ||
} | ||
}, [setIsFetchingLocation, geolocationOptions, handleUserPosition, defaultHandleUserPosition]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot use
{@link Geolocation}
here due to an issue with API Extractor adding_2
suffix to duplicate interface/class names. In search-ui-react, Geolocation from Typescript's "lib.dom.d.ts" file conflicts with Geolocation component.See: microsoft/rushstack#2534 and microsoft/rushstack#2976
Open PR: microsoft/rushstack#2608
It does make it a little odd in the doc but the signature of the component is correct. What to know if the team have any thoughts on this. A work around, which is a little hacky, is to add a script to manually update the files generated from API extractor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with it, the api extractor docs aren't made to be extremely beginner friendly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we link to
Geolocation_2
? or would that not resolve correctly?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would link correctly in the doc pages but we would see this in search-ui-react.api.md file:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh ok, I'm fine leaving it without a link