Skip to content

Commit

Permalink
Merge a74100f into 3748b15
Browse files Browse the repository at this point in the history
  • Loading branch information
yen-tt committed Nov 17, 2022
2 parents 3748b15 + a74100f commit 61ea553
Show file tree
Hide file tree
Showing 21 changed files with 640 additions and 4 deletions.
1 change: 1 addition & 0 deletions .storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const parameters = {
'AlternativeVerticals',
'SpellCheck',
'ResultsCount',
'Geolocation',
'LocationBias',
'Dropdown'
]
Expand Down
26 changes: 26 additions & 0 deletions docs/search-ui-react.geolocation_2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [Geolocation\_2](./search-ui-react.geolocation_2.md)

## Geolocation\_2() function

A React Component which collects location information to create a location filter and perform a new search.

<b>Signature:</b>

```typescript
export declare function Geolocation({ geolocationOptions, radius, label, GeolocationIcon, handleClick, customCssClasses, }: GeolocationProps): JSX.Element | null;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| { geolocationOptions, radius, label, GeolocationIcon, handleClick, customCssClasses, } | [GeolocationProps](./search-ui-react.geolocationprops.md) | |

<b>Returns:</b>

JSX.Element \| null

A react component for geolocation

11 changes: 11 additions & 0 deletions docs/search-ui-react.geolocationcssclasses.button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md) &gt; [button](./search-ui-react.geolocationcssclasses.button.md)

## GeolocationCssClasses.button property

<b>Signature:</b>

```typescript
button?: string;
```
11 changes: 11 additions & 0 deletions docs/search-ui-react.geolocationcssclasses.geolocationcontainer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md) &gt; [geolocationContainer](./search-ui-react.geolocationcssclasses.geolocationcontainer.md)

## GeolocationCssClasses.geolocationContainer property

<b>Signature:</b>

```typescript
geolocationContainer?: string;
```
11 changes: 11 additions & 0 deletions docs/search-ui-react.geolocationcssclasses.iconcontainer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md) &gt; [iconContainer](./search-ui-react.geolocationcssclasses.iconcontainer.md)

## GeolocationCssClasses.iconContainer property

<b>Signature:</b>

```typescript
iconContainer?: string;
```
22 changes: 22 additions & 0 deletions docs/search-ui-react.geolocationcssclasses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md)

## GeolocationCssClasses interface

The CSS class interface for the Geolocation component.

<b>Signature:</b>

```typescript
export interface GeolocationCssClasses
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [button?](./search-ui-react.geolocationcssclasses.button.md) | string | <i>(Optional)</i> |
| [geolocationContainer?](./search-ui-react.geolocationcssclasses.geolocationcontainer.md) | string | <i>(Optional)</i> |
| [iconContainer?](./search-ui-react.geolocationcssclasses.iconcontainer.md) | string | <i>(Optional)</i> |

13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.customcssclasses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [customCssClasses](./search-ui-react.geolocationprops.customcssclasses.md)

## GeolocationProps.customCssClasses property

CSS classes for customizing the component styling.

<b>Signature:</b>

```typescript
customCssClasses?: GeolocationCssClasses;
```
13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.geolocationicon.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [GeolocationIcon](./search-ui-react.geolocationprops.geolocationicon.md)

## GeolocationProps.GeolocationIcon property

Custom icon component to display along with the button.

<b>Signature:</b>

```typescript
GeolocationIcon?: React.FunctionComponent;
```
13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.geolocationoptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [geolocationOptions](./search-ui-react.geolocationprops.geolocationoptions.md)

## GeolocationProps.geolocationOptions property

Configuration used when collecting the user's location. Definition: [https://w3c.github.io/geolocation-api/\#position\_options\_interface](https://w3c.github.io/geolocation-api/#position_options_interface)<!-- -->.

<b>Signature:</b>

```typescript
geolocationOptions?: PositionOptions;
```
13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.handleclick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [handleClick](./search-ui-react.geolocationprops.handleclick.md)

## GeolocationProps.handleClick property

A function which is called when the geolocation button is clicked.

<b>Signature:</b>

```typescript
handleClick?: (position: GeolocationPosition) => void;
```
13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [label](./search-ui-react.geolocationprops.label.md)

## GeolocationProps.label property

The label for the button. Defaults to 'Use my location'.

<b>Signature:</b>

```typescript
label?: string;
```
25 changes: 25 additions & 0 deletions docs/search-ui-react.geolocationprops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md)

## GeolocationProps interface

The props for the Geolocation component.

<b>Signature:</b>

```typescript
export interface GeolocationProps
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [customCssClasses?](./search-ui-react.geolocationprops.customcssclasses.md) | [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md) | <i>(Optional)</i> CSS classes for customizing the component styling. |
| [GeolocationIcon?](./search-ui-react.geolocationprops.geolocationicon.md) | React.FunctionComponent | <i>(Optional)</i> Custom icon component to display along with the button. |
| [geolocationOptions?](./search-ui-react.geolocationprops.geolocationoptions.md) | PositionOptions | <i>(Optional)</i> Configuration used when collecting the user's location. Definition: [https://w3c.github.io/geolocation-api/\#position\_options\_interface](https://w3c.github.io/geolocation-api/#position_options_interface)<!-- -->. |
| [handleClick?](./search-ui-react.geolocationprops.handleclick.md) | (position: GeolocationPosition) =&gt; void | <i>(Optional)</i> A function which is called when the geolocation button is clicked. |
| [label?](./search-ui-react.geolocationprops.label.md) | string | <i>(Optional)</i> The label for the button. Defaults to 'Use my location'. |
| [radius?](./search-ui-react.geolocationprops.radius.md) | number | <i>(Optional)</i> 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. |

13 changes: 13 additions & 0 deletions docs/search-ui-react.geolocationprops.radius.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [GeolocationProps](./search-ui-react.geolocationprops.md) &gt; [radius](./search-ui-react.geolocationprops.radius.md)

## GeolocationProps.radius property

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.

<b>Signature:</b>

```typescript
radius?: number;
```
3 changes: 3 additions & 0 deletions docs/search-ui-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
| [executeSearch(searchActions)](./search-ui-react.executesearch.md) | Executes a universal/vertical search. |
| [FilterDivider({ className })](./search-ui-react.filterdivider.md) | A divider component used to separate NumericalFacets, HierarchicalFacets, StandardFacets, and StaticFilters. |
| [FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, sectioned, customCssClasses })](./search-ui-react.filtersearch.md) | A component which allows a user to search for filters associated with specific entities and fields. |
| [Geolocation\_2({ geolocationOptions, radius, label, GeolocationIcon, handleClick, customCssClasses, })](./search-ui-react.geolocation_2.md) | A React Component which collects location information to create a location filter and perform a new search. |
| [getSearchIntents(searchActions)](./search-ui-react.getsearchintents.md) | Get search intents of the current query stored in headless using autocomplete request. |
| [getUserLocation(geolocationOptions)](./search-ui-react.getuserlocation.md) | Retrieves user's location using navigator.geolocation API. |
| [HierarchicalFacets({ searchOnChange, collapsible, defaultExpanded, includedFieldIds, customCssClasses, delimiter, showMoreLimit })](./search-ui-react.hierarchicalfacets.md) | A component that displays hierarchical facets, in a tree level structure, applicable to the current vertical search. |
Expand Down Expand Up @@ -64,6 +65,8 @@
| [FilterOptionConfig](./search-ui-react.filteroptionconfig.md) | The configuration data for a field value filter option. |
| [FilterSearchCssClasses](./search-ui-react.filtersearchcssclasses.md) | The CSS class interface for [FilterSearch()](./search-ui-react.filtersearch.md)<!-- -->. |
| [FilterSearchProps](./search-ui-react.filtersearchprops.md) | The props for the [FilterSearch()](./search-ui-react.filtersearch.md) component. |
| [GeolocationCssClasses](./search-ui-react.geolocationcssclasses.md) | The CSS class interface for the Geolocation component. |
| [GeolocationProps](./search-ui-react.geolocationprops.md) | The props for the Geolocation component. |
| [HierarchicalFacetDisplayCssClasses](./search-ui-react.hierarchicalfacetdisplaycssclasses.md) | The CSS class interface for HierarchicalFacetDisplay. |
| [HierarchicalFacetsCssClasses](./search-ui-react.hierarchicalfacetscssclasses.md) | The CSS class interface for [HierarchicalFacets()](./search-ui-react.hierarchicalfacets.md)<!-- -->. |
| [HierarchicalFacetsProps](./search-ui-react.hierarchicalfacetsprops.md) | Props for the [HierarchicalFacets()](./search-ui-react.hierarchicalfacets.md) component. |
Expand Down
24 changes: 24 additions & 0 deletions etc/search-ui-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,30 @@ export interface FilterSearchProps {
// @public
export type FocusedItemData = Record<string, unknown>;

// @public
function Geolocation_2({ geolocationOptions, radius, label, GeolocationIcon, handleClick, customCssClasses, }: GeolocationProps): JSX.Element | null;
export { Geolocation_2 as Geolocation }

// @public
export interface GeolocationCssClasses {
// (undocumented)
button?: string;
// (undocumented)
geolocationContainer?: string;
// (undocumented)
iconContainer?: string;
}

// @public
export interface GeolocationProps {
customCssClasses?: GeolocationCssClasses;
GeolocationIcon?: React.FunctionComponent;
geolocationOptions?: PositionOptions;
handleClick?: (position: GeolocationPosition) => void;
label?: string;
radius?: number;
}

// @public
export function getSearchIntents(searchActions: SearchActions): Promise<SearchIntent[] | undefined>;

Expand Down
4 changes: 2 additions & 2 deletions src/components/AppliedFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export interface AppliedFiltersProps {
customCssClasses?: AppliedFiltersCssClasses
}

const DEFUALT_HIDDEN_FIELDS = ['builtin.entityType'];
const DEFAULT_HIDDEN_FIELDS = ['builtin.entityType'];

/**
* A component that displays a list of filters applied to the current vertical
Expand All @@ -61,7 +61,7 @@ export function AppliedFilters(props: AppliedFiltersProps): JSX.Element {
const isLoading = useSearchState(state => state.searchStatus.isLoading);

const {
hiddenFields = DEFUALT_HIDDEN_FIELDS,
hiddenFields = DEFAULT_HIDDEN_FIELDS,
customCssClasses = {},
hierarchicalFacetsDelimiter = DEFAULT_HIERARCHICAL_DELIMITER,
hierarchicalFacetsFieldIds
Expand Down
127 changes: 127 additions & 0 deletions src/components/Geolocation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { Matcher, SelectableStaticFilter, useSearchActions, useSearchState } from '@yext/search-headless-react';
import { executeSearch } from '../utils/search-operations';
import { getUserLocation } from '../utils/location-operations';
import { useComposedCssClasses } from '../hooks/useComposedCssClasses';
import { useCallback, useState } from 'react';
import LoadingIndicator from '../icons/LoadingIndicator';
import { YextIcon } from '../icons/YextIcon';

/**
* The CSS class interface for the Geolocation component.
*
* @public
*/
export interface GeolocationCssClasses {
geolocationContainer?: string,
button?: string,
iconContainer?: string
}

const builtInCssClasses: Readonly<GeolocationCssClasses> = {
geolocationContainer: 'text-sm text-neutral text-center justify-center items-center flex flex-row',
button: 'text-primary font-semibold hover:underline focus:underline',
iconContainer: 'w-4 ml-2'
};

/**
* The props for the Geolocation component.
*
* @public
*/
export interface GeolocationProps {
/**
* Configuration used when collecting the user's location.
* Definition: {@link https://w3c.github.io/geolocation-api/#position_options_interface}.
*/
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,
/** The label for the button. Defaults to 'Use my location'. */
label?: string,
/** Custom icon component to display along with the button. */
GeolocationIcon?: React.FunctionComponent,
/**
* A function which is called when the geolocation button is clicked,
* after user's position is successfully determined.
*/
handleClick?: (position: GeolocationPosition) => void,
/** CSS classes for customizing the component styling. */
customCssClasses?: GeolocationCssClasses
}

const LOCATION_FIELD_ID = 'builtin.location';
const METERS_PER_MILE = 1609.344;

/**
* A React Component which collects location information to create a
* location filter and perform a new search.
*
* @public
*
* @param props - {@link GeolocationProps}
* @returns A react component for geolocation
*/
export function Geolocation({
geolocationOptions,
radius = 50,
label = 'Use my location',
//TODO: replace default icon with SVG create from design team
GeolocationIcon = YextIcon,
handleClick,
customCssClasses,
}: GeolocationProps): JSX.Element | null {
const searchActions = useSearchActions();
const staticFilters = useSearchState(s => s.filters.static || []);
const [isFetchingLocation, setIsFetchingLocation] = useState<boolean>(false);
const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);

const defaultHandleClick = 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]);

const handleGeolocationClick = useCallback(async () => {
setIsFetchingLocation(true);
try {
const position = await getUserLocation(geolocationOptions);
(handleClick ?? defaultHandleClick)(position);
} catch (e) {
console.warn(e);
} finally {
setIsFetchingLocation(false);
}
}, [geolocationOptions, handleClick, defaultHandleClick]);

return (
<div className={cssClasses.geolocationContainer}>
<button className={cssClasses.button} onClick={handleGeolocationClick}>
{label}
</button>
<div className={cssClasses.iconContainer}>
{isFetchingLocation ? <LoadingIndicator /> : <GeolocationIcon />}
</div>
</div>
);
}
Loading

0 comments on commit 61ea553

Please sign in to comment.