From 0a1797290f81c641b8e6b2986058e421815c9651 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 13:57:48 -0700 Subject: [PATCH 01/36] feat(refinementList): show more count --- .../src/components/RefinementList/RefinementList.tsx | 2 ++ .../refinement-list/connectRefinementList.ts | 12 ++++++++++++ .../src/widgets/refinement-list/refinement-list.tsx | 2 ++ 3 files changed, 16 insertions(+) diff --git a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx index 94b6921bd2..76a8831ffb 100644 --- a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx @@ -68,6 +68,7 @@ export type RefinementListProps = { showMore?: boolean; toggleShowMore?: () => void; isShowingMore?: boolean; + showMoreCount?: number; hasExhaustiveItems?: boolean; canToggleShowMore?: boolean; className?: string; @@ -307,6 +308,7 @@ class RefinementList extends Component< }} data={{ isShowingMore: this.props.isShowingMore, + showMoreCount: this.props.showMoreCount, }} /> ); diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 34052fb4f0..f6d78c3d54 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -135,6 +135,10 @@ export type RefinementListRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -234,6 +238,7 @@ const connectRefinementList: RefinementListConnector = let sendEvent: RefinementListRenderState['sendEvent'] | undefined; let isShowingMore = false; + let showMoreCount = 0; // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let toggleShowMore = () => {}; @@ -321,6 +326,7 @@ const connectRefinementList: RefinementListConnector = }), items: normalizedFacetValues, canToggleShowMore: false, + showMoreCount, canRefine: true, isFromSearch: true, instantSearchInstance, @@ -370,6 +376,7 @@ const connectRefinementList: RefinementListConnector = renderOptions; let items: RefinementListItem[] = []; let facetValues: SearchResults.FacetValue[] | FacetHit[] = []; + showMoreCount = 0; if (!sendEvent || !triggerRefine || !searchForFacetValues) { sendEvent = createSendEventForFacet({ @@ -414,6 +421,10 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; + if (facetValues.length > 0 && facetValues.length > currentLimit) { + showMoreCount = Object.keys(facetValues).length - currentLimit; + } + if (renderOptions.results) { toggleShowMore = createToggleShowMore(renderOptions, this); } @@ -442,6 +453,7 @@ const connectRefinementList: RefinementListConnector = canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, canToggleShowMore, toggleShowMore: cachedToggleShowMore, sendEvent, diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 8afd84e3c5..1fd4a5a467 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -243,6 +243,7 @@ const renderer = instantSearchInstance, toggleShowMore, isShowingMore, + showMoreCount, hasExhaustiveItems, canToggleShowMore, }, @@ -277,6 +278,7 @@ const renderer = showMore={showMore && !isFromSearch && items.length > 0} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} hasExhaustiveItems={hasExhaustiveItems} canToggleShowMore={canToggleShowMore} />, From 52c38110c250b89cc7bed294055855b4d87cd7e8 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 15:50:33 -0700 Subject: [PATCH 02/36] feat(refinementList): updated react test --- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index fc79c78dc7..9f72a172ed 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -21,6 +21,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From 86c402045e5a970340655d0576101b40369010de Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:14:01 -0700 Subject: [PATCH 03/36] feat(refinementList): updated count check --- .../connectors/refinement-list/connectRefinementList.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index f6d78c3d54..b6afafd999 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -421,8 +421,12 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; - if (facetValues.length > 0 && facetValues.length > currentLimit) { - showMoreCount = Object.keys(facetValues).length - currentLimit; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetValues.length + ? showMoreLimit + : facetValues.length; + showMoreCount = showMoreTotalCount - currentLimit; } if (renderOptions.results) { From cdae18c910a378debdfe7bd419b26b2ee0dad04f Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:24:31 -0700 Subject: [PATCH 04/36] feat(refinementList): updated tests --- .../src/ui/RefinementList.tsx | 3 +++ .../src/ui/ShowMoreButton.tsx | 8 +++++++- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx index 3887fe95a4..48e4e2c196 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx @@ -19,6 +19,7 @@ export type RefinementListProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; classNames?: Partial; translations: RefinementListTranslations; }; @@ -91,6 +92,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, className, classNames = {}, translations, @@ -190,6 +192,7 @@ export function RefinementList({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx index f8c35c654d..6dd2774112 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx @@ -2,6 +2,7 @@ import React from 'react'; type ShowMoreButtonProps = React.ComponentProps<'button'> & { isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -10,6 +11,10 @@ export type ShowMoreButtonTextOptions = { * Whether the widget is showing more items or not. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; }; export type ShowMoreButtonTranslations = { @@ -21,12 +26,13 @@ export type ShowMoreButtonTranslations = { export function ShowMoreButton({ isShowingMore, + showMoreCount, translations, ...props }: ShowMoreButtonProps) { return ( ); } diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index 9f72a172ed..3a5644afea 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -39,6 +39,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From b4ce94b084e4d405f79ed5c268cab2ee49c85841 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 14:07:06 -0700 Subject: [PATCH 05/36] feat(refinementList): Applied change to hierarchicalMenu & menu --- .../connectHierarchicalMenu.ts | 21 ++++++++++++++++--- .../src/connectors/menu/connectMenu.ts | 19 +++++++++++++++-- .../hierarchical-menu/hierarchical-menu.tsx | 6 ++++-- .../src/widgets/menu/menu.tsx | 8 +++---- .../refinement-list/refinement-list.tsx | 4 ++-- .../src/ui/HierarchicalMenu.tsx | 3 +++ .../src/ui/Menu.tsx | 3 +++ .../src/widgets/HierarchicalMenu.tsx | 3 +++ .../src/widgets/Menu.tsx | 3 +++ .../src/widgets/RefinementList.tsx | 3 +++ 10 files changed, 60 insertions(+), 13 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index 0ec7595c14..d947a9a773 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -113,6 +113,10 @@ export type HierarchicalMenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -222,6 +226,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = let _refine: HierarchicalMenuRenderState['refine'] | undefined; let isShowingMore = false; + let showMoreCount = 0; function createToggleShowMore( renderOptions: RenderOptions, @@ -347,6 +352,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(hierarchicalFacetName, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -363,9 +369,17 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = // Because this is used for making the search of facets unable or not, it is important // to be conservative here. const hasExhaustiveItems = - (state.maxValuesPerFacet || 0) > getLimit() - ? facetItems.length <= getLimit() - : facetItems.length < getLimit(); + (state.maxValuesPerFacet || 0) > currentLimit + ? facetItems.length <= currentLimit + : facetItems.length < currentLimit; + + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } canToggleShowMore = showMore && (isShowingMore || !hasExhaustiveItems); @@ -383,6 +397,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = sendEvent, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index 4ca69716ca..887348d56d 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -96,6 +96,10 @@ export type MenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMore.limit`. */ @@ -182,6 +186,7 @@ const connectMenu: MenuConnector = function connectMenu( // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let isShowingMore = false; + let showMoreCount = 0; let toggleShowMore = () => {}; function createToggleShowMore( renderOptions: RenderOptions, @@ -289,6 +294,7 @@ const connectMenu: MenuConnector = function connectMenu( } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(attribute, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -298,12 +304,20 @@ const connectMenu: MenuConnector = function connectMenu( ? facetValues.data : []; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } + canToggleShowMore = - showMore && (isShowingMore || facetItems.length > getLimit()); + showMore && (isShowingMore || facetItems.length > currentLimit); items = transformItems( facetItems - .slice(0, getLimit()) + .slice(0, currentLimit) .map(({ name: label, escapedValue: value, path, ...item }) => ({ ...item, label, @@ -321,6 +335,7 @@ const connectMenu: MenuConnector = function connectMenu( canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx index d3d86c00d8..685cb70fe1 100644 --- a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx +++ b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx @@ -48,9 +48,9 @@ type HierarchicalMenuTemplates = Partial<{ cssClasses: HierarchicalMenuCSSClasses; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type HierarchicalMenuCSSClasses = Partial<{ @@ -208,6 +208,7 @@ const renderer = refine, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: HierarchicalMenuRenderState & @@ -233,6 +234,7 @@ const renderer = showMore={showMore} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/menu/menu.tsx b/packages/instantsearch.js/src/widgets/menu/menu.tsx index 51d798dafb..88dc52d26a 100644 --- a/packages/instantsearch.js/src/widgets/menu/menu.tsx +++ b/packages/instantsearch.js/src/widgets/menu/menu.tsx @@ -86,11 +86,9 @@ export type MenuTemplates = Partial<{ value: string; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ - isShowingMore: boolean; - }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type MenuComponentCSSClasses = ComponentCSSClasses; @@ -135,6 +133,7 @@ const renderer = createURL, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: MenuRenderState & RendererOptions, @@ -164,6 +163,7 @@ const renderer = toggleRefinement={refine} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 1fd4a5a467..59887aebb1 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -143,9 +143,9 @@ export type RefinementListOwnTemplates = Partial<{ */ item: Template; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; /** * Templates to use for search for facet values when there are no results. */ diff --git a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx index 688b1fa33e..b99775a25e 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx @@ -78,6 +78,7 @@ export type HierarchicalMenuProps = React.ComponentProps<'div'> & canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -167,6 +168,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, translations, ...props }: HierarchicalMenuProps) { @@ -201,6 +203,7 @@ export function HierarchicalMenu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx index 61b217d917..b66e499898 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx @@ -14,6 +14,7 @@ export type MenuProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; createURL: CreateURL; onRefine: (item: MenuItem) => void; translations: MenuTranslations; @@ -71,6 +72,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, createURL, onRefine, translations, @@ -127,6 +129,7 @@ export function Menu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx index dc7b4eab6e..f6c938f7b4 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx @@ -15,6 +15,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -45,6 +46,7 @@ export function HierarchicalMenu({ canToggleShowMore, createURL, isShowingMore, + showMoreCount, refine, toggleShowMore, } = useHierarchicalMenu( @@ -72,6 +74,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx index b0fa3e5aa1..d2ca7b69a8 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx @@ -14,6 +14,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -33,6 +34,7 @@ export function Menu({ const { canToggleShowMore, isShowingMore, + showMoreCount, items, refine, createURL, @@ -58,6 +60,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx index 06d2a75e86..576ef6328c 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx @@ -21,6 +21,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -60,6 +61,7 @@ export function RefinementList({ canToggleShowMore, isFromSearch, isShowingMore, + showMoreCount, items, refine, searchForItems, @@ -145,6 +147,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText: mergedTranslations.showMoreButtonText, }, From 2c0b70ff207081b340286a6ecc47d772c224afc9 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 17:02:00 -0700 Subject: [PATCH 06/36] feat(refinementList): updated tests --- .../__tests__/connectHierarchicalMenu-test.ts | 5 +++++ .../src/connectors/menu/__tests__/connectMenu-test.ts | 4 ++++ .../__tests__/connectRefinementList-test.ts | 8 ++++++++ .../menu/__tests__/__snapshots__/menu-test.ts.snap | 2 ++ .../src/ui/__tests__/HierarchicalMenu.test.tsx | 1 + .../src/ui/__tests__/Menu.test.tsx | 1 + .../src/ui/__tests__/RefinementList.test.tsx | 1 + .../src/connectors/__tests__/useHierarchicalMenu.test.tsx | 2 ++ .../src/connectors/__tests__/useMenu.test.tsx | 2 ++ 9 files changed, 26 insertions(+) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts index f42c3ed694..b43017f624 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts @@ -620,6 +620,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica attributes: ['anotherCategory', 'anotherSubCategory'], }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: () => {}, canToggleShowMore: false, }, @@ -641,6 +642,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -713,6 +715,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -751,6 +754,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -821,6 +825,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); diff --git a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts index cb40363427..11b7fe2988 100644 --- a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts @@ -628,6 +628,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -673,6 +674,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co createURL: expect.any(Function), widgetParams: { attribute: 'brand' }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -706,6 +708,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -765,6 +768,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: true, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, diff --git a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts index 64d0dad964..186d267efb 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts @@ -1091,6 +1091,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1125,6 +1126,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // should be 0; canToggleShowMore: false, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1160,6 +1162,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1201,6 +1204,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: true, + showMoreCount: 0, // @todo should be 1; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -2455,6 +2459,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2515,6 +2520,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [ { count: 88, @@ -2575,6 +2581,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2618,6 +2625,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap index 8bf2991858..8212f5cc4a 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap @@ -41,6 +41,7 @@ exports[`menu render renders transformed items 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], @@ -96,6 +97,7 @@ exports[`menu render snapshot 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx index 42af221dd4..c40e98c8d8 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx @@ -59,6 +59,7 @@ describe('HierarchicalMenu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx index 91aebaaba5..c8ee1273c2 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx @@ -32,6 +32,7 @@ describe('Menu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index 04a1dc5064..df82c89ee1 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -36,6 +36,7 @@ describe('RefinementList', () => { searchBox: null, canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, onToggleShowMore: jest.fn(), translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx index 997c6f787e..28fdabc3bd 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx @@ -19,6 +19,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx index 3ab9038f05..cf37c7138a 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx @@ -19,6 +19,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), From bf504526dfcdcd745d26fe19b20b16a17b8ad4ba Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 21 Apr 2023 06:45:34 -0700 Subject: [PATCH 07/36] feat(refinementList): updated tests --- .../src/ui/__tests__/ShowMoreButton.test.tsx | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx index 539451897d..24c2d8de51 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx @@ -19,6 +19,7 @@ describe('ShowMoreButton', () => { const { container } = render( ); @@ -34,7 +35,11 @@ describe('ShowMoreButton', () => { test('changes the button label when is showing more', () => { const { container } = render( - + ); expect(container).toMatchInlineSnapshot(` @@ -51,6 +56,7 @@ describe('ShowMoreButton', () => { const { getByRole } = render( @@ -66,6 +72,7 @@ describe('ShowMoreButton', () => { const { container, getByRole } = render( { }, }; const { getByRole, rerender } = render( - + ); expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); rerender( - + ); expect(getByRole('button', { name: 'Display more' })).toBeInTheDocument(); }); + + test('renders show more count', () => { + const translations = { + showMoreButtonText({ + isShowingMore, + showMoreCount, + }: { + isShowingMore: boolean; + showMoreCount: number; + }) { + return isShowingMore ? 'Display less' : `Display ${showMoreCount} more`; + }, + }; + const { getByRole, rerender } = render( + + ); + + expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); + + rerender( + + ); + + expect(getByRole('button', { name: 'Display 5 more' })).toBeInTheDocument(); + }); }); From a84d505e70d901481498c495fa8040182db85eb3 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 21 Apr 2023 12:44:33 -0700 Subject: [PATCH 08/36] feat(refinementList): updated storybook --- .../stories/hierarchical-menu.stories.ts | 45 +++++++++++++++++++ .../instantsearch.js/stories/menu.stories.ts | 18 ++++++++ .../stories/refinement-list.stories.ts | 18 ++++++++ 3 files changed, 81 insertions(+) diff --git a/packages/instantsearch.js/stories/hierarchical-menu.stories.ts b/packages/instantsearch.js/stories/hierarchical-menu.stories.ts index d2effddfeb..80cd99c3c4 100644 --- a/packages/instantsearch.js/stories/hierarchical-menu.stories.ts +++ b/packages/instantsearch.js/stories/hierarchical-menu.stories.ts @@ -134,6 +134,51 @@ storiesOf('Refinements/HierarchicalMenu', module) ]); }) ) + .add( + 'with show more and templates', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.hierarchicalMenu({ + container, + attributes: [ + 'hierarchicalCategories.lvl0', + 'hierarchicalCategories.lvl1', + 'hierarchicalCategories.lvl2', + 'hierarchicalCategories.lvl3', + ], + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText: ({ isShowingMore }) => (isShowingMore ? '⬆️' : '⬇️'), + }, + }), + ]); + }) + ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.hierarchicalMenu({ + container, + attributes: [ + 'hierarchicalCategories.lvl0', + 'hierarchicalCategories.lvl1', + 'hierarchicalCategories.lvl2', + 'hierarchicalCategories.lvl3', + ], + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with transformed items', withHits(({ search, container, instantsearch }) => { diff --git a/packages/instantsearch.js/stories/menu.stories.ts b/packages/instantsearch.js/stories/menu.stories.ts index af6761ec5b..d0b9490bc7 100644 --- a/packages/instantsearch.js/stories/menu.stories.ts +++ b/packages/instantsearch.js/stories/menu.stories.ts @@ -74,6 +74,24 @@ storiesOf('Refinements/Menu', module) ]); }) ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.menu({ + container, + attribute: 'categories', + limit: 3, + showMore: true, + showMoreLimit: 10, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with add/remove', withHits(({ search, container, instantsearch }) => { diff --git a/packages/instantsearch.js/stories/refinement-list.stories.ts b/packages/instantsearch.js/stories/refinement-list.stories.ts index fbf8fd1652..f5e6b1cb97 100644 --- a/packages/instantsearch.js/stories/refinement-list.stories.ts +++ b/packages/instantsearch.js/stories/refinement-list.stories.ts @@ -45,6 +45,24 @@ storiesOf('Refinements/RefinementList', module) ]); }) ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.refinementList({ + container, + attribute: 'brand', + limit: 3, + showMore: true, + showMoreLimit: 10, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with search inside items', withHits(({ search, container, instantsearch }) => { From a68b0accc8f29dddbbc400a438490d2c23aa0d77 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 13:57:48 -0700 Subject: [PATCH 09/36] feat(refinementList): show more count --- .../src/components/RefinementList/RefinementList.tsx | 2 ++ .../refinement-list/connectRefinementList.ts | 12 ++++++++++++ .../src/widgets/refinement-list/refinement-list.tsx | 2 ++ 3 files changed, 16 insertions(+) diff --git a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx index eb573b47f1..b89948e98a 100644 --- a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx @@ -68,6 +68,7 @@ export type RefinementListProps = { showMore?: boolean; toggleShowMore?: () => void; isShowingMore?: boolean; + showMoreCount?: number; hasExhaustiveItems?: boolean; canToggleShowMore?: boolean; className?: string; @@ -302,6 +303,7 @@ class RefinementList extends Component< }} data={{ isShowingMore: this.props.isShowingMore, + showMoreCount: this.props.showMoreCount, }} /> ); diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 673606304c..5dc59c2ba8 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -136,6 +136,10 @@ export type RefinementListRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -235,6 +239,7 @@ const connectRefinementList: RefinementListConnector = let sendEvent: RefinementListRenderState['sendEvent'] | undefined; let isShowingMore = false; + let showMoreCount = 0; // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let toggleShowMore = () => {}; @@ -322,6 +327,7 @@ const connectRefinementList: RefinementListConnector = }), items: normalizedFacetValues, canToggleShowMore: false, + showMoreCount, canRefine: true, isFromSearch: true, instantSearchInstance, @@ -371,6 +377,7 @@ const connectRefinementList: RefinementListConnector = renderOptions; let items: RefinementListItem[] = []; let facetValues: SearchResults.FacetValue[] | FacetHit[] = []; + showMoreCount = 0; if (!sendEvent || !triggerRefine || !searchForFacetValues) { sendEvent = createSendEventForFacet({ @@ -415,6 +422,10 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; + if (facetValues.length > 0 && facetValues.length > currentLimit) { + showMoreCount = Object.keys(facetValues).length - currentLimit; + } + if (renderOptions.results) { toggleShowMore = createToggleShowMore(renderOptions, this); } @@ -443,6 +454,7 @@ const connectRefinementList: RefinementListConnector = canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, canToggleShowMore, toggleShowMore: cachedToggleShowMore, sendEvent, diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 8afd84e3c5..1fd4a5a467 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -243,6 +243,7 @@ const renderer = instantSearchInstance, toggleShowMore, isShowingMore, + showMoreCount, hasExhaustiveItems, canToggleShowMore, }, @@ -277,6 +278,7 @@ const renderer = showMore={showMore && !isFromSearch && items.length > 0} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} hasExhaustiveItems={hasExhaustiveItems} canToggleShowMore={canToggleShowMore} />, From b3b77e3dec53332283d82d84fe196294e87e7ac4 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 15:50:33 -0700 Subject: [PATCH 10/36] feat(refinementList): updated react test --- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index fc79c78dc7..9f72a172ed 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -21,6 +21,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From 8a978060aba519e41d5578e07a0dda6aa05c19ab Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:14:01 -0700 Subject: [PATCH 11/36] feat(refinementList): updated count check --- .../connectors/refinement-list/connectRefinementList.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 5dc59c2ba8..e80a03bb40 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -422,8 +422,12 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; - if (facetValues.length > 0 && facetValues.length > currentLimit) { - showMoreCount = Object.keys(facetValues).length - currentLimit; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetValues.length + ? showMoreLimit + : facetValues.length; + showMoreCount = showMoreTotalCount - currentLimit; } if (renderOptions.results) { From b06f2ad5fbaadbd7d6a806f84fe685f6ac73a1ba Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:24:31 -0700 Subject: [PATCH 12/36] feat(refinementList): updated tests --- .../src/ui/RefinementList.tsx | 3 +++ .../src/ui/ShowMoreButton.tsx | 8 +++++++- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx index 037ac62312..c5d87cf73d 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx @@ -19,6 +19,7 @@ export type RefinementListProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; classNames?: Partial; translations: RefinementListTranslations; }; @@ -91,6 +92,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, className, classNames = {}, translations, @@ -190,6 +192,7 @@ export function RefinementList({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx index bee8841819..0749ba5932 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx @@ -2,6 +2,7 @@ import React from 'react'; type ShowMoreButtonProps = React.ComponentProps<'button'> & { isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -10,6 +11,10 @@ export type ShowMoreButtonTextOptions = { * Whether the widget is showing more items or not. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; }; export type ShowMoreButtonTranslations = { @@ -21,12 +26,13 @@ export type ShowMoreButtonTranslations = { export function ShowMoreButton({ isShowingMore, + showMoreCount, translations, ...props }: ShowMoreButtonProps) { return ( ); } diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index 9f72a172ed..3a5644afea 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -39,6 +39,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From f78041b7eef6a3109fa0838d1d23adf68aad62a8 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 14:07:06 -0700 Subject: [PATCH 13/36] feat(refinementList): Applied change to hierarchicalMenu & menu --- .../connectHierarchicalMenu.ts | 21 ++++++++++++++++--- .../src/connectors/menu/connectMenu.ts | 19 +++++++++++++++-- .../hierarchical-menu/hierarchical-menu.tsx | 6 ++++-- .../src/widgets/menu/menu.tsx | 8 +++---- .../refinement-list/refinement-list.tsx | 4 ++-- .../src/ui/HierarchicalMenu.tsx | 3 +++ .../src/ui/Menu.tsx | 3 +++ .../src/widgets/HierarchicalMenu.tsx | 3 +++ .../src/widgets/Menu.tsx | 3 +++ .../src/widgets/RefinementList.tsx | 3 +++ 10 files changed, 60 insertions(+), 13 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index 68cdabc1c0..a8d8784e8a 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -113,6 +113,10 @@ export type HierarchicalMenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -222,6 +226,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = let _refine: HierarchicalMenuRenderState['refine'] | undefined; let isShowingMore = false; + let showMoreCount = 0; function createToggleShowMore( renderOptions: RenderOptions, @@ -347,6 +352,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(hierarchicalFacetName, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -363,9 +369,17 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = // Because this is used for making the search of facets unable or not, it is important // to be conservative here. const hasExhaustiveItems = - (state.maxValuesPerFacet || 0) > getLimit() - ? facetItems.length <= getLimit() - : facetItems.length < getLimit(); + (state.maxValuesPerFacet || 0) > currentLimit + ? facetItems.length <= currentLimit + : facetItems.length < currentLimit; + + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } canToggleShowMore = showMore && (isShowingMore || !hasExhaustiveItems); @@ -383,6 +397,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = sendEvent, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index 5eb54de735..e1068acb1d 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -96,6 +96,10 @@ export type MenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMore.limit`. */ @@ -182,6 +186,7 @@ const connectMenu: MenuConnector = function connectMenu( // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let isShowingMore = false; + let showMoreCount = 0; let toggleShowMore = () => {}; function createToggleShowMore( renderOptions: RenderOptions, @@ -289,6 +294,7 @@ const connectMenu: MenuConnector = function connectMenu( } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(attribute, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -298,12 +304,20 @@ const connectMenu: MenuConnector = function connectMenu( ? facetValues.data : []; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } + canToggleShowMore = - showMore && (isShowingMore || facetItems.length > getLimit()); + showMore && (isShowingMore || facetItems.length > currentLimit); items = transformItems( facetItems - .slice(0, getLimit()) + .slice(0, currentLimit) .map(({ name: label, escapedValue: value, path, ...item }) => ({ ...item, label, @@ -321,6 +335,7 @@ const connectMenu: MenuConnector = function connectMenu( canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx index d3d86c00d8..685cb70fe1 100644 --- a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx +++ b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx @@ -48,9 +48,9 @@ type HierarchicalMenuTemplates = Partial<{ cssClasses: HierarchicalMenuCSSClasses; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type HierarchicalMenuCSSClasses = Partial<{ @@ -208,6 +208,7 @@ const renderer = refine, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: HierarchicalMenuRenderState & @@ -233,6 +234,7 @@ const renderer = showMore={showMore} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/menu/menu.tsx b/packages/instantsearch.js/src/widgets/menu/menu.tsx index 51d798dafb..88dc52d26a 100644 --- a/packages/instantsearch.js/src/widgets/menu/menu.tsx +++ b/packages/instantsearch.js/src/widgets/menu/menu.tsx @@ -86,11 +86,9 @@ export type MenuTemplates = Partial<{ value: string; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ - isShowingMore: boolean; - }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type MenuComponentCSSClasses = ComponentCSSClasses; @@ -135,6 +133,7 @@ const renderer = createURL, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: MenuRenderState & RendererOptions, @@ -164,6 +163,7 @@ const renderer = toggleRefinement={refine} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 1fd4a5a467..59887aebb1 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -143,9 +143,9 @@ export type RefinementListOwnTemplates = Partial<{ */ item: Template; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; /** * Templates to use for search for facet values when there are no results. */ diff --git a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx index 688b1fa33e..b99775a25e 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx @@ -78,6 +78,7 @@ export type HierarchicalMenuProps = React.ComponentProps<'div'> & canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -167,6 +168,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, translations, ...props }: HierarchicalMenuProps) { @@ -201,6 +203,7 @@ export function HierarchicalMenu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx index 61b217d917..b66e499898 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx @@ -14,6 +14,7 @@ export type MenuProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; createURL: CreateURL; onRefine: (item: MenuItem) => void; translations: MenuTranslations; @@ -71,6 +72,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, createURL, onRefine, translations, @@ -127,6 +129,7 @@ export function Menu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx index dc7b4eab6e..f6c938f7b4 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx @@ -15,6 +15,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -45,6 +46,7 @@ export function HierarchicalMenu({ canToggleShowMore, createURL, isShowingMore, + showMoreCount, refine, toggleShowMore, } = useHierarchicalMenu( @@ -72,6 +74,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx index b0fa3e5aa1..d2ca7b69a8 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx @@ -14,6 +14,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -33,6 +34,7 @@ export function Menu({ const { canToggleShowMore, isShowingMore, + showMoreCount, items, refine, createURL, @@ -58,6 +60,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx index 06d2a75e86..576ef6328c 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx @@ -21,6 +21,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -60,6 +61,7 @@ export function RefinementList({ canToggleShowMore, isFromSearch, isShowingMore, + showMoreCount, items, refine, searchForItems, @@ -145,6 +147,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText: mergedTranslations.showMoreButtonText, }, From ab54c9d3d281df5d180ee5ae3b86ff14382775f1 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 17:02:00 -0700 Subject: [PATCH 14/36] feat(refinementList): updated tests --- .../__tests__/connectHierarchicalMenu-test.ts | 5 +++++ .../src/connectors/menu/__tests__/connectMenu-test.ts | 4 ++++ .../__tests__/connectRefinementList-test.ts | 8 ++++++++ .../menu/__tests__/__snapshots__/menu-test.ts.snap | 2 ++ .../src/ui/__tests__/HierarchicalMenu.test.tsx | 1 + .../src/ui/__tests__/Menu.test.tsx | 1 + .../src/ui/__tests__/RefinementList.test.tsx | 1 + .../src/connectors/__tests__/useHierarchicalMenu.test.tsx | 2 ++ .../src/connectors/__tests__/useMenu.test.tsx | 2 ++ 9 files changed, 26 insertions(+) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts index 109db9d173..bd1cc78719 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts @@ -620,6 +620,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica attributes: ['anotherCategory', 'anotherSubCategory'], }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: () => {}, canToggleShowMore: false, }, @@ -641,6 +642,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -713,6 +715,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -751,6 +754,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -821,6 +825,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); diff --git a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts index 4a6af23a3c..c01b6c9b08 100644 --- a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts @@ -628,6 +628,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -673,6 +674,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co createURL: expect.any(Function), widgetParams: { attribute: 'brand' }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -706,6 +708,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -765,6 +768,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: true, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, diff --git a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts index 067b47186b..23cf6e2892 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts @@ -1091,6 +1091,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1125,6 +1126,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // should be 0; canToggleShowMore: false, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1160,6 +1162,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1201,6 +1204,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: true, + showMoreCount: 0, // @todo should be 1; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -2455,6 +2459,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2515,6 +2520,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [ { count: 88, @@ -2575,6 +2581,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2618,6 +2625,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap index 8bf2991858..8212f5cc4a 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap @@ -41,6 +41,7 @@ exports[`menu render renders transformed items 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], @@ -96,6 +97,7 @@ exports[`menu render snapshot 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx index 42af221dd4..c40e98c8d8 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx @@ -59,6 +59,7 @@ describe('HierarchicalMenu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx index 91aebaaba5..c8ee1273c2 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx @@ -32,6 +32,7 @@ describe('Menu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index 04a1dc5064..df82c89ee1 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -36,6 +36,7 @@ describe('RefinementList', () => { searchBox: null, canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, onToggleShowMore: jest.fn(), translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx index 997c6f787e..28fdabc3bd 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx @@ -19,6 +19,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx index 3ab9038f05..cf37c7138a 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx @@ -19,6 +19,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), From ef3b18a132331ff2b66b079e866bcddcf8186cb3 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 21 Apr 2023 06:45:34 -0700 Subject: [PATCH 15/36] feat(refinementList): updated tests --- .../src/ui/__tests__/ShowMoreButton.test.tsx | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx index 539451897d..24c2d8de51 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx @@ -19,6 +19,7 @@ describe('ShowMoreButton', () => { const { container } = render( ); @@ -34,7 +35,11 @@ describe('ShowMoreButton', () => { test('changes the button label when is showing more', () => { const { container } = render( - + ); expect(container).toMatchInlineSnapshot(` @@ -51,6 +56,7 @@ describe('ShowMoreButton', () => { const { getByRole } = render( @@ -66,6 +72,7 @@ describe('ShowMoreButton', () => { const { container, getByRole } = render( { }, }; const { getByRole, rerender } = render( - + ); expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); rerender( - + ); expect(getByRole('button', { name: 'Display more' })).toBeInTheDocument(); }); + + test('renders show more count', () => { + const translations = { + showMoreButtonText({ + isShowingMore, + showMoreCount, + }: { + isShowingMore: boolean; + showMoreCount: number; + }) { + return isShowingMore ? 'Display less' : `Display ${showMoreCount} more`; + }, + }; + const { getByRole, rerender } = render( + + ); + + expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); + + rerender( + + ); + + expect(getByRole('button', { name: 'Display 5 more' })).toBeInTheDocument(); + }); }); From 68e1d2466e92de0fec0c8ba0e1803b019defba64 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 5 May 2023 20:44:55 -0700 Subject: [PATCH 16/36] feat(refinementList): added new tests --- .../__tests__/connectRefinementList-test.ts | 8 +- .../__tests__/refinement-list.test.tsx | 222 ++++++++++++++++++ .../src/ui/__tests__/RefinementList.test.tsx | 30 +++ 3 files changed, 256 insertions(+), 4 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts index 23cf6e2892..e8082f7721 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts @@ -1091,7 +1091,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // @todo should be 0; + showMoreCount: 1, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1126,7 +1126,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // should be 0; + showMoreCount: 1, canToggleShowMore: false, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1162,7 +1162,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // @todo should be 0; + showMoreCount: 1, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1204,7 +1204,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: true, - showMoreCount: 0, // @todo should be 1; + showMoreCount: 0, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, diff --git a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx index 6790d1e0a6..64d5aabe1c 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx @@ -851,6 +851,224 @@ describe('refinementList', () => { `); }); + test('renders with templates show more count', async () => { + const container = document.createElement('div'); + const searchClient = createMockedSearchClient(); + + const search = instantsearch({ + indexName: 'indexName', + searchClient, + initialUiState: { + indexName: { + refinementList: { + brand: ['Apple'], + }, + }, + }, + }); + + search.addWidgets([ + refinementList({ + container, + attribute: 'brand', + showMore: true, + searchable: true, + limit: 2, + showMoreLimit: 4, + templates: { + showMoreText({ isShowingMore, showMoreCount }) { + return isShowingMore + ? `Show top 2 items` + : `Show ${showMoreCount} more`; + }, + }, + }), + ]); + + search.start(); + + await wait(0); + + expect(container).toMatchInlineSnapshot(` +
+
+ +
    +
  • +
    + +
    +
  • +
  • +
    + +
    +
  • +
+ +
+
+`); + + const showMoreButton = container.querySelector( + '.ais-RefinementList-showMore' + )!; + + fireEvent.click(showMoreButton); + + expect(showMoreButton).toHaveTextContent('Show top 2 items'); + }); + function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { @@ -863,6 +1081,10 @@ describe('refinementList', () => { Apple: 746, Samsung: 633, Metra: 591, + Motorola: 434, + OtterBox: 143, + Speck: 114, + Platinum: 76, }, }, }) diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index df82c89ee1..df46d8efd7 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -682,4 +682,34 @@ describe('RefinementList', () => { getByRole('button', { name: 'Show less brands' }) ).toBeInTheDocument(); }); + + test('renders with translations show more count', () => { + const props = createProps({ + showMore: true, + translations: { + showMoreButtonText({ + isShowingMore, + showMoreCount, + }: { + isShowingMore: boolean; + showMoreCount: number; + }) { + return isShowingMore + ? `Show top 5 items` + : `Show ${showMoreCount} more`; + }, + }, + }); + const { getByRole, rerender } = render( + + ); + + expect(getByRole('button', { name: 'Show 5 more' })).toBeInTheDocument(); + + rerender(); + + expect( + getByRole('button', { name: 'Show top 5 items' }) + ).toBeInTheDocument(); + }); }); From 21fadcfa7194fa219db0015a83813d1485e887a5 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 5 May 2023 21:18:31 -0700 Subject: [PATCH 17/36] feat(refinementList): added new tests --- .../src/widgets/menu/__tests__/menu.test.tsx | 138 ++++++++++++++++++ .../__tests__/refinement-list.test.tsx | 25 +++- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx index 97a8137457..611eaa40f2 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx @@ -397,6 +397,144 @@ describe('menu', () => { `); }); + test('renders with templates show more count', async () => { + const container = document.createElement('div'); + const searchClient = createMockedSearchClient(); + + const search = instantsearch({ + indexName: 'indexName', + searchClient, + initialUiState: { + indexName: { + menu: { + brand: 'Apple', + }, + }, + }, + }); + + search.addWidgets([ + menu({ + container, + attribute: 'brand', + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText({ isShowingMore, showMoreCount }) { + return isShowingMore + ? `Show top 3 items` + : `Show ${showMoreCount} more`; + }, + }, + }), + ]); + + // @MAJOR Once Hogan.js and string-based templates are removed, + // `search.start()` can be moved to the test body and the following + // assertion can go away. + expect(async () => { + search.start(); + + await wait(0); + }).not.toWarnDev(); + + await wait(0); + + expect(container).toMatchInlineSnapshot(` +
+
+ + +
+
+`); + + const toggleButton = within(container).getByRole('button'); + + fireEvent.click(toggleButton); + + expect(toggleButton).toMatchInlineSnapshot(` + +`); + }); + function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { diff --git a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx index 64d5aabe1c..709b8d8d99 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx @@ -874,7 +874,7 @@ describe('refinementList', () => { showMore: true, searchable: true, limit: 2, - showMoreLimit: 4, + showMoreLimit: 6, templates: { showMoreText({ isShowingMore, showMoreCount }) { return isShowingMore @@ -1054,7 +1054,7 @@ describe('refinementList', () => { @@ -1081,10 +1081,23 @@ describe('refinementList', () => { Apple: 746, Samsung: 633, Metra: 591, - Motorola: 434, - OtterBox: 143, - Speck: 114, - Platinum: 76, + HP: 530, + 'Insignia™': 442, + GE: 394, + Sony: 350, + Incipio: 320, + KitchenAid: 318, + Whirlpool: 298, + LG: 291, + Canon: 287, + Frigidaire: 275, + Speck: 216, + OtterBox: 214, + Epson: 204, + 'Dynex™': 184, + Dell: 174, + 'Hamilton Beach': 173, + Platinum: 155, }, }, }) From af8a5fa42c81dbeb69879f65bc725f5541ac6b00 Mon Sep 17 00:00:00 2001 From: Mike Davis <77642365+mikedavis77@users.noreply.github.com> Date: Wed, 17 May 2023 14:59:38 -0700 Subject: [PATCH 18/36] Apply suggestions from code review Co-authored-by: Dhaya <154633+dhayab@users.noreply.github.com> --- .../hierarchical-menu/connectHierarchicalMenu.ts | 7 ++----- .../instantsearch.js/src/connectors/menu/connectMenu.ts | 7 ++----- .../connectors/refinement-list/connectRefinementList.ts | 7 ++----- .../src/ui/ShowMoreButton.tsx | 2 +- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index a8d8784e8a..df4fcb9d71 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -114,7 +114,7 @@ export type HierarchicalMenuRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -374,10 +374,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = : facetItems.length < currentLimit; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetItems.length - ? showMoreLimit - : facetItems.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index e1068acb1d..483ae436be 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -97,7 +97,7 @@ export type MenuRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -305,10 +305,7 @@ const connectMenu: MenuConnector = function connectMenu( : []; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetItems.length - ? showMoreLimit - : facetItems.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index e80a03bb40..52b5089beb 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -137,7 +137,7 @@ export type RefinementListRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -423,10 +423,7 @@ const connectRefinementList: RefinementListConnector = lastItemsFromMainSearch = items; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetValues.length - ? showMoreLimit - : facetValues.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetValues.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx index 0749ba5932..b194a6095b 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx @@ -12,7 +12,7 @@ export type ShowMoreButtonTextOptions = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; }; From c6be31fa8d9ae6ce63d9d3395143518e43bdd7ba Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 17 May 2023 15:55:48 -0700 Subject: [PATCH 19/36] fix lint errors --- .../connectors/hierarchical-menu/connectHierarchicalMenu.ts | 5 ++++- packages/instantsearch.js/src/connectors/menu/connectMenu.ts | 5 ++++- .../src/connectors/refinement-list/connectRefinementList.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index df4fcb9d71..c1333def5e 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -374,7 +374,10 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = : facetItems.length < currentLimit; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetItems.length + ); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index 483ae436be..f2773e7f4c 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -305,7 +305,10 @@ const connectMenu: MenuConnector = function connectMenu( : []; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetItems.length + ); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 52b5089beb..2a586824aa 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -423,7 +423,10 @@ const connectRefinementList: RefinementListConnector = lastItemsFromMainSearch = items; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetValues.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetValues.length + ); showMoreCount = showMoreTotalCount - currentLimit; } From 5aa3037ed0d05fa3cf726727a6351f5c1be0f0eb Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 17 May 2023 16:06:04 -0700 Subject: [PATCH 20/36] updated Vue package with showMoreCount --- .../vue-instantsearch/src/components/HierarchicalMenu.vue | 7 ++++++- packages/vue-instantsearch/src/components/Menu.vue | 7 ++++++- .../vue-instantsearch/src/components/RefinementList.vue | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/vue-instantsearch/src/components/HierarchicalMenu.vue b/packages/vue-instantsearch/src/components/HierarchicalMenu.vue index 0aefe0f765..31362b5515 100644 --- a/packages/vue-instantsearch/src/components/HierarchicalMenu.vue +++ b/packages/vue-instantsearch/src/components/HierarchicalMenu.vue @@ -8,6 +8,7 @@ :can-refine="state.canRefine" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :refine="state.refine" :createURL="state.createURL" :toggle-show-more="state.toggleShowMore" @@ -30,7 +31,11 @@ :disabled="!state.canToggleShowMore" @click.prevent="state.toggleShowMore" > - + {{ state.isShowingMore ? 'Show less' : 'Show more' }} diff --git a/packages/vue-instantsearch/src/components/Menu.vue b/packages/vue-instantsearch/src/components/Menu.vue index 30f07bb5e7..834a7991b8 100644 --- a/packages/vue-instantsearch/src/components/Menu.vue +++ b/packages/vue-instantsearch/src/components/Menu.vue @@ -8,6 +8,7 @@ :can-refine="state.canRefine" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :refine="state.refine" :createURL="state.createURL" :toggle-show-more="state.toggleShowMore" @@ -39,7 +40,11 @@ :disabled="!state.canToggleShowMore" @click.prevent="state.toggleShowMore()" > - + {{ state.isShowingMore ? 'Show less' : 'Show more' }} diff --git a/packages/vue-instantsearch/src/components/RefinementList.vue b/packages/vue-instantsearch/src/components/RefinementList.vue index e3c880e57d..df7b895fe5 100644 --- a/packages/vue-instantsearch/src/components/RefinementList.vue +++ b/packages/vue-instantsearch/src/components/RefinementList.vue @@ -11,6 +11,7 @@ :toggle-show-more="toggleShowMore" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :createURL="state.createURL" :is-from-search="state.isFromSearch" :can-refine="state.canRefine" @@ -70,7 +71,11 @@ v-if="showMore" :disabled="!state.canToggleShowMore" > - + Show {{ state.isShowingMore ? 'less' : 'more' }} From 666e359c8b76adbb071dfbf61bd6e5a04a204a4e Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 13:57:48 -0700 Subject: [PATCH 21/36] feat(refinementList): show more count --- .../src/components/RefinementList/RefinementList.tsx | 2 ++ .../refinement-list/connectRefinementList.ts | 12 ++++++++++++ .../src/widgets/refinement-list/refinement-list.tsx | 2 ++ 3 files changed, 16 insertions(+) diff --git a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx index eb573b47f1..b89948e98a 100644 --- a/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx +++ b/packages/instantsearch.js/src/components/RefinementList/RefinementList.tsx @@ -68,6 +68,7 @@ export type RefinementListProps = { showMore?: boolean; toggleShowMore?: () => void; isShowingMore?: boolean; + showMoreCount?: number; hasExhaustiveItems?: boolean; canToggleShowMore?: boolean; className?: string; @@ -302,6 +303,7 @@ class RefinementList extends Component< }} data={{ isShowingMore: this.props.isShowingMore, + showMoreCount: this.props.showMoreCount, }} /> ); diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 673606304c..5dc59c2ba8 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -136,6 +136,10 @@ export type RefinementListRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -235,6 +239,7 @@ const connectRefinementList: RefinementListConnector = let sendEvent: RefinementListRenderState['sendEvent'] | undefined; let isShowingMore = false; + let showMoreCount = 0; // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let toggleShowMore = () => {}; @@ -322,6 +327,7 @@ const connectRefinementList: RefinementListConnector = }), items: normalizedFacetValues, canToggleShowMore: false, + showMoreCount, canRefine: true, isFromSearch: true, instantSearchInstance, @@ -371,6 +377,7 @@ const connectRefinementList: RefinementListConnector = renderOptions; let items: RefinementListItem[] = []; let facetValues: SearchResults.FacetValue[] | FacetHit[] = []; + showMoreCount = 0; if (!sendEvent || !triggerRefine || !searchForFacetValues) { sendEvent = createSendEventForFacet({ @@ -415,6 +422,10 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; + if (facetValues.length > 0 && facetValues.length > currentLimit) { + showMoreCount = Object.keys(facetValues).length - currentLimit; + } + if (renderOptions.results) { toggleShowMore = createToggleShowMore(renderOptions, this); } @@ -443,6 +454,7 @@ const connectRefinementList: RefinementListConnector = canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, canToggleShowMore, toggleShowMore: cachedToggleShowMore, sendEvent, diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 8afd84e3c5..1fd4a5a467 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -243,6 +243,7 @@ const renderer = instantSearchInstance, toggleShowMore, isShowingMore, + showMoreCount, hasExhaustiveItems, canToggleShowMore, }, @@ -277,6 +278,7 @@ const renderer = showMore={showMore && !isFromSearch && items.length > 0} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} hasExhaustiveItems={hasExhaustiveItems} canToggleShowMore={canToggleShowMore} />, From 22e7ef7b0d09aa0c31e39b40e70e66f018c7bdb2 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 12 Apr 2023 15:50:33 -0700 Subject: [PATCH 22/36] feat(refinementList): updated react test --- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index fc79c78dc7..9f72a172ed 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -21,6 +21,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From 08b9e2b6e27de2993bcbc8c6b6270cb895c01c75 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:14:01 -0700 Subject: [PATCH 23/36] feat(refinementList): updated count check --- .../connectors/refinement-list/connectRefinementList.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 5dc59c2ba8..e80a03bb40 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -422,8 +422,12 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; - if (facetValues.length > 0 && facetValues.length > currentLimit) { - showMoreCount = Object.keys(facetValues).length - currentLimit; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetValues.length + ? showMoreLimit + : facetValues.length; + showMoreCount = showMoreTotalCount - currentLimit; } if (renderOptions.results) { From e6151fc7d56d3e62ee94b750e5261fb21e959877 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:24:31 -0700 Subject: [PATCH 24/36] feat(refinementList): updated tests --- .../src/ui/RefinementList.tsx | 3 +++ .../src/ui/ShowMoreButton.tsx | 8 +++++++- .../src/connectors/__tests__/useRefinementList.test.tsx | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx index 037ac62312..c5d87cf73d 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/RefinementList.tsx @@ -19,6 +19,7 @@ export type RefinementListProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; classNames?: Partial; translations: RefinementListTranslations; }; @@ -91,6 +92,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, className, classNames = {}, translations, @@ -190,6 +192,7 @@ export function RefinementList({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx index bee8841819..0749ba5932 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx @@ -2,6 +2,7 @@ import React from 'react'; type ShowMoreButtonProps = React.ComponentProps<'button'> & { isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -10,6 +11,10 @@ export type ShowMoreButtonTextOptions = { * Whether the widget is showing more items or not. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; }; export type ShowMoreButtonTranslations = { @@ -21,12 +26,13 @@ export type ShowMoreButtonTranslations = { export function ShowMoreButton({ isShowingMore, + showMoreCount, translations, ...props }: ShowMoreButtonProps) { return ( ); } diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx index 9f72a172ed..3a5644afea 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useRefinementList.test.tsx @@ -39,6 +39,7 @@ describe('useRefinementList', () => { hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), From bd859464e6e6ab538c6fe2bb09c83faa260da1e5 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 14:07:06 -0700 Subject: [PATCH 25/36] feat(refinementList): Applied change to hierarchicalMenu & menu --- .../connectHierarchicalMenu.ts | 21 ++++++++++++++++--- .../src/connectors/menu/connectMenu.ts | 19 +++++++++++++++-- .../hierarchical-menu/hierarchical-menu.tsx | 6 ++++-- .../src/widgets/menu/menu.tsx | 8 +++---- .../refinement-list/refinement-list.tsx | 4 ++-- .../src/ui/HierarchicalMenu.tsx | 3 +++ .../src/ui/Menu.tsx | 3 +++ .../src/widgets/HierarchicalMenu.tsx | 3 +++ .../src/widgets/Menu.tsx | 3 +++ .../src/widgets/RefinementList.tsx | 3 +++ 10 files changed, 60 insertions(+), 13 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index 68cdabc1c0..a8d8784e8a 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -113,6 +113,10 @@ export type HierarchicalMenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMoreLimit`. */ @@ -222,6 +226,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = let _refine: HierarchicalMenuRenderState['refine'] | undefined; let isShowingMore = false; + let showMoreCount = 0; function createToggleShowMore( renderOptions: RenderOptions, @@ -347,6 +352,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(hierarchicalFacetName, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -363,9 +369,17 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = // Because this is used for making the search of facets unable or not, it is important // to be conservative here. const hasExhaustiveItems = - (state.maxValuesPerFacet || 0) > getLimit() - ? facetItems.length <= getLimit() - : facetItems.length < getLimit(); + (state.maxValuesPerFacet || 0) > currentLimit + ? facetItems.length <= currentLimit + : facetItems.length < currentLimit; + + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } canToggleShowMore = showMore && (isShowingMore || !hasExhaustiveItems); @@ -383,6 +397,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = sendEvent, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index 5eb54de735..e1068acb1d 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -96,6 +96,10 @@ export type MenuRenderState = { * True if the menu is displaying all the menu items. */ isShowingMore: boolean; + /** + * Total number of facets that can be displayed for 'show more'. + */ + showMoreCount: number; /** * Toggles the number of values displayed between `limit` and `showMore.limit`. */ @@ -182,6 +186,7 @@ const connectMenu: MenuConnector = function connectMenu( // Provide the same function to the `renderFn` so that way the user // has to only bind it once when `isFirstRendering` for instance let isShowingMore = false; + let showMoreCount = 0; let toggleShowMore = () => {}; function createToggleShowMore( renderOptions: RenderOptions, @@ -289,6 +294,7 @@ const connectMenu: MenuConnector = function connectMenu( } if (results) { + const currentLimit = getLimit(); const facetValues = results.getFacetValues(attribute, { sortBy, facetOrdering: sortBy === DEFAULT_SORT, @@ -298,12 +304,20 @@ const connectMenu: MenuConnector = function connectMenu( ? facetValues.data : []; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetItems.length + ? showMoreLimit + : facetItems.length; + showMoreCount = showMoreTotalCount - currentLimit; + } + canToggleShowMore = - showMore && (isShowingMore || facetItems.length > getLimit()); + showMore && (isShowingMore || facetItems.length > currentLimit); items = transformItems( facetItems - .slice(0, getLimit()) + .slice(0, currentLimit) .map(({ name: label, escapedValue: value, path, ...item }) => ({ ...item, label, @@ -321,6 +335,7 @@ const connectMenu: MenuConnector = function connectMenu( canRefine: items.length > 0, widgetParams, isShowingMore, + showMoreCount, toggleShowMore: cachedToggleShowMore, canToggleShowMore, }; diff --git a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx index d3d86c00d8..685cb70fe1 100644 --- a/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx +++ b/packages/instantsearch.js/src/widgets/hierarchical-menu/hierarchical-menu.tsx @@ -48,9 +48,9 @@ type HierarchicalMenuTemplates = Partial<{ cssClasses: HierarchicalMenuCSSClasses; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type HierarchicalMenuCSSClasses = Partial<{ @@ -208,6 +208,7 @@ const renderer = refine, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: HierarchicalMenuRenderState & @@ -233,6 +234,7 @@ const renderer = showMore={showMore} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/menu/menu.tsx b/packages/instantsearch.js/src/widgets/menu/menu.tsx index 51d798dafb..88dc52d26a 100644 --- a/packages/instantsearch.js/src/widgets/menu/menu.tsx +++ b/packages/instantsearch.js/src/widgets/menu/menu.tsx @@ -86,11 +86,9 @@ export type MenuTemplates = Partial<{ value: string; }>; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ - isShowingMore: boolean; - }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; }>; export type MenuComponentCSSClasses = ComponentCSSClasses; @@ -135,6 +133,7 @@ const renderer = createURL, instantSearchInstance, isShowingMore, + showMoreCount, toggleShowMore, canToggleShowMore, }: MenuRenderState & RendererOptions, @@ -164,6 +163,7 @@ const renderer = toggleRefinement={refine} toggleShowMore={toggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} canToggleShowMore={canToggleShowMore} />, containerNode diff --git a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx index 1fd4a5a467..59887aebb1 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/refinement-list.tsx @@ -143,9 +143,9 @@ export type RefinementListOwnTemplates = Partial<{ */ item: Template; /** - * Template used for the show more text, provided with `isShowingMore` data property. + * Template used for the show more text, provided with `isShowingMore`, `showMoreCount` data properties. */ - showMoreText: Template<{ isShowingMore: boolean }>; + showMoreText: Template<{ isShowingMore: boolean; showMoreCount: number }>; /** * Templates to use for search for facet values when there are no results. */ diff --git a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx index 688b1fa33e..b99775a25e 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/HierarchicalMenu.tsx @@ -78,6 +78,7 @@ export type HierarchicalMenuProps = React.ComponentProps<'div'> & canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; translations: ShowMoreButtonTranslations; }; @@ -167,6 +168,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, translations, ...props }: HierarchicalMenuProps) { @@ -201,6 +203,7 @@ export function HierarchicalMenu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx index 61b217d917..b66e499898 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/Menu.tsx @@ -14,6 +14,7 @@ export type MenuProps = React.ComponentProps<'div'> & { canToggleShowMore: boolean; onToggleShowMore: () => void; isShowingMore: boolean; + showMoreCount: number; createURL: CreateURL; onRefine: (item: MenuItem) => void; translations: MenuTranslations; @@ -71,6 +72,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore, isShowingMore, + showMoreCount, createURL, onRefine, translations, @@ -127,6 +129,7 @@ export function Menu({ disabled={!canToggleShowMore} onClick={onToggleShowMore} isShowingMore={isShowingMore} + showMoreCount={showMoreCount} translations={translations} /> )} diff --git a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx index dc7b4eab6e..f6c938f7b4 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/HierarchicalMenu.tsx @@ -15,6 +15,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -45,6 +46,7 @@ export function HierarchicalMenu({ canToggleShowMore, createURL, isShowingMore, + showMoreCount, refine, toggleShowMore, } = useHierarchicalMenu( @@ -72,6 +74,7 @@ export function HierarchicalMenu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx index b0fa3e5aa1..d2ca7b69a8 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/Menu.tsx @@ -14,6 +14,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -33,6 +34,7 @@ export function Menu({ const { canToggleShowMore, isShowingMore, + showMoreCount, items, refine, createURL, @@ -58,6 +60,7 @@ export function Menu({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText(options) { return options.isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx index 06d2a75e86..576ef6328c 100644 --- a/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx +++ b/packages/react-instantsearch-hooks-web/src/widgets/RefinementList.tsx @@ -21,6 +21,7 @@ type UiProps = Pick< | 'canToggleShowMore' | 'onToggleShowMore' | 'isShowingMore' + | 'showMoreCount' | 'translations' >; @@ -60,6 +61,7 @@ export function RefinementList({ canToggleShowMore, isFromSearch, isShowingMore, + showMoreCount, items, refine, searchForItems, @@ -145,6 +147,7 @@ export function RefinementList({ canToggleShowMore, onToggleShowMore: toggleShowMore, isShowingMore, + showMoreCount, translations: { showMoreButtonText: mergedTranslations.showMoreButtonText, }, From edd04bb257d91aee20c81f2893caf4c203a443bb Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 19 Apr 2023 17:02:00 -0700 Subject: [PATCH 26/36] feat(refinementList): updated tests --- .../__tests__/connectHierarchicalMenu-test.ts | 5 +++++ .../src/connectors/menu/__tests__/connectMenu-test.ts | 4 ++++ .../__tests__/connectRefinementList-test.ts | 8 ++++++++ .../menu/__tests__/__snapshots__/menu-test.ts.snap | 2 ++ .../src/ui/__tests__/HierarchicalMenu.test.tsx | 1 + .../src/ui/__tests__/Menu.test.tsx | 1 + .../src/ui/__tests__/RefinementList.test.tsx | 1 + .../src/connectors/__tests__/useHierarchicalMenu.test.tsx | 2 ++ .../src/connectors/__tests__/useMenu.test.tsx | 2 ++ 9 files changed, 26 insertions(+) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts index 109db9d173..bd1cc78719 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/__tests__/connectHierarchicalMenu-test.ts @@ -620,6 +620,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica attributes: ['anotherCategory', 'anotherSubCategory'], }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: () => {}, canToggleShowMore: false, }, @@ -641,6 +642,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -713,6 +715,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica sendEvent: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -751,6 +754,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); @@ -821,6 +825,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/hierarchica createURL: expect.any(Function), widgetParams: { attributes: ['category', 'subCategory'] }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }); diff --git a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts index 4a6af23a3c..c01b6c9b08 100644 --- a/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts +++ b/packages/instantsearch.js/src/connectors/menu/__tests__/connectMenu-test.ts @@ -628,6 +628,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -673,6 +674,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co createURL: expect.any(Function), widgetParams: { attribute: 'brand' }, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, }, @@ -706,6 +708,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: false, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, @@ -765,6 +768,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/menu/js/#co sendEvent: expect.any(Function), canRefine: true, isShowingMore: false, + showMoreCount: 0, toggleShowMore: expect.any(Function), canToggleShowMore: false, widgetParams: { attribute: 'brand' }, diff --git a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts index 067b47186b..23cf6e2892 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts @@ -1091,6 +1091,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1125,6 +1126,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // should be 0; canToggleShowMore: false, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1160,6 +1162,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, + showMoreCount: 1, // @todo should be 0; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1201,6 +1204,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: true, + showMoreCount: 0, // @todo should be 1; canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -2455,6 +2459,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2515,6 +2520,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [ { count: 88, @@ -2575,6 +2581,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), @@ -2618,6 +2625,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- hasExhaustiveItems: true, isFromSearch: false, isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), searchForItems: expect.any(Function), diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap index 8bf2991858..8212f5cc4a 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/__snapshots__/menu-test.ts.snap @@ -41,6 +41,7 @@ exports[`menu render renders transformed items 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], @@ -96,6 +97,7 @@ exports[`menu render snapshot 1`] = ` ], "isShowingMore": false, "showMore": undefined, + "showMoreCount": 0, "templateProps": { "templates": { "item": [Function], diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx index 42af221dd4..c40e98c8d8 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/HierarchicalMenu.test.tsx @@ -59,6 +59,7 @@ describe('HierarchicalMenu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx index 91aebaaba5..c8ee1273c2 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/Menu.test.tsx @@ -32,6 +32,7 @@ describe('Menu', () => { onToggleShowMore: jest.fn(), canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { return isShowingMore ? 'Show less' : 'Show more'; diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index 04a1dc5064..df82c89ee1 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -36,6 +36,7 @@ describe('RefinementList', () => { searchBox: null, canToggleShowMore: true, isShowingMore: false, + showMoreCount: 0, onToggleShowMore: jest.fn(), translations: { showMoreButtonText({ isShowingMore }: { isShowingMore: boolean }) { diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx index 997c6f787e..28fdabc3bd 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useHierarchicalMenu.test.tsx @@ -19,6 +19,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useHierarchicalMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), diff --git a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx index 3ab9038f05..cf37c7138a 100644 --- a/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx +++ b/packages/react-instantsearch-hooks/src/connectors/__tests__/useMenu.test.tsx @@ -19,6 +19,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), @@ -33,6 +34,7 @@ describe('useMenu', () => { canToggleShowMore: false, createURL: expect.any(Function), isShowingMore: false, + showMoreCount: 0, items: [], refine: expect.any(Function), sendEvent: expect.any(Function), From c16b4b785065cf7cf79a8ba6eec39da63f2c5ef2 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 21 Apr 2023 06:45:34 -0700 Subject: [PATCH 27/36] feat(refinementList): updated tests --- .../src/ui/__tests__/ShowMoreButton.test.tsx | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx index 539451897d..24c2d8de51 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/ShowMoreButton.test.tsx @@ -19,6 +19,7 @@ describe('ShowMoreButton', () => { const { container } = render( ); @@ -34,7 +35,11 @@ describe('ShowMoreButton', () => { test('changes the button label when is showing more', () => { const { container } = render( - + ); expect(container).toMatchInlineSnapshot(` @@ -51,6 +56,7 @@ describe('ShowMoreButton', () => { const { getByRole } = render( @@ -66,6 +72,7 @@ describe('ShowMoreButton', () => { const { container, getByRole } = render( { }, }; const { getByRole, rerender } = render( - + ); expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); rerender( - + ); expect(getByRole('button', { name: 'Display more' })).toBeInTheDocument(); }); + + test('renders show more count', () => { + const translations = { + showMoreButtonText({ + isShowingMore, + showMoreCount, + }: { + isShowingMore: boolean; + showMoreCount: number; + }) { + return isShowingMore ? 'Display less' : `Display ${showMoreCount} more`; + }, + }; + const { getByRole, rerender } = render( + + ); + + expect(getByRole('button', { name: 'Display less' })).toBeInTheDocument(); + + rerender( + + ); + + expect(getByRole('button', { name: 'Display 5 more' })).toBeInTheDocument(); + }); }); From f1282a76748e228a23b5f75ec190f291b1554d72 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 21 Apr 2023 12:44:33 -0700 Subject: [PATCH 28/36] feat(refinementList): updated storybook --- .../stories/hierarchical-menu.stories.ts | 45 +++++++++++++++++++ .../instantsearch.js/stories/menu.stories.ts | 18 ++++++++ .../stories/refinement-list.stories.ts | 18 ++++++++ 3 files changed, 81 insertions(+) diff --git a/packages/instantsearch.js/stories/hierarchical-menu.stories.ts b/packages/instantsearch.js/stories/hierarchical-menu.stories.ts index d2effddfeb..80cd99c3c4 100644 --- a/packages/instantsearch.js/stories/hierarchical-menu.stories.ts +++ b/packages/instantsearch.js/stories/hierarchical-menu.stories.ts @@ -134,6 +134,51 @@ storiesOf('Refinements/HierarchicalMenu', module) ]); }) ) + .add( + 'with show more and templates', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.hierarchicalMenu({ + container, + attributes: [ + 'hierarchicalCategories.lvl0', + 'hierarchicalCategories.lvl1', + 'hierarchicalCategories.lvl2', + 'hierarchicalCategories.lvl3', + ], + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText: ({ isShowingMore }) => (isShowingMore ? '⬆️' : '⬇️'), + }, + }), + ]); + }) + ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.hierarchicalMenu({ + container, + attributes: [ + 'hierarchicalCategories.lvl0', + 'hierarchicalCategories.lvl1', + 'hierarchicalCategories.lvl2', + 'hierarchicalCategories.lvl3', + ], + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with transformed items', withHits(({ search, container, instantsearch }) => { diff --git a/packages/instantsearch.js/stories/menu.stories.ts b/packages/instantsearch.js/stories/menu.stories.ts index af6761ec5b..d0b9490bc7 100644 --- a/packages/instantsearch.js/stories/menu.stories.ts +++ b/packages/instantsearch.js/stories/menu.stories.ts @@ -74,6 +74,24 @@ storiesOf('Refinements/Menu', module) ]); }) ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.menu({ + container, + attribute: 'categories', + limit: 3, + showMore: true, + showMoreLimit: 10, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with add/remove', withHits(({ search, container, instantsearch }) => { diff --git a/packages/instantsearch.js/stories/refinement-list.stories.ts b/packages/instantsearch.js/stories/refinement-list.stories.ts index fbf8fd1652..f5e6b1cb97 100644 --- a/packages/instantsearch.js/stories/refinement-list.stories.ts +++ b/packages/instantsearch.js/stories/refinement-list.stories.ts @@ -45,6 +45,24 @@ storiesOf('Refinements/RefinementList', module) ]); }) ) + .add( + 'with show more templates and showMoreCount', + withHits(({ search, container, instantsearch }) => { + search.addWidgets([ + instantsearch.widgets.refinementList({ + container, + attribute: 'brand', + limit: 3, + showMore: true, + showMoreLimit: 10, + templates: { + showMoreText: ({ isShowingMore, showMoreCount }) => + isShowingMore ? 'Show less' : `Show ${showMoreCount} more`, + }, + }), + ]); + }) + ) .add( 'with search inside items', withHits(({ search, container, instantsearch }) => { From 3bc5eea0d55efd8260cdf85c6e3f6a890f50bcce Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Thu, 25 Jan 2024 15:55:23 -0800 Subject: [PATCH 29/36] merge conflict from rebase --- .../src/connectors/refinement-list/connectRefinementList.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index e80a03bb40..fa95bb78df 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -422,6 +422,10 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; + if (facetValues.length > 0 && facetValues.length > currentLimit) { + showMoreCount = Object.keys(facetValues).length - currentLimit; + } + if (showMore) { const showMoreTotalCount = showMoreLimit < facetValues.length From 92977bedf0e384298c2f95a30ef8eaae950b4aa2 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Mon, 17 Apr 2023 14:14:01 -0700 Subject: [PATCH 30/36] feat(refinementList): updated count check --- .../connectors/refinement-list/connectRefinementList.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index fa95bb78df..76134348af 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -422,8 +422,12 @@ const connectRefinementList: RefinementListConnector = lastResultsFromMainSearch = results; lastItemsFromMainSearch = items; - if (facetValues.length > 0 && facetValues.length > currentLimit) { - showMoreCount = Object.keys(facetValues).length - currentLimit; + if (showMore) { + const showMoreTotalCount = + showMoreLimit < facetValues.length + ? showMoreLimit + : facetValues.length; + showMoreCount = showMoreTotalCount - currentLimit; } if (showMore) { From 188f752c88356e4938908afc6d316a82e1ed4bd2 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 5 May 2023 20:44:55 -0700 Subject: [PATCH 31/36] feat(refinementList): added new tests --- .../__tests__/connectRefinementList-test.ts | 8 +- .../__tests__/refinement-list.test.tsx | 222 ++++++++++++++++++ .../src/ui/__tests__/RefinementList.test.tsx | 30 +++ 3 files changed, 256 insertions(+), 4 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts index 23cf6e2892..e8082f7721 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/__tests__/connectRefinementList-test.ts @@ -1091,7 +1091,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // @todo should be 0; + showMoreCount: 1, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1126,7 +1126,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // should be 0; + showMoreCount: 1, canToggleShowMore: false, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1162,7 +1162,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: false, - showMoreCount: 1, // @todo should be 0; + showMoreCount: 1, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, @@ -1204,7 +1204,7 @@ See documentation: https://www.algolia.com/doc/api-reference/widgets/refinement- showMoreLimit: 2, }, isShowingMore: true, - showMoreCount: 0, // @todo should be 1; + showMoreCount: 0, canToggleShowMore: true, toggleShowMore: expect.any(Function), hasExhaustiveItems: false, diff --git a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx index 6790d1e0a6..64d5aabe1c 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx @@ -851,6 +851,224 @@ describe('refinementList', () => { `); }); + test('renders with templates show more count', async () => { + const container = document.createElement('div'); + const searchClient = createMockedSearchClient(); + + const search = instantsearch({ + indexName: 'indexName', + searchClient, + initialUiState: { + indexName: { + refinementList: { + brand: ['Apple'], + }, + }, + }, + }); + + search.addWidgets([ + refinementList({ + container, + attribute: 'brand', + showMore: true, + searchable: true, + limit: 2, + showMoreLimit: 4, + templates: { + showMoreText({ isShowingMore, showMoreCount }) { + return isShowingMore + ? `Show top 2 items` + : `Show ${showMoreCount} more`; + }, + }, + }), + ]); + + search.start(); + + await wait(0); + + expect(container).toMatchInlineSnapshot(` +
+
+ +
    +
  • +
    + +
    +
  • +
  • +
    + +
    +
  • +
+ +
+
+`); + + const showMoreButton = container.querySelector( + '.ais-RefinementList-showMore' + )!; + + fireEvent.click(showMoreButton); + + expect(showMoreButton).toHaveTextContent('Show top 2 items'); + }); + function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { @@ -863,6 +1081,10 @@ describe('refinementList', () => { Apple: 746, Samsung: 633, Metra: 591, + Motorola: 434, + OtterBox: 143, + Speck: 114, + Platinum: 76, }, }, }) diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index df82c89ee1..df46d8efd7 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -682,4 +682,34 @@ describe('RefinementList', () => { getByRole('button', { name: 'Show less brands' }) ).toBeInTheDocument(); }); + + test('renders with translations show more count', () => { + const props = createProps({ + showMore: true, + translations: { + showMoreButtonText({ + isShowingMore, + showMoreCount, + }: { + isShowingMore: boolean; + showMoreCount: number; + }) { + return isShowingMore + ? `Show top 5 items` + : `Show ${showMoreCount} more`; + }, + }, + }); + const { getByRole, rerender } = render( + + ); + + expect(getByRole('button', { name: 'Show 5 more' })).toBeInTheDocument(); + + rerender(); + + expect( + getByRole('button', { name: 'Show top 5 items' }) + ).toBeInTheDocument(); + }); }); From 493912f60eee95db6bd653650844f917eb35e87b Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Fri, 5 May 2023 21:18:31 -0700 Subject: [PATCH 32/36] feat(refinementList): added new tests --- .../src/widgets/menu/__tests__/menu.test.tsx | 138 ++++++++++++++++++ .../__tests__/refinement-list.test.tsx | 25 +++- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx index 97a8137457..611eaa40f2 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx @@ -397,6 +397,144 @@ describe('menu', () => { `); }); + test('renders with templates show more count', async () => { + const container = document.createElement('div'); + const searchClient = createMockedSearchClient(); + + const search = instantsearch({ + indexName: 'indexName', + searchClient, + initialUiState: { + indexName: { + menu: { + brand: 'Apple', + }, + }, + }, + }); + + search.addWidgets([ + menu({ + container, + attribute: 'brand', + limit: 3, + showMore: true, + showMoreLimit: 6, + templates: { + showMoreText({ isShowingMore, showMoreCount }) { + return isShowingMore + ? `Show top 3 items` + : `Show ${showMoreCount} more`; + }, + }, + }), + ]); + + // @MAJOR Once Hogan.js and string-based templates are removed, + // `search.start()` can be moved to the test body and the following + // assertion can go away. + expect(async () => { + search.start(); + + await wait(0); + }).not.toWarnDev(); + + await wait(0); + + expect(container).toMatchInlineSnapshot(` +
+
+ + +
+
+`); + + const toggleButton = within(container).getByRole('button'); + + fireEvent.click(toggleButton); + + expect(toggleButton).toMatchInlineSnapshot(` + +`); + }); + function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { diff --git a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx index 64d5aabe1c..709b8d8d99 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx @@ -874,7 +874,7 @@ describe('refinementList', () => { showMore: true, searchable: true, limit: 2, - showMoreLimit: 4, + showMoreLimit: 6, templates: { showMoreText({ isShowingMore, showMoreCount }) { return isShowingMore @@ -1054,7 +1054,7 @@ describe('refinementList', () => { @@ -1081,10 +1081,23 @@ describe('refinementList', () => { Apple: 746, Samsung: 633, Metra: 591, - Motorola: 434, - OtterBox: 143, - Speck: 114, - Platinum: 76, + HP: 530, + 'Insignia™': 442, + GE: 394, + Sony: 350, + Incipio: 320, + KitchenAid: 318, + Whirlpool: 298, + LG: 291, + Canon: 287, + Frigidaire: 275, + Speck: 216, + OtterBox: 214, + Epson: 204, + 'Dynex™': 184, + Dell: 174, + 'Hamilton Beach': 173, + Platinum: 155, }, }, }) From 4875312cf5c2ca3dcbfc0bcb49f84414fe47062e Mon Sep 17 00:00:00 2001 From: Mike Davis <77642365+mikedavis77@users.noreply.github.com> Date: Wed, 17 May 2023 14:59:38 -0700 Subject: [PATCH 33/36] Apply suggestions from code review Co-authored-by: Dhaya <154633+dhayab@users.noreply.github.com> --- .../hierarchical-menu/connectHierarchicalMenu.ts | 7 ++----- .../instantsearch.js/src/connectors/menu/connectMenu.ts | 7 ++----- .../connectors/refinement-list/connectRefinementList.ts | 7 ++----- .../src/ui/ShowMoreButton.tsx | 2 +- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index a8d8784e8a..df4fcb9d71 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -114,7 +114,7 @@ export type HierarchicalMenuRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -374,10 +374,7 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = : facetItems.length < currentLimit; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetItems.length - ? showMoreLimit - : facetItems.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index e1068acb1d..483ae436be 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -97,7 +97,7 @@ export type MenuRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -305,10 +305,7 @@ const connectMenu: MenuConnector = function connectMenu( : []; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetItems.length - ? showMoreLimit - : facetItems.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index 76134348af..dbf20c23b0 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -137,7 +137,7 @@ export type RefinementListRenderState = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; /** @@ -423,10 +423,7 @@ const connectRefinementList: RefinementListConnector = lastItemsFromMainSearch = items; if (showMore) { - const showMoreTotalCount = - showMoreLimit < facetValues.length - ? showMoreLimit - : facetValues.length; + const showMoreTotalCount = Math.min(showMoreLimit, facetValues.length); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx index 0749ba5932..b194a6095b 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/ShowMoreButton.tsx @@ -12,7 +12,7 @@ export type ShowMoreButtonTextOptions = { */ isShowingMore: boolean; /** - * Total number of facets that can be displayed for 'show more'. + * Total number of facet values that can be displayed for 'show more'. */ showMoreCount: number; }; From 50c41fba97c03c023d64236569ac662d51ac0794 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 17 May 2023 15:55:48 -0700 Subject: [PATCH 34/36] fix lint errors --- .../connectors/hierarchical-menu/connectHierarchicalMenu.ts | 5 ++++- packages/instantsearch.js/src/connectors/menu/connectMenu.ts | 5 ++++- .../src/connectors/refinement-list/connectRefinementList.ts | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts index df4fcb9d71..c1333def5e 100644 --- a/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts +++ b/packages/instantsearch.js/src/connectors/hierarchical-menu/connectHierarchicalMenu.ts @@ -374,7 +374,10 @@ const connectHierarchicalMenu: HierarchicalMenuConnector = : facetItems.length < currentLimit; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetItems.length + ); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts index 483ae436be..f2773e7f4c 100644 --- a/packages/instantsearch.js/src/connectors/menu/connectMenu.ts +++ b/packages/instantsearch.js/src/connectors/menu/connectMenu.ts @@ -305,7 +305,10 @@ const connectMenu: MenuConnector = function connectMenu( : []; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetItems.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetItems.length + ); showMoreCount = showMoreTotalCount - currentLimit; } diff --git a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts index dbf20c23b0..cda6f2280e 100644 --- a/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts +++ b/packages/instantsearch.js/src/connectors/refinement-list/connectRefinementList.ts @@ -423,7 +423,10 @@ const connectRefinementList: RefinementListConnector = lastItemsFromMainSearch = items; if (showMore) { - const showMoreTotalCount = Math.min(showMoreLimit, facetValues.length); + const showMoreTotalCount = Math.min( + showMoreLimit, + facetValues.length + ); showMoreCount = showMoreTotalCount - currentLimit; } From b00aa8b09f60b10d79e3d3746f5d8dc3df6f31c6 Mon Sep 17 00:00:00 2001 From: Mike Davis Date: Wed, 17 May 2023 16:06:04 -0700 Subject: [PATCH 35/36] updated Vue package with showMoreCount --- .../vue-instantsearch/src/components/HierarchicalMenu.vue | 7 ++++++- packages/vue-instantsearch/src/components/Menu.vue | 7 ++++++- .../vue-instantsearch/src/components/RefinementList.vue | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/vue-instantsearch/src/components/HierarchicalMenu.vue b/packages/vue-instantsearch/src/components/HierarchicalMenu.vue index 0aefe0f765..31362b5515 100644 --- a/packages/vue-instantsearch/src/components/HierarchicalMenu.vue +++ b/packages/vue-instantsearch/src/components/HierarchicalMenu.vue @@ -8,6 +8,7 @@ :can-refine="state.canRefine" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :refine="state.refine" :createURL="state.createURL" :toggle-show-more="state.toggleShowMore" @@ -30,7 +31,11 @@ :disabled="!state.canToggleShowMore" @click.prevent="state.toggleShowMore" > - + {{ state.isShowingMore ? 'Show less' : 'Show more' }} diff --git a/packages/vue-instantsearch/src/components/Menu.vue b/packages/vue-instantsearch/src/components/Menu.vue index 30f07bb5e7..834a7991b8 100644 --- a/packages/vue-instantsearch/src/components/Menu.vue +++ b/packages/vue-instantsearch/src/components/Menu.vue @@ -8,6 +8,7 @@ :can-refine="state.canRefine" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :refine="state.refine" :createURL="state.createURL" :toggle-show-more="state.toggleShowMore" @@ -39,7 +40,11 @@ :disabled="!state.canToggleShowMore" @click.prevent="state.toggleShowMore()" > - + {{ state.isShowingMore ? 'Show less' : 'Show more' }} diff --git a/packages/vue-instantsearch/src/components/RefinementList.vue b/packages/vue-instantsearch/src/components/RefinementList.vue index e3c880e57d..df7b895fe5 100644 --- a/packages/vue-instantsearch/src/components/RefinementList.vue +++ b/packages/vue-instantsearch/src/components/RefinementList.vue @@ -11,6 +11,7 @@ :toggle-show-more="toggleShowMore" :can-toggle-show-more="state.canToggleShowMore" :is-showing-more="state.isShowingMore" + :show-more-count="state.showMoreCount" :createURL="state.createURL" :is-from-search="state.isFromSearch" :can-refine="state.canRefine" @@ -70,7 +71,11 @@ v-if="showMore" :disabled="!state.canToggleShowMore" > - + Show {{ state.isShowingMore ? 'less' : 'more' }} From 825f8be550613f644de4d31e1a6d8fa20a6a4230 Mon Sep 17 00:00:00 2001 From: Dhaya <154633+dhayab@users.noreply.github.com> Date: Fri, 26 Jan 2024 01:01:50 +0100 Subject: [PATCH 36/36] refactoring: move show more count tests to common suite (#5638) * refactoring: move show more count tests to common suite * map flavor specific props during setup --- .../src/widgets/menu/__tests__/menu.test.tsx | 138 ---------- .../__tests__/refinement-list.test.tsx | 235 ------------------ .../src/__tests__/common.test.tsx | 48 +++- .../src/ui/__tests__/RefinementList.test.tsx | 30 --- .../src/__tests__/common.test.js | 52 +++- .../common/widgets/hierarchical-menu/index.ts | 3 + .../widgets/hierarchical-menu/show-more.ts | 87 +++++++ tests/common/widgets/menu/index.ts | 3 + tests/common/widgets/menu/show-more.ts | 87 +++++++ tests/common/widgets/refinement-list/index.ts | 3 + .../widgets/refinement-list/show-more.ts | 87 +++++++ 11 files changed, 364 insertions(+), 409 deletions(-) create mode 100644 tests/common/widgets/hierarchical-menu/show-more.ts create mode 100644 tests/common/widgets/menu/show-more.ts create mode 100644 tests/common/widgets/refinement-list/show-more.ts diff --git a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx index 611eaa40f2..97a8137457 100644 --- a/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx +++ b/packages/instantsearch.js/src/widgets/menu/__tests__/menu.test.tsx @@ -397,144 +397,6 @@ describe('menu', () => { `); }); - test('renders with templates show more count', async () => { - const container = document.createElement('div'); - const searchClient = createMockedSearchClient(); - - const search = instantsearch({ - indexName: 'indexName', - searchClient, - initialUiState: { - indexName: { - menu: { - brand: 'Apple', - }, - }, - }, - }); - - search.addWidgets([ - menu({ - container, - attribute: 'brand', - limit: 3, - showMore: true, - showMoreLimit: 6, - templates: { - showMoreText({ isShowingMore, showMoreCount }) { - return isShowingMore - ? `Show top 3 items` - : `Show ${showMoreCount} more`; - }, - }, - }), - ]); - - // @MAJOR Once Hogan.js and string-based templates are removed, - // `search.start()` can be moved to the test body and the following - // assertion can go away. - expect(async () => { - search.start(); - - await wait(0); - }).not.toWarnDev(); - - await wait(0); - - expect(container).toMatchInlineSnapshot(` -
-
- - -
-
-`); - - const toggleButton = within(container).getByRole('button'); - - fireEvent.click(toggleButton); - - expect(toggleButton).toMatchInlineSnapshot(` - -`); - }); - function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { diff --git a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx index 709b8d8d99..6790d1e0a6 100644 --- a/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx +++ b/packages/instantsearch.js/src/widgets/refinement-list/__tests__/refinement-list.test.tsx @@ -851,224 +851,6 @@ describe('refinementList', () => { `); }); - test('renders with templates show more count', async () => { - const container = document.createElement('div'); - const searchClient = createMockedSearchClient(); - - const search = instantsearch({ - indexName: 'indexName', - searchClient, - initialUiState: { - indexName: { - refinementList: { - brand: ['Apple'], - }, - }, - }, - }); - - search.addWidgets([ - refinementList({ - container, - attribute: 'brand', - showMore: true, - searchable: true, - limit: 2, - showMoreLimit: 6, - templates: { - showMoreText({ isShowingMore, showMoreCount }) { - return isShowingMore - ? `Show top 2 items` - : `Show ${showMoreCount} more`; - }, - }, - }), - ]); - - search.start(); - - await wait(0); - - expect(container).toMatchInlineSnapshot(` -
-
- -
    -
  • -
    - -
    -
  • -
  • -
    - -
    -
  • -
- -
-
-`); - - const showMoreButton = container.querySelector( - '.ais-RefinementList-showMore' - )!; - - fireEvent.click(showMoreButton); - - expect(showMoreButton).toHaveTextContent('Show top 2 items'); - }); - function createMockedSearchClient() { return createSearchClient({ search: jest.fn((requests) => { @@ -1081,23 +863,6 @@ describe('refinementList', () => { Apple: 746, Samsung: 633, Metra: 591, - HP: 530, - 'Insignia™': 442, - GE: 394, - Sony: 350, - Incipio: 320, - KitchenAid: 318, - Whirlpool: 298, - LG: 291, - Canon: 287, - Frigidaire: 275, - Speck: 216, - OtterBox: 214, - Epson: 204, - 'Dynex™': 184, - Dell: 174, - 'Hamilton Beach': 173, - Platinum: 155, }, }, }) diff --git a/packages/react-instantsearch-hooks-web/src/__tests__/common.test.tsx b/packages/react-instantsearch-hooks-web/src/__tests__/common.test.tsx index e092b7da3b..593014e5db 100644 --- a/packages/react-instantsearch-hooks-web/src/__tests__/common.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/__tests__/common.test.tsx @@ -33,6 +33,27 @@ import { import type { Hit } from 'instantsearch.js'; import type { SendEventForHits } from 'instantsearch.js/es/lib/utils'; +/** + * Converts InstantSearch.js templates into React InstantSearch Hooks translations. + * @param templates InstantSearch.js templates received in `widgetParams` + * @param map Matching between template keys and translation keys + */ +function fromTemplates( + templates: Record, + map: Record +) { + return Object.entries(map).reduce>( + (translations, [templateKey, translationKey]) => { + if (templates[templateKey] !== undefined) { + translations[translationKey] = templates[templateKey]; + } + + return translations; + }, + {} + ); +} + /** * prevent rethrowing InstantSearch errors, so tests can be asserted. * IRL this isn't needed, as the error doesn't stop execution. @@ -44,18 +65,32 @@ function GlobalErrorSwallower() { } createRefinementListTests(({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const translations = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreButtonText', + }); + render( - + ); }, act); createHierarchicalMenuTests(({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const translations = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreButtonText', + }); + render( - + ); @@ -73,9 +108,16 @@ createBreadcrumbTests(({ instantSearchOptions, widgetParams }) => { }, act); createMenuTests(({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const translations = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreButtonText', + }); + render( - + ); diff --git a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx index df46d8efd7..df82c89ee1 100644 --- a/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx +++ b/packages/react-instantsearch-hooks-web/src/ui/__tests__/RefinementList.test.tsx @@ -682,34 +682,4 @@ describe('RefinementList', () => { getByRole('button', { name: 'Show less brands' }) ).toBeInTheDocument(); }); - - test('renders with translations show more count', () => { - const props = createProps({ - showMore: true, - translations: { - showMoreButtonText({ - isShowingMore, - showMoreCount, - }: { - isShowingMore: boolean; - showMoreCount: number; - }) { - return isShowingMore - ? `Show top 5 items` - : `Show ${showMoreCount} more`; - }, - }, - }); - const { getByRole, rerender } = render( - - ); - - expect(getByRole('button', { name: 'Show 5 more' })).toBeInTheDocument(); - - rerender(); - - expect( - getByRole('button', { name: 'Show top 5 items' }) - ).toBeInTheDocument(); - }); }); diff --git a/packages/vue-instantsearch/src/__tests__/common.test.js b/packages/vue-instantsearch/src/__tests__/common.test.js index d6cca7b91b..c9317481c3 100644 --- a/packages/vue-instantsearch/src/__tests__/common.test.js +++ b/packages/vue-instantsearch/src/__tests__/common.test.js @@ -31,6 +31,25 @@ import { } from '../instantsearch'; jest.unmock('instantsearch.js/es'); +/** + * Converts InstantSearch.js templates into Vue InstantSearch slots. + * @param {Record} templates InstantSearch.js templates received in `widgetParams` + * @param {Record} map Matching between template keys and slots names + * @returns {Record} Vue InstantSearch slots + */ +function fromTemplates(templates, map) { + return Object.entries(map).reduce( + (translations, [templateKey, translationKey]) => { + if (templates[templateKey] !== undefined) { + return { ...translations, [translationKey]: templates[templateKey] }; + } + + return translations; + }, + {} + ); +} + /** * prevent rethrowing InstantSearch errors, so tests can be asserted. * IRL this isn't needed, as the error doesn't stop execution. @@ -46,11 +65,21 @@ const GlobalErrorSwallower = { }; createRefinementListTests(async ({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const scopedSlots = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreLabel', + }); + mountApp( { render: renderCompat((h) => h(AisInstantSearch, { props: instantSearchOptions }, [ - h(AisRefinementList, { props: widgetParams }), + h(AisRefinementList, { + props, + scopedSlots, + }), h(GlobalErrorSwallower), ]) ), @@ -62,11 +91,21 @@ createRefinementListTests(async ({ instantSearchOptions, widgetParams }) => { }); createHierarchicalMenuTests(async ({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const scopedSlots = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreLabel', + }); + mountApp( { render: renderCompat((h) => h(AisInstantSearch, { props: instantSearchOptions }, [ - h(AisHierarchicalMenu, { props: widgetParams }), + h(AisHierarchicalMenu, { + props, + scopedSlots, + }), h(GlobalErrorSwallower), ]) ), @@ -100,11 +139,18 @@ createBreadcrumbTests(async ({ instantSearchOptions, widgetParams }) => { }); createMenuTests(async ({ instantSearchOptions, widgetParams }) => { + const { templates, ...props } = widgetParams; + const scopedSlots = + templates && + fromTemplates(templates, { + showMoreText: 'showMoreLabel', + }); + mountApp( { render: renderCompat((h) => h(AisInstantSearch, { props: instantSearchOptions }, [ - h(AisMenu, { props: widgetParams }), + h(AisMenu, { props, scopedSlots }), h(GlobalErrorSwallower), ]) ), diff --git a/tests/common/widgets/hierarchical-menu/index.ts b/tests/common/widgets/hierarchical-menu/index.ts index b8f34e5db6..e96dc1de06 100644 --- a/tests/common/widgets/hierarchical-menu/index.ts +++ b/tests/common/widgets/hierarchical-menu/index.ts @@ -2,10 +2,12 @@ import type { HierarchicalMenuWidget } from 'instantsearch.js/es/widgets/hierarc import type { Act, TestSetup } from '../../common'; import { fakeAct } from '../../common'; import { createOptimisticUiTests } from './optimistic-ui'; +import { createShowMoreTests } from './show-more'; type WidgetParams = Parameters[0]; export type HierarchicalMenuSetup = TestSetup<{ widgetParams: Omit; + vueSlots?: Record; }>; export function createHierarchicalMenuTests( @@ -18,5 +20,6 @@ export function createHierarchicalMenuTests( describe('HierarchicalMenu common tests', () => { createOptimisticUiTests(setup, act); + createShowMoreTests(setup, act); }); } diff --git a/tests/common/widgets/hierarchical-menu/show-more.ts b/tests/common/widgets/hierarchical-menu/show-more.ts new file mode 100644 index 0000000000..b9f9dbcb38 --- /dev/null +++ b/tests/common/widgets/hierarchical-menu/show-more.ts @@ -0,0 +1,87 @@ +import { wait } from '@instantsearch/testutils'; +import { + createMultiSearchResponse, + createSearchClient, + createSingleSearchResponse, +} from '@instantsearch/mocks'; + +import type { HierarchicalMenuSetup } from '.'; +import type { Act } from '../../common'; + +export function createShowMoreTests(setup: HierarchicalMenuSetup, act: Act) { + describe('show more', () => { + test('receives a count of facet values', async () => { + const delay = 100; + const margin = 10; + const attributes = ['brand']; + const limit = 2; + const showMoreLimit = 6; + + const options = { + instantSearchOptions: { + indexName: 'indexName', + searchClient: createSearchClient({ + search: jest.fn(async (requests) => { + await wait(delay); + return createMultiSearchResponse( + ...requests.map(() => + createSingleSearchResponse({ + facets: { + [attributes[0]]: { + Apple: 746, + Samsung: 633, + Metra: 591, + HP: 530, + 'Insignia™': 442, + GE: 394, + Sony: 350, + Incipio: 320, + KitchenAid: 318, + Whirlpool: 298, + LG: 291, + Canon: 287, + Frigidaire: 275, + Speck: 216, + OtterBox: 214, + Epson: 204, + 'Dynex™': 184, + Dell: 174, + 'Hamilton Beach': 173, + Platinum: 155, + }, + }, + }) + ) + ); + }), + }), + }, + widgetParams: { + attributes, + limit, + showMoreLimit, + showMore: true, + templates: { + // @ts-ignore + showMoreText({ isShowingMore, showMoreCount }) { + return !isShowingMore + ? `Show ${showMoreCount} more` + : 'Show top items'; + }, + }, + }, + }; + + await setup(options); + + await act(async () => { + await wait(margin + delay); + await wait(0); + }); + + expect( + document.querySelector('.ais-HierarchicalMenu-showMore') + ).toHaveTextContent(`Show ${showMoreLimit - limit} more`); + }); + }); +} diff --git a/tests/common/widgets/menu/index.ts b/tests/common/widgets/menu/index.ts index 3df854b115..4f86452de4 100644 --- a/tests/common/widgets/menu/index.ts +++ b/tests/common/widgets/menu/index.ts @@ -2,10 +2,12 @@ import type { MenuWidget } from 'instantsearch.js/es/widgets/menu/menu'; import type { Act, TestSetup } from '../../common'; import { fakeAct } from '../../common'; import { createOptimisticUiTests } from './optimistic-ui'; +import { createShowMoreTests } from './show-more'; type WidgetParams = Parameters[0]; export type MenuSetup = TestSetup<{ widgetParams: Omit; + vueSlots?: Record; }>; export function createMenuTests(setup: MenuSetup, act: Act = fakeAct) { @@ -15,5 +17,6 @@ export function createMenuTests(setup: MenuSetup, act: Act = fakeAct) { describe('Menu common tests', () => { createOptimisticUiTests(setup, act); + createShowMoreTests(setup, act); }); } diff --git a/tests/common/widgets/menu/show-more.ts b/tests/common/widgets/menu/show-more.ts new file mode 100644 index 0000000000..e4ebf8aecf --- /dev/null +++ b/tests/common/widgets/menu/show-more.ts @@ -0,0 +1,87 @@ +import { wait } from '@instantsearch/testutils'; +import { + createMultiSearchResponse, + createSearchClient, + createSingleSearchResponse, +} from '@instantsearch/mocks'; + +import type { MenuSetup } from '.'; +import type { Act } from '../../common'; + +export function createShowMoreTests(setup: MenuSetup, act: Act) { + describe('show more', () => { + test('receives a count of facet values', async () => { + const delay = 100; + const margin = 10; + const attribute = 'brand'; + const limit = 2; + const showMoreLimit = 6; + + const options = { + instantSearchOptions: { + indexName: 'indexName', + searchClient: createSearchClient({ + search: jest.fn(async (requests) => { + await wait(delay); + return createMultiSearchResponse( + ...requests.map(() => + createSingleSearchResponse({ + facets: { + [attribute]: { + Apple: 746, + Samsung: 633, + Metra: 591, + HP: 530, + 'Insignia™': 442, + GE: 394, + Sony: 350, + Incipio: 320, + KitchenAid: 318, + Whirlpool: 298, + LG: 291, + Canon: 287, + Frigidaire: 275, + Speck: 216, + OtterBox: 214, + Epson: 204, + 'Dynex™': 184, + Dell: 174, + 'Hamilton Beach': 173, + Platinum: 155, + }, + }, + }) + ) + ); + }), + }), + }, + widgetParams: { + attribute, + limit, + showMoreLimit, + showMore: true, + templates: { + // @ts-ignore + showMoreText({ isShowingMore, showMoreCount }) { + return !isShowingMore + ? `Show ${showMoreCount} more` + : 'Show top items'; + }, + }, + }, + }; + + await setup(options); + + await act(async () => { + await wait(margin + delay); + await wait(0); + }); + + expect(document.querySelector('.ais-Menu-showMore')).toHaveTextContent( + `Show ${showMoreLimit - limit} more` + ); + }); + }); +} diff --git a/tests/common/widgets/refinement-list/index.ts b/tests/common/widgets/refinement-list/index.ts index ad807fbced..75399dd771 100644 --- a/tests/common/widgets/refinement-list/index.ts +++ b/tests/common/widgets/refinement-list/index.ts @@ -2,10 +2,12 @@ import type { RefinementListWidget } from 'instantsearch.js/es/widgets/refinemen import type { TestSetup, Act } from '../../common'; import { fakeAct } from '../../common'; import { createOptimisticUiTests } from './optimistic-ui'; +import { createShowMoreTests } from './show-more'; type WidgetParams = Parameters[0]; export type RefinementListSetup = TestSetup<{ widgetParams: Omit; + vueSlots?: Record; }>; export function createRefinementListTests( @@ -18,5 +20,6 @@ export function createRefinementListTests( describe('RefinementList common tests', () => { createOptimisticUiTests(setup, act); + createShowMoreTests(setup, act); }); } diff --git a/tests/common/widgets/refinement-list/show-more.ts b/tests/common/widgets/refinement-list/show-more.ts new file mode 100644 index 0000000000..5c2e3b7683 --- /dev/null +++ b/tests/common/widgets/refinement-list/show-more.ts @@ -0,0 +1,87 @@ +import { wait } from '@instantsearch/testutils'; +import { + createMultiSearchResponse, + createSearchClient, + createSingleSearchResponse, +} from '@instantsearch/mocks'; + +import type { RefinementListSetup } from '.'; +import type { Act } from '../../common'; + +export function createShowMoreTests(setup: RefinementListSetup, act: Act) { + describe('show more', () => { + test('receives a count of facet values', async () => { + const delay = 100; + const margin = 10; + const attribute = 'brand'; + const limit = 2; + const showMoreLimit = 6; + + const options = { + instantSearchOptions: { + indexName: 'indexName', + searchClient: createSearchClient({ + search: jest.fn(async (requests) => { + await wait(delay); + return createMultiSearchResponse( + ...requests.map(() => + createSingleSearchResponse({ + facets: { + [attribute]: { + Apple: 746, + Samsung: 633, + Metra: 591, + HP: 530, + 'Insignia™': 442, + GE: 394, + Sony: 350, + Incipio: 320, + KitchenAid: 318, + Whirlpool: 298, + LG: 291, + Canon: 287, + Frigidaire: 275, + Speck: 216, + OtterBox: 214, + Epson: 204, + 'Dynex™': 184, + Dell: 174, + 'Hamilton Beach': 173, + Platinum: 155, + }, + }, + }) + ) + ); + }), + }), + }, + widgetParams: { + attribute, + limit, + showMoreLimit, + showMore: true, + templates: { + // @ts-ignore + showMoreText({ isShowingMore, showMoreCount }) { + return !isShowingMore + ? `Show ${showMoreCount} more` + : 'Show top items'; + }, + }, + }, + }; + + await setup(options); + + await act(async () => { + await wait(margin + delay); + await wait(0); + }); + + expect( + document.querySelector('.ais-RefinementList-showMore') + ).toHaveTextContent(`Show ${showMoreLimit - limit} more`); + }); + }); +}