Skip to content

Commit

Permalink
Merge branch 'develop' into dev/vulnerabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
EmilyZhang777 committed Feb 1, 2024
2 parents 186c628 + bd614cb commit 069aae8
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 10 deletions.
4 changes: 2 additions & 2 deletions docs/search-ui-react.filtersearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ A component which allows a user to search for filters associated with specific e
**Signature:**

```typescript
declare function FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, sectioned, customCssClasses }: FilterSearchProps): JSX.Element;
declare function FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, onDropdownInputChange, sectioned, customCssClasses }: FilterSearchProps): JSX.Element;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| { searchFields, label, placeholder, searchOnSelect, onSelect, sectioned, customCssClasses } | [FilterSearchProps](./search-ui-react.filtersearchprops.md) | |
| { searchFields, label, placeholder, searchOnSelect, onSelect, onDropdownInputChange, sectioned, customCssClasses } | [FilterSearchProps](./search-ui-react.filtersearchprops.md) | |

**Returns:**

Expand Down
1 change: 1 addition & 0 deletions docs/search-ui-react.filtersearchprops.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface FilterSearchProps
| --- | --- | --- | --- |
| [customCssClasses?](./search-ui-react.filtersearchprops.customcssclasses.md) | | [FilterSearchCssClasses](./search-ui-react.filtersearchcssclasses.md) | _(Optional)_ CSS classes for customizing the component styling. |
| [label?](./search-ui-react.filtersearchprops.label.md) | | string | _(Optional)_ The display label for the component. |
| [onDropdownInputChange?](./search-ui-react.filtersearchprops.ondropdowninputchange.md) | | (params: [OnDropdownInputChangeProps](./search-ui-react.ondropdowninputchangeprops.md)<!-- -->) =&gt; void | _(Optional)_ A function which is called when the input element's value changes. Replaces the default behavior. |
| [onSelect?](./search-ui-react.filtersearchprops.onselect.md) | | (params: [OnSelectParams](./search-ui-react.onselectparams.md)<!-- -->) =&gt; void | _(Optional)_ A function which is called when a filter is selected. |
| [placeholder?](./search-ui-react.filtersearchprops.placeholder.md) | | string | _(Optional)_ The search input's placeholder text when no text has been entered by the user. Defaults to "Search here...". |
| [searchFields](./search-ui-react.filtersearchprops.searchfields.md) | | Omit&lt;SearchParameterField, 'fetchEntities'&gt;\[\] | An array of fieldApiName and entityType which indicates what to perform the filter search against. |
Expand Down
13 changes: 13 additions & 0 deletions docs/search-ui-react.filtersearchprops.ondropdowninputchange.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; [FilterSearchProps](./search-ui-react.filtersearchprops.md) &gt; [onDropdownInputChange](./search-ui-react.filtersearchprops.ondropdowninputchange.md)

## FilterSearchProps.onDropdownInputChange property

A function which is called when the input element's value changes. Replaces the default behavior.

**Signature:**

```typescript
onDropdownInputChange?: (params: OnDropdownInputChangeProps) => void;
```
3 changes: 2 additions & 1 deletion docs/search-ui-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
| [executeSearch(searchActions)](./search-ui-react.executesearch.md) | Executes a universal/vertical search. |
| [Facets(props)](./search-ui-react.facets.md) | A component that displays all facets applicable to the current 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. |
| [FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, onDropdownInputChange, 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. |
Expand Down Expand Up @@ -84,6 +84,7 @@
| [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) | Props for the [StandardFacet()](./search-ui-react.standardfacet.md) component. |
| [NumericalFacetsCssClasses](./search-ui-react.numericalfacetscssclasses.md) | The CSS class interface for [NumericalFacets()](./search-ui-react.numericalfacets.md)<!-- -->. |
| [NumericalFacetsProps](./search-ui-react.numericalfacetsprops.md) | Props for the [NumericalFacets()](./search-ui-react.numericalfacets.md) component. |
| [OnDropdownInputChangeProps](./search-ui-react.ondropdowninputchangeprops.md) | The parameters that are passed into [FilterSearchProps.onDropdownInputChange](./search-ui-react.filtersearchprops.ondropdowninputchange.md)<!-- -->. |
| [OnSelectParams](./search-ui-react.onselectparams.md) | The parameters that are passed into [FilterSearchProps.onSelect](./search-ui-react.filtersearchprops.onselect.md)<!-- -->. |
| [PaginationCssClasses](./search-ui-react.paginationcssclasses.md) | The CSS classes used for pagination. |
| [PaginationProps](./search-ui-react.paginationprops.md) | Props for [Pagination()](./search-ui-react.pagination.md) component |
Expand Down
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; [OnDropdownInputChangeProps](./search-ui-react.ondropdowninputchangeprops.md) &gt; [executeFilterSearch](./search-ui-react.ondropdowninputchangeprops.executefiltersearch.md)

## OnDropdownInputChangeProps.executeFilterSearch property

A function that executes a filter search and updates the input and dropdown options with the response.

**Signature:**

```typescript
executeFilterSearch: (query?: string) => Promise<FilterSearchResponse | undefined>;
```
21 changes: 21 additions & 0 deletions docs/search-ui-react.ondropdowninputchangeprops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- 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; [OnDropdownInputChangeProps](./search-ui-react.ondropdowninputchangeprops.md)

## OnDropdownInputChangeProps interface

The parameters that are passed into [FilterSearchProps.onDropdownInputChange](./search-ui-react.filtersearchprops.ondropdowninputchange.md)<!-- -->.

**Signature:**

```typescript
interface OnDropdownInputChangeProps
```

## Properties

| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [executeFilterSearch](./search-ui-react.ondropdowninputchangeprops.executefiltersearch.md) | | (query?: string) =&gt; Promise&lt;FilterSearchResponse \| undefined&gt; | A function that executes a filter search and updates the input and dropdown options with the response. |
| [value](./search-ui-react.ondropdowninputchangeprops.value.md) | | string | The input element's new value after the change |

13 changes: 13 additions & 0 deletions docs/search-ui-react.ondropdowninputchangeprops.value.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; [OnDropdownInputChangeProps](./search-ui-react.ondropdowninputchangeprops.md) &gt; [value](./search-ui-react.ondropdowninputchangeprops.value.md)

## OnDropdownInputChangeProps.value property

The input element's new value after the change

**Signature:**

```typescript
value: string;
```
9 changes: 8 additions & 1 deletion etc/search-ui-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export interface FilterOptionConfig {
}

// @public
export function FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, sectioned, customCssClasses }: FilterSearchProps): JSX.Element;
export function FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, onDropdownInputChange, sectioned, customCssClasses }: FilterSearchProps): JSX.Element;

// @public
export interface FilterSearchCssClasses extends AutocompleteResultCssClasses {
Expand All @@ -290,6 +290,7 @@ export interface FilterSearchCssClasses extends AutocompleteResultCssClasses {
export interface FilterSearchProps {
customCssClasses?: FilterSearchCssClasses;
label?: string;
onDropdownInputChange?: (params: OnDropdownInputChangeProps) => void;
onSelect?: (params: OnSelectParams) => void;
placeholder?: string;
searchFields: Omit<SearchParameterField, 'fetchEntities'>[];
Expand Down Expand Up @@ -461,6 +462,12 @@ export interface NumericalFacetsProps extends Omit<StandardFacetsProps, 'exclude
// @public
export type OnDragHandler = (center: mapboxgl_2.LngLat, bounds: mapboxgl_2.LngLatBounds) => void;

// @public
export interface OnDropdownInputChangeProps {
executeFilterSearch: (query?: string) => Promise<FilterSearchResponse | undefined>;
value: string;
}

// @public
export type onSearchFunc = (searchEventData: {
verticalKey?: string;
Expand Down
30 changes: 29 additions & 1 deletion src/components/FilterSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ export interface OnSelectParams {
executeFilterSearch: (query?: string) => Promise<FilterSearchResponse | undefined>
}

/**
* The parameters that are passed into {@link FilterSearchProps.onDropdownInputChange}.
*
* @public
*/
export interface OnDropdownInputChangeProps {
/** The input element's new value after the change */
value: string,
/**
* A function that executes a filter search and updates the input and dropdown options
* with the response.
*/
executeFilterSearch: (query?: string) => Promise<FilterSearchResponse | undefined>
}

/**
* The props for the {@link FilterSearch} component.
*
Expand All @@ -78,6 +93,8 @@ export interface FilterSearchProps {
searchOnSelect?: boolean,
/** A function which is called when a filter is selected. */
onSelect?: (params: OnSelectParams) => void,
/** A function which is called when the input element's value changes. Replaces the default behavior. */
onDropdownInputChange?: (params: OnDropdownInputChangeProps) => void,
/** Determines whether or not the results of the filter search are separated by field. Defaults to false. */
sectioned?: boolean,
/** CSS classes for customizing the component styling. */
Expand All @@ -98,6 +115,7 @@ export function FilterSearch({
placeholder = 'Search here...',
searchOnSelect,
onSelect,
onDropdownInputChange,
sectioned = false,
customCssClasses
}: FilterSearchProps): JSX.Element {
Expand Down Expand Up @@ -224,6 +242,16 @@ export function FilterSearch({
matchingFieldIds
]);

const handleInputChange = useCallback((value) => {
onDropdownInputChange ? onDropdownInputChange({
value,
executeFilterSearch
}) : executeFilterSearch(value);
}, [
onDropdownInputChange,
executeFilterSearch
]);

const meetsSubmitCritera = useCallback(index => index >= 0, []);

const itemDataMatrix = useMemo(() => {
Expand Down Expand Up @@ -279,7 +307,7 @@ export function FilterSearch({
<DropdownInput
className={cssClasses.inputElement}
placeholder={placeholder}
onChange={executeFilterSearch}
onChange={handleInputChange}
onFocus={handleInputFocus}
submitCriteria={meetsSubmitCritera}
/>
Expand Down
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export {
FilterSearch,
FilterSearchCssClasses,
FilterSearchProps,
OnSelectParams
OnSelectParams,
OnDropdownInputChangeProps
} from './FilterSearch';

export {
Expand Down
40 changes: 37 additions & 3 deletions test-site/src/pages/PeoplePage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useLayoutEffect } from 'react';
import { useSearchActions } from '@yext/search-headless-react';
import { FieldValueStaticFilter, SelectableStaticFilter, useSearchActions } from '@yext/search-headless-react';
import {
AppliedFilters,
FilterSearch,
Expand All @@ -19,12 +19,14 @@ import {
NumericalFacets,
AlternativeVerticals,
StandardFacet,
NumericalFacet
NumericalFacet,
OnDropdownInputChangeProps
} from '@yext/search-ui-react';
// import { CustomCard } from '../components/CustomCard';

const hierarchicalFacetFieldIds = ['c_hierarchicalFacet'];
const filterSearchFields = [{ fieldApiName: 'name', entityType: 'ce_person' }];
const employeeFilterSearchFields = [{fieldApiName: 'c_employeeDepartment', entityType: 'ce_person'}];
const employeeFilterConfigs = [
{ value: 'Consulting' },
{ value: 'Technology' }
Expand All @@ -43,6 +45,31 @@ export function PeoplePage() {
searchActions.executeVerticalQuery();
});

/**
* This example function that's being used for onDropdownInputChange allows for clearing the filter in the search state when the input is empty.
* This is especially useful for implementations that have multiple FilterSearch components.
* Ex. a user can search using both inputs initially, but then wants to clear one of the FilterSearch inputs and re-run a search.
*/
const removeAssociatedFilterWhenInputIsEmpty = (searchFields: { fieldApiName: string; entityType: string; }[]) => (params: OnDropdownInputChangeProps) => {
const { value, executeFilterSearch } = params;
// If there is still an input value, execute the filter search as normal
if (value !== "") {
executeFilterSearch(value);
}
// When the input is empty, remove the associated filter from the search state while keeping any other filters that are applied.
else {
const fieldIds = searchFields.map((field: {fieldApiName: string, entityType: string}) => field.fieldApiName);
const filtersToKeep: SelectableStaticFilter[] = [];
searchActions.state.filters.static?.forEach((staticFilter) => {
const filter = staticFilter.filter as FieldValueStaticFilter;
if (!fieldIds.includes(filter.fieldId)) {
filtersToKeep.push(staticFilter);
}
});
searchActions.setStaticFilters(filtersToKeep);
}
}

return (
<div>
<SearchBar />
Expand All @@ -51,7 +78,14 @@ export function PeoplePage() {
<FilterSearch
searchFields={filterSearchFields}
searchOnSelect={true}
label='Filters'
label='FilterSearch Name Filter'
onDropdownInputChange={removeAssociatedFilterWhenInputIsEmpty(filterSearchFields)}
/>
<FilterSearch
searchFields={employeeFilterSearchFields}
searchOnSelect={true}
label='FilterSearch Department Filter'
onDropdownInputChange={removeAssociatedFilterWhenInputIsEmpty(employeeFilterSearchFields)}
/>
<FilterDivider />
<StaticFilters
Expand Down
3 changes: 2 additions & 1 deletion tests/components/FilterSearch.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const meta: Meta<typeof FilterSearch> = {
}
},
args: {
label: 'Filter'
label: 'Filter',
onDropdownInputChange: undefined,
}
};
export default meta;
Expand Down
10 changes: 10 additions & 0 deletions tests/components/FilterSearch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,16 @@ describe('search without section labels', () => {
userEvent.keyboard('{enter}');
expect(inputNode).toHaveValue('first name 1');
});

it('when an onDropdownInputChange prop is specified, it gets called each time after the input changes and executeFilterSearch does not', async () => {
const mockedOnDropdownInputChange = jest.fn();
const executeFilterSearch = jest
.spyOn(SearchHeadless.prototype, 'executeFilterSearch');
renderFilterSearch({ searchFields: searchFieldsProp, onDropdownInputChange: mockedOnDropdownInputChange});
userEvent.type(screen.getByRole('textbox'), 'a');
await waitFor(() => expect(mockedOnDropdownInputChange).toHaveBeenCalledTimes(1));
expect(executeFilterSearch).toHaveBeenCalledTimes(0);
})
});

describe('screen reader', () => {
Expand Down

0 comments on commit 069aae8

Please sign in to comment.