-
-
+
+
+ {facets => facets
+ .map((facet, i) => {
+ let facetType: FacetType = FacetType.STANDARD;
+ let facetProps: FacetProps = {
+ fieldId: facet.fieldId,
+ label: facet.displayName,
+ };
+ if (fieldIdToCustomFacetProps.has(facet.fieldId)) {
+ const customFacetElement: ReactElement = fieldIdToCustomFacetProps.get(facet.fieldId);
+ facetProps = customFacetElement.props;
+ facetType = getFacetTypeFromReactElementType(
+ (typeof customFacetElement.type === 'function') ? customFacetElement.type.name : '');
+ } else {
+ if (isStringFacet(facet)) {
+ facetType = FacetType.STANDARD;
+ } else if (isNumericalFacet(facet)) {
+ facetType = FacetType.NUMERICAL;
+ }
+ }
+
+ let facetComponent: ReactElement;
+ switch (facetType) {
+ case FacetType.NUMERICAL:
+ facetComponent = ;
+ break;
+ case FacetType.STANDARD:
+ // fall through
+ default:
+ facetComponent = (
+ );
+ }
+
+ return (
+
+ {facetComponent}
+ {(i < facets.length - 1) && }
+
+ );
+ })
+ }
+
+
);
-}
\ No newline at end of file
+}
+
+/**
+ * A component that displays a single standard facet. Use this to override the default rendering.
+ *
+ * @param props - {@link StandardFacetProps}
+ * @returns ReactElement
+ * @public
+ */
+export function StandardFacet(props: StandardFacetProps) { return null; }
+
+/**
+ * Returns the type of the facet based on the props.
+ * @param elementType - string
+ * @returns {@link FacetType}
+ *
+ * @internal
+ */
+export function getFacetTypeFromReactElementType(elementType: string) {
+ switch (elementType) {
+ case StandardFacet.toString():
+ // fall through
+ default:
+ return FacetType.STANDARD;
+ }
+}
diff --git a/src/components/Filters/FacetsProvider.tsx b/src/components/Filters/FacetsProvider.tsx
index 52f4f5c3b..3aac3bc4b 100644
--- a/src/components/Filters/FacetsProvider.tsx
+++ b/src/components/Filters/FacetsProvider.tsx
@@ -31,8 +31,8 @@ export interface FacetsProviderProps {
}
/**
- * The Facets component is a wrapper component around {@link Filters} that updates facet options
- * when a child filter is updated.
+ * The FacetsProvider component is a wrapper component around {@link Filters} that updates facet
+ * options when a child filter is updated.
*
* The representation of the facets is configured using a FACC (function as a child component)
* The FACC is passed the facets data, and is intended for use with components like
diff --git a/src/components/StandardFacetContent.tsx b/src/components/StandardFacetContent.tsx
new file mode 100644
index 000000000..a1155a7c7
--- /dev/null
+++ b/src/components/StandardFacetContent.tsx
@@ -0,0 +1,39 @@
+import { FilterGroup } from './FilterGroup';
+import { DisplayableFacet } from '@yext/search-headless-react';
+import { StandardFacetProps } from './FacetProps';
+
+/**
+ * A component that displays the content of a standard facet.
+ *
+ * @param props - props to render the component
+ * @returns A React component for the content of a standard facet
+ *
+ * @internal
+ */
+export function StandardFacetContent({
+ fieldId,
+ customCssClasses,
+ transformOptions,
+ facet,
+ label = '',
+ showMoreLimit = 10,
+ showOptionCounts = true,
+ ...filterGroupProps
+}: StandardFacetProps & { facet: DisplayableFacet }) {
+ const options = facet.options || [];
+ const transformedOptions = transformOptions ? (transformOptions(options) || []) : options;
+
+ return (
+
{
+ return showOptionCounts ? { ...o, resultsCount: o.count } : o;
+ })}
+ title={label}
+ customCssClasses={customCssClasses}
+ showMoreLimit={showMoreLimit}
+ searchable={facet?.options.length > showMoreLimit}
+ {...filterGroupProps}
+ />
+ );
+}
diff --git a/src/components/StandardFacets.tsx b/src/components/StandardFacets.tsx
index afa4607ca..3b2ade707 100644
--- a/src/components/StandardFacets.tsx
+++ b/src/components/StandardFacets.tsx
@@ -1,12 +1,13 @@
import { FacetsProvider } from './Filters';
import { FilterGroup, FilterGroupCssClasses } from './FilterGroup';
import { Fragment } from 'react';
-import { DisplayableFacet } from '@yext/search-headless-react';
import { FilterDivider } from './FilterDivider';
+import { isStringFacet } from '../utils/filterutils';
/**
* The CSS class interface for {@link StandardFacets}.
*
+ * @deprecated Use {@link Facets} instead.
* @public
*/
export interface StandardFacetsCssClasses extends FilterGroupCssClasses {
@@ -17,6 +18,7 @@ export interface StandardFacetsCssClasses extends FilterGroupCssClasses {
/**
* Props for the {@link StandardFacets} component.
*
+ * @deprecated Use {@link Facets} instead.
* @public
*/
export interface StandardFacetsProps {
@@ -56,6 +58,7 @@ export interface StandardFacetsProps {
* @param props - {@link StandardFacetsProps}
* @returns A React component for facets
*
+ * @deprecated Use {@link Facets} instead.
* @public
*/
export function StandardFacets(props: StandardFacetsProps) {
@@ -93,7 +96,3 @@ export function StandardFacets(props: StandardFacetsProps) {
);
}
-
-function isStringFacet(facet: DisplayableFacet): boolean {
- return facet.options.length > 0 && typeof facet.options[0].value === 'string';
-}
\ No newline at end of file
diff --git a/src/components/index.ts b/src/components/index.ts
index f12aa093e..ba055d85a 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -127,10 +127,16 @@ export {
export {
Facets,
- FacetsCssClasses,
- FacetsProps
+ StandardFacet
} from './Facets';
+export {
+ FacetsCssClasses,
+ FacetsProps,
+ FacetProps,
+ StandardFacetProps
+} from './FacetProps';
+
export {
FilterGroupProps,
FilterGroupCssClasses
diff --git a/src/utils/filterutils.tsx b/src/utils/filterutils.tsx
index 7347bf8f5..0f746e42c 100644
--- a/src/utils/filterutils.tsx
+++ b/src/utils/filterutils.tsx
@@ -17,6 +17,13 @@ export function isNumberRangeValue(obj: unknown): obj is NumberRangeValue {
return typeof obj === 'object' && !!obj && ('start' in obj || 'end' in obj);
}
+/**
+ * Checks if the facet is a string facet with string options.
+ */
+export function isStringFacet(facet: DisplayableFacet): boolean {
+ return facet.options.length > 0 && typeof facet.options[0].value === 'string';
+}
+
/**
* Checks if the facet is a numerical facet with number range filter options.
*/
diff --git a/test-site/package-lock.json b/test-site/package-lock.json
index 762030b58..5a6e34d16 100644
--- a/test-site/package-lock.json
+++ b/test-site/package-lock.json
@@ -32,7 +32,7 @@
},
"..": {
"name": "@yext/search-ui-react",
- "version": "1.1.0",
+ "version": "1.2.0-beta.0",
"license": "BSD-3-Clause",
"dependencies": {
"@microsoft/api-documenter": "^7.15.3",
@@ -80,7 +80,7 @@
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"@yext/eslint-config-slapshot": "^0.5.0",
- "@yext/search-headless-react": "^2.1.0",
+ "@yext/search-headless-react": "^2.2.0-beta.0",
"axe-playwright": "^1.1.11",
"babel-jest": "^27.0.6",
"eslint": "^8.11.0",
@@ -97,7 +97,7 @@
"typescript": "~4.5.5"
},
"peerDependencies": {
- "@yext/search-headless-react": "^2.1.0",
+ "@yext/search-headless-react": "^2.2.0-beta.0",
"react": "^16.14 || ^17 || ^18",
"react-dom": "^16.14 || ^17 || ^18"
}
@@ -20112,7 +20112,7 @@
"@typescript-eslint/parser": "^5.16.0",
"@yext/analytics": "^0.2.0-beta.3",
"@yext/eslint-config-slapshot": "^0.5.0",
- "@yext/search-headless-react": "^2.1.0",
+ "@yext/search-headless-react": "^2.2.0-beta.0",
"axe-playwright": "^1.1.11",
"babel-jest": "^27.0.6",
"classnames": "^2.3.1",
diff --git a/tests/components/Facets.test.tsx b/tests/components/Facets.test.tsx
index 46ca478c8..e1b70fde3 100644
--- a/tests/components/Facets.test.tsx
+++ b/tests/components/Facets.test.tsx
@@ -5,8 +5,9 @@ import {
} from '@yext/search-headless-react';
import { mockAnswersHooks, mockAnswersState } from '../__utils__/mocks';
import { DisplayableFacets } from '../__fixtures__/data/filters';
-import { Facets } from '../../src';
+import { Facets, StandardFacet, StandardFacetProps } from '../../src';
import { getOptionLabelText } from '../__utils__/facets';
+import { DisplayableFacetOption } from '@yext/search-core';
const mockedState: Partial = {
filters: {
@@ -88,4 +89,31 @@ describe('Facets', () => {
expect(screen.queryByText(`${o.displayName} (${o.count})}`)).toBeNull();
});
});
+
+ it('Properly renders an override standard facet if present', () => {
+ const mockTransformOptions = (options: DisplayableFacetOption[]) =>
+ options.map(option => ({ ...option, displayName: `my ${option.displayName}` }));
+
+ const overrideFieldId = 'products';
+ const overrideLabel = 'My Products';
+ const props: StandardFacetProps = {
+ fieldId: overrideFieldId,
+ label: overrideLabel,
+ transformOptions: mockTransformOptions,
+ };
+
+ render(
+
+
+ );
+ const regularFilter = DisplayableFacets[0];
+
+ expect(screen.getByText(overrideLabel)).toBeDefined();
+ expect(screen.queryByText(regularFilter.displayName)).toBeNull();
+ expect(
+ screen
+ .getByText(
+ `my ${regularFilter.options[0].displayName} (${regularFilter.options[0].count})`))
+ .toBeDefined();
+ });
});
\ No newline at end of file
diff --git a/tests/components/StandardFacet.stories.tsx b/tests/components/StandardFacet.stories.tsx
new file mode 100644
index 000000000..cbb3255c8
--- /dev/null
+++ b/tests/components/StandardFacet.stories.tsx
@@ -0,0 +1,16 @@
+import { ComponentMeta, Story } from '@storybook/react';
+import { Facets, StandardFacetProps, StandardFacet } from '../../src';
+
+const meta: ComponentMeta = {
+ title: 'StandardFacet',
+ component: StandardFacet
+};
+export default meta;
+
+export const Primary: Story = (args) => {
+ return (
+
+
+
+ );
+};
\ No newline at end of file
From f936f9b7873fd859e737ad8cd04f2e0c98940ff9 Mon Sep 17 00:00:00 2001
From: EmilyZhang777 <48967088+EmilyZhang777@users.noreply.github.com>
Date: Tue, 16 May 2023 14:20:57 -0400
Subject: [PATCH 14/23] Add Numerical Facet (#372)
Add Numerical Facet
This change adds a singular NumericalFacet that can be used to override facets rendered in Facets.
J=BACK-2221
TEST=auto,manual
Ran npm run test and confirmed all tests pass.
Manually added a NumericalFacet with Facets on the people's page under test-site/. Confirmed the facet gets overridden correctly.
---
docs/search-ui-react.facetprops.md | 4 +-
docs/search-ui-react.facets.md | 2 +-
docs/search-ui-react.facetsprops.children.md | 2 +-
docs/search-ui-react.md | 2 +
docs/search-ui-react.numericalfacet.md | 26 ++++++++++
...ct.numericalfacetprops.customcssclasses.md | 13 +++++
...umericalfacetprops.getfilterdisplayname.md | 18 +++++++
...i-react.numericalfacetprops.inputprefix.md | 13 +++++
docs/search-ui-react.numericalfacetprops.md | 24 +++++++++
...ct.numericalfacetprops.showoptioncounts.md | 13 +++++
etc/search-ui-react.api.md | 13 ++++-
src/components/FacetProps.tsx | 31 +++++++++++-
src/components/Facets.tsx | 28 +++++++----
src/components/NumericalFacetContent.tsx | 50 +++++++++++++++++++
src/components/index.ts | 6 ++-
tests/components/Facets.test.tsx | 25 +++++++++-
tests/components/NumericalFacet.stories.tsx | 37 ++++++++++++++
tests/components/StandardFacet.stories.tsx | 37 +++++++++++---
18 files changed, 315 insertions(+), 29 deletions(-)
create mode 100644 docs/search-ui-react.numericalfacet.md
create mode 100644 docs/search-ui-react.numericalfacetprops.customcssclasses.md
create mode 100644 docs/search-ui-react.numericalfacetprops.getfilterdisplayname.md
create mode 100644 docs/search-ui-react.numericalfacetprops.inputprefix.md
create mode 100644 docs/search-ui-react.numericalfacetprops.md
create mode 100644 docs/search-ui-react.numericalfacetprops.showoptioncounts.md
create mode 100644 src/components/NumericalFacetContent.tsx
create mode 100644 tests/components/NumericalFacet.stories.tsx
diff --git a/docs/search-ui-react.facetprops.md b/docs/search-ui-react.facetprops.md
index cea2942ba..c5429d55f 100644
--- a/docs/search-ui-react.facetprops.md
+++ b/docs/search-ui-react.facetprops.md
@@ -9,7 +9,7 @@ Props for a single facet component.
Signature:
```typescript
-export declare type FacetProps = StandardFacetProps;
+export declare type FacetProps = StandardFacetProps | NumericalFacetProps;
```
-References: [StandardFacetProps](./search-ui-react.standardfacetprops.md)
+References: [StandardFacetProps](./search-ui-react.standardfacetprops.md), [NumericalFacetProps](./search-ui-react.numericalfacetprops.md)
diff --git a/docs/search-ui-react.facets.md b/docs/search-ui-react.facets.md
index 299d0c122..e24bc7ad3 100644
--- a/docs/search-ui-react.facets.md
+++ b/docs/search-ui-react.facets.md
@@ -28,5 +28,5 @@ A React component for facets
This component is a quick way of getting facets on the page, and it will render standard facets, numerical facets, and hierarchical facets. The [StandardFacets()](./search-ui-react.standardfacets.md), [NumericalFacets()](./search-ui-react.numericalfacets.md), and [HierarchicalFacets()](./search-ui-react.hierarchicalfacets.md) components can be used instead for more control over facet configuration.
-To override a single facet, use [StandardFacet()](./search-ui-react.standardfacet.md).
+To override a single facet, use [StandardFacet()](./search-ui-react.standardfacet.md) or [NumericalFacet()](./search-ui-react.numericalfacet.md).
diff --git a/docs/search-ui-react.facetsprops.children.md b/docs/search-ui-react.facetsprops.children.md
index 77f1227ec..1f661f275 100644
--- a/docs/search-ui-react.facetsprops.children.md
+++ b/docs/search-ui-react.facetsprops.children.md
@@ -14,5 +14,5 @@ children?: ReactElement[] | ReactElement | undefined | null;
## Remarks
-Supported components include [StandardFacet()](./search-ui-react.standardfacet.md).
+Supported components include [StandardFacet()](./search-ui-react.standardfacet.md), [NumericalFacet()](./search-ui-react.numericalfacet.md).
diff --git a/docs/search-ui-react.md b/docs/search-ui-react.md
index 26bc33e2f..5f48f36a1 100644
--- a/docs/search-ui-react.md
+++ b/docs/search-ui-react.md
@@ -26,6 +26,7 @@
| [isCtaData(data)](./search-ui-react.isctadata.md) | Type guard for CtaData. |
| [LocationBias({ geolocationOptions, customCssClasses })](./search-ui-react.locationbias.md) | A React Component which displays and collects location information in order to bias searches. |
| [MapboxMap({ mapboxAccessToken, mapboxOptions, PinComponent, getCoordinate, onDrag })](./search-ui-react.mapboxmap.md) | A component that renders a map with markers to show result locations using Mapbox GL. |
+| [NumericalFacet(props)](./search-ui-react.numericalfacet.md) | A component that displays a single numerical facet. Use this to override the default rendering. |
| [NumericalFacets({ searchOnChange, includedFieldIds, getFilterDisplayName, inputPrefix, customCssClasses, ...filterGroupProps })](./search-ui-react.numericalfacets.md) | A component that displays numerical facets applicable to the current vertical search. |
| [Pagination(props)](./search-ui-react.pagination.md) | Renders a component that divide a series of vertical results into chunks across multiple pages and enable user to navigate between those pages. |
| [renderHighlightedValue(highlightedValueOrString, customCssClasses)](./search-ui-react.renderhighlightedvalue.md) | Renders a HighlightedValue with highlighting based on its matchedSubstrings. |
@@ -78,6 +79,7 @@
| [LocationBiasCssClasses](./search-ui-react.locationbiascssclasses.md) | The CSS class interface for the [LocationBias()](./search-ui-react.locationbias.md) component. |
| [LocationBiasProps](./search-ui-react.locationbiasprops.md) | The props for the [LocationBias()](./search-ui-react.locationbias.md) component. |
| [MapboxMapProps](./search-ui-react.mapboxmapprops.md) | Props for the [MapboxMap()](./search-ui-react.mapboxmap.md) component. The type param "T" represents the type of "rawData" field of the results use in the map. |
+| [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. |
| [OnSelectParams](./search-ui-react.onselectparams.md) | The parameters that are passed into [FilterSearchProps.onSelect](./search-ui-react.filtersearchprops.onselect.md). |
diff --git a/docs/search-ui-react.numericalfacet.md b/docs/search-ui-react.numericalfacet.md
new file mode 100644
index 000000000..d192a66ed
--- /dev/null
+++ b/docs/search-ui-react.numericalfacet.md
@@ -0,0 +1,26 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacet](./search-ui-react.numericalfacet.md)
+
+## NumericalFacet() function
+
+A component that displays a single numerical facet. Use this to override the default rendering.
+
+Signature:
+
+```typescript
+export declare function NumericalFacet(props: NumericalFacetProps): null;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| props | [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) | [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) |
+
+Returns:
+
+null
+
+ReactElement
+
diff --git a/docs/search-ui-react.numericalfacetprops.customcssclasses.md b/docs/search-ui-react.numericalfacetprops.customcssclasses.md
new file mode 100644
index 000000000..602d8a32c
--- /dev/null
+++ b/docs/search-ui-react.numericalfacetprops.customcssclasses.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) > [customCssClasses](./search-ui-react.numericalfacetprops.customcssclasses.md)
+
+## NumericalFacetProps.customCssClasses property
+
+CSS classes for customizing the component styling.
+
+Signature:
+
+```typescript
+customCssClasses?: FilterGroupCssClasses & RangeInputCssClasses;
+```
diff --git a/docs/search-ui-react.numericalfacetprops.getfilterdisplayname.md b/docs/search-ui-react.numericalfacetprops.getfilterdisplayname.md
new file mode 100644
index 000000000..6f4034e70
--- /dev/null
+++ b/docs/search-ui-react.numericalfacetprops.getfilterdisplayname.md
@@ -0,0 +1,18 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) > [getFilterDisplayName](./search-ui-react.numericalfacetprops.getfilterdisplayname.md)
+
+## NumericalFacetProps.getFilterDisplayName property
+
+Returns the filter's display name based on the range values which is used when the filter is displayed by other components such as AppliedFilters.
+
+Signature:
+
+```typescript
+getFilterDisplayName?: (value: NumberRangeValue) => string;
+```
+
+## Remarks
+
+By default, the displayName separates the range with a dash such as '10 - 20'. If the range is unbounded, it will display as 'Up to 20' or 'Over 10'.
+
diff --git a/docs/search-ui-react.numericalfacetprops.inputprefix.md b/docs/search-ui-react.numericalfacetprops.inputprefix.md
new file mode 100644
index 000000000..50b0b3877
--- /dev/null
+++ b/docs/search-ui-react.numericalfacetprops.inputprefix.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) > [inputPrefix](./search-ui-react.numericalfacetprops.inputprefix.md)
+
+## NumericalFacetProps.inputPrefix property
+
+An optional element which renders in front of the input text.
+
+Signature:
+
+```typescript
+inputPrefix?: JSX.Element;
+```
diff --git a/docs/search-ui-react.numericalfacetprops.md b/docs/search-ui-react.numericalfacetprops.md
new file mode 100644
index 000000000..0fc6c4b7f
--- /dev/null
+++ b/docs/search-ui-react.numericalfacetprops.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacetProps](./search-ui-react.numericalfacetprops.md)
+
+## NumericalFacetProps interface
+
+Props for the [StandardFacet()](./search-ui-react.standardfacet.md) component.
+
+Signature:
+
+```typescript
+export interface NumericalFacetProps extends StandardFacetProps
+```
+Extends: [StandardFacetProps](./search-ui-react.standardfacetprops.md)
+
+## Properties
+
+| Property | Type | Description |
+| --- | --- | --- |
+| [customCssClasses?](./search-ui-react.numericalfacetprops.customcssclasses.md) | [FilterGroupCssClasses](./search-ui-react.filtergroupcssclasses.md) & [RangeInputCssClasses](./search-ui-react.rangeinputcssclasses.md) | (Optional) CSS classes for customizing the component styling. |
+| [getFilterDisplayName?](./search-ui-react.numericalfacetprops.getfilterdisplayname.md) | (value: NumberRangeValue) => string | (Optional) Returns the filter's display name based on the range values which is used when the filter is displayed by other components such as AppliedFilters. |
+| [inputPrefix?](./search-ui-react.numericalfacetprops.inputprefix.md) | JSX.Element | (Optional) An optional element which renders in front of the input text. |
+| [showOptionCounts?](./search-ui-react.numericalfacetprops.showoptioncounts.md) | boolean | (Optional) Whether or not to show the option counts for each filter. Defaults to false. |
+
diff --git a/docs/search-ui-react.numericalfacetprops.showoptioncounts.md b/docs/search-ui-react.numericalfacetprops.showoptioncounts.md
new file mode 100644
index 000000000..8f510813b
--- /dev/null
+++ b/docs/search-ui-react.numericalfacetprops.showoptioncounts.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/search-ui-react](./search-ui-react.md) > [NumericalFacetProps](./search-ui-react.numericalfacetprops.md) > [showOptionCounts](./search-ui-react.numericalfacetprops.showoptioncounts.md)
+
+## NumericalFacetProps.showOptionCounts property
+
+Whether or not to show the option counts for each filter. Defaults to false.
+
+Signature:
+
+```typescript
+showOptionCounts?: boolean;
+```
diff --git a/etc/search-ui-react.api.md b/etc/search-ui-react.api.md
index 82b5d8ffb..08c3d8c9d 100644
--- a/etc/search-ui-react.api.md
+++ b/etc/search-ui-react.api.md
@@ -203,7 +203,7 @@ export function executeAutocomplete(searchActions: SearchActions): Promise;
// @public
-export type FacetProps = StandardFacetProps;
+export type FacetProps = StandardFacetProps | NumericalFacetProps;
// @public
export function Facets(props: FacetsProps): JSX.Element;
@@ -418,6 +418,17 @@ export interface MapboxMapProps {
PinComponent?: PinComponent;
}
+// @public
+export function NumericalFacet(props: NumericalFacetProps): null;
+
+// @public
+export interface NumericalFacetProps extends StandardFacetProps {
+ customCssClasses?: FilterGroupCssClasses & RangeInputCssClasses;
+ getFilterDisplayName?: (value: NumberRangeValue) => string;
+ inputPrefix?: JSX.Element;
+ showOptionCounts?: boolean;
+}
+
// @public
export function NumericalFacets({ searchOnChange, includedFieldIds, getFilterDisplayName, inputPrefix, customCssClasses, ...filterGroupProps }: NumericalFacetsProps): JSX.Element;
diff --git a/src/components/FacetProps.tsx b/src/components/FacetProps.tsx
index de5de039a..018b4356d 100644
--- a/src/components/FacetProps.tsx
+++ b/src/components/FacetProps.tsx
@@ -1,6 +1,8 @@
import { DisplayableFacetOption } from '@yext/search-headless-react';
import { FilterGroupCssClasses } from './FilterGroup';
import { ReactElement } from 'react';
+import { NumberRangeValue } from '@yext/search-headless-react';
+import { RangeInputCssClasses } from './Filters';
/**
* The CSS class interface for {@link Facets}.
@@ -27,7 +29,7 @@ export interface FacetsProps {
/** The custom facet components that will override the default rendering.
*
* @remarks
- * Supported components include {@link StandardFacet}.
+ * Supported components include {@link StandardFacet}, {@link NumericalFacet}.
*/
children?: ReactElement[] | ReactElement | undefined | null
}
@@ -56,9 +58,34 @@ export interface StandardFacetProps {
customCssClasses?: FilterGroupCssClasses
}
+/**
+ * Props for the {@link StandardFacet} component.
+ *
+ * @public
+ */
+export interface NumericalFacetProps extends StandardFacetProps {
+ /** Whether or not to show the option counts for each filter. Defaults to false. */
+ showOptionCounts?: boolean,
+ /** CSS classes for customizing the component styling. */
+ customCssClasses?: FilterGroupCssClasses & RangeInputCssClasses,
+ /**
+ * Returns the filter's display name based on the range values which is used when the filter
+ * is displayed by other components such as AppliedFilters.
+ *
+ * @remarks
+ * By default, the displayName separates the range with a dash such as '10 - 20'.
+ * If the range is unbounded, it will display as 'Up to 20' or 'Over 10'.
+ */
+ getFilterDisplayName?: (value: NumberRangeValue) => string,
+ /**
+ * An optional element which renders in front of the input text.
+ */
+ inputPrefix?: JSX.Element
+}
+
/**
* Props for a single facet component.
*
* @public
*/
-export type FacetProps = StandardFacetProps;
+export type FacetProps = StandardFacetProps | NumericalFacetProps;
diff --git a/src/components/Facets.tsx b/src/components/Facets.tsx
index d03ebf5bb..348b95498 100644
--- a/src/components/Facets.tsx
+++ b/src/components/Facets.tsx
@@ -2,13 +2,13 @@ import { FacetsProvider } from './Filters';
import { StandardFacetContent } from './StandardFacetContent';
import {
FacetProps,
- FacetsProps,
+ FacetsProps, NumericalFacetProps,
StandardFacetProps
} from './FacetProps';
import { isNumericalFacet, isStringFacet } from '../utils/filterutils';
import { FilterDivider } from './FilterDivider';
import { Fragment, ReactElement } from 'react';
-import { NumericalFacets } from './NumericalFacets';
+import { NumericalFacetContent } from './NumericalFacetContent';
/** @internal */
enum FacetType {
@@ -26,7 +26,7 @@ enum FacetType {
* and {@link HierarchicalFacets} components can be used instead for more control over facet
* configuration.
*
- * To override a single facet, use {@link StandardFacet}.
+ * To override a single facet, use {@link StandardFacet} or {@link NumericalFacet}.
*
* @param props - {@link FacetsProps}
* @returns A React component for facets
@@ -68,16 +68,12 @@ export function Facets(props: FacetsProps) {
let facetComponent: ReactElement;
switch (facetType) {
case FacetType.NUMERICAL:
- facetComponent = ;
+ facetComponent = ();
break;
case FacetType.STANDARD:
// fall through
default:
- facetComponent = (
- );
+ facetComponent = ();
}
return (
@@ -89,7 +85,6 @@ export function Facets(props: FacetsProps) {
})
}
-
);
}
@@ -103,6 +98,15 @@ export function Facets(props: FacetsProps) {
*/
export function StandardFacet(props: StandardFacetProps) { return null; }
+/**
+ * A component that displays a single numerical facet. Use this to override the default rendering.
+ *
+ * @param props - {@link NumericalFacetProps}
+ * @returns ReactElement
+ * @public
+ */
+export function NumericalFacet(props: NumericalFacetProps) { return null; }
+
/**
* Returns the type of the facet based on the props.
* @param elementType - string
@@ -112,7 +116,9 @@ export function StandardFacet(props: StandardFacetProps) { return null; }
*/
export function getFacetTypeFromReactElementType(elementType: string) {
switch (elementType) {
- case StandardFacet.toString():
+ case NumericalFacet.name.toString():
+ return FacetType.NUMERICAL;
+ case StandardFacet.name.toString():
// fall through
default:
return FacetType.STANDARD;
diff --git a/src/components/NumericalFacetContent.tsx b/src/components/NumericalFacetContent.tsx
new file mode 100644
index 000000000..9583e4b9b
--- /dev/null
+++ b/src/components/NumericalFacetContent.tsx
@@ -0,0 +1,50 @@
+import { FilterGroup } from './FilterGroup';
+import { DisplayableFacet } from '@yext/search-headless-react';
+import { NumericalFacetProps } from './FacetProps';
+import { RangeInput } from './Filters';
+
+const DEFAULT_RANGE_INPUT_PREFIX = <>$>;
+
+/**
+ * A component that displays the content of a numerical facet.
+ *
+ * @param props - props to render the component
+ * @returns A React component for the content of a standard facet
+ *
+ * @internal
+ */
+export function NumericalFacetContent({
+ fieldId,
+ customCssClasses,
+ transformOptions,
+ getFilterDisplayName,
+ facet,
+ label = '',
+ showMoreLimit = 10,
+ showOptionCounts = false,
+ inputPrefix = DEFAULT_RANGE_INPUT_PREFIX,
+ ...filterGroupProps
+}: NumericalFacetProps & { facet: DisplayableFacet }) {
+ const options = facet.options || [];
+ const transformedOptions = transformOptions ? (transformOptions(options) || []) : options;
+
+ return (
+