diff --git a/bundlesize.config.json b/bundlesize.config.json index 52a70b56a6..e90615b149 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -10,7 +10,7 @@ }, { "path": "./packages/instantsearch.js/dist/instantsearch.production.min.js", - "maxSize": "83.75 kB" + "maxSize": "84 kB" }, { "path": "./packages/instantsearch.js/dist/instantsearch.development.js", @@ -18,7 +18,7 @@ }, { "path": "packages/react-instantsearch-core/dist/umd/ReactInstantSearchCore.min.js", - "maxSize": "51.50 kB" + "maxSize": "51.75 kB" }, { "path": "packages/react-instantsearch/dist/umd/ReactInstantSearch.min.js", @@ -26,7 +26,7 @@ }, { "path": "packages/vue-instantsearch/vue2/umd/index.js", - "maxSize": "69.00 kB" + "maxSize": "69.25 kB" }, { "path": "packages/vue-instantsearch/vue3/umd/index.js", diff --git a/packages/algoliasearch-helper/index.d.ts b/packages/algoliasearch-helper/index.d.ts index b3b2410512..4430f2fdfe 100644 --- a/packages/algoliasearch-helper/index.d.ts +++ b/packages/algoliasearch-helper/index.d.ts @@ -197,6 +197,26 @@ declare namespace algoliasearchHelper { userState?: PlainSearchParameters ): Promise; + /** + * Search for facet values using the Composition API & based on a query and the name of a faceted attribute. + * This triggers a search and will return a promise. On top of using the query, it also sends + * the parameters from the state so that the search is narrowed down to only the possible values. + * + * See the description of [FacetSearchResult](reference.html#FacetSearchResult) + * @param facet the name of the faceted attribute + * @param query the string query for the search + * @param [maxFacetHits] the maximum number values returned. Should be > 0 and <= 100 + * @param [userState] the set of custom parameters to use on top of the current state. Setting a property to `undefined` removes + * it in the generated query. + * @return the results of the search + */ + searchForCompositionFacetValues( + facet: string, + query: string, + maxFacetHits: number, + userState?: PlainSearchParameters + ): Promise; + /** * Sets the text query used for the search. * diff --git a/packages/algoliasearch-helper/src/algoliasearch.helper.js b/packages/algoliasearch-helper/src/algoliasearch.helper.js index b1aa13f677..f0496dcd67 100644 --- a/packages/algoliasearch-helper/src/algoliasearch.helper.js +++ b/packages/algoliasearch-helper/src/algoliasearch.helper.js @@ -461,6 +461,81 @@ AlgoliaSearchHelper.prototype.searchForFacetValues = function ( ); }; +/** + * Search for facet values using the Composition API & based on a query and the name of a faceted attribute. + * This triggers a search and will return a promise. On top of using the query, it also sends + * the parameters from the state so that the search is narrowed down to only the possible values. + * + * See the description of [FacetSearchResult](reference.html#FacetSearchResult) + * @param {string} facet the name of the faceted attribute + * @param {string} query the string query for the search + * @param {number} [maxFacetHits] the maximum number values returned. Should be > 0 and <= 100 + * @param {object} [userState] the set of custom parameters to use on top of the current state. Setting a property to `undefined` removes + * it in the generated query. + * @return {promise.} the results of the search + */ +AlgoliaSearchHelper.prototype.searchForCompositionFacetValues = function ( + facet, + query, + maxFacetHits, + userState +) { + if (typeof this.client.searchForFacetValues !== 'function') { + throw new Error( + 'search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues' + ); + } + + var state = this.state.setQueryParameters(userState || {}); + var isDisjunctive = state.isDisjunctiveFacet(facet); + + this._currentNbQueries++; + // eslint-disable-next-line consistent-this + var self = this; + var searchForFacetValuesPromise; + + searchForFacetValuesPromise = this.client.searchForFacetValues({ + compositionID: state.index, + facetName: facet, + searchForFacetValuesRequest: { + params: { + query: state.query, + maxFacetHits: maxFacetHits, + searchQuery: { query: query }, + }, + }, + }); + + this.emit('searchForFacetValues', { + state: state, + facet: facet, + query: query, + }); + + return searchForFacetValuesPromise.then( + function addIsRefined(content) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + + content = content.results[0]; + + content.facetHits.forEach(function (f) { + f.escapedValue = escapeFacetValue(f.value); + f.isRefined = isDisjunctive + ? state.isDisjunctiveFacetRefined(facet, f.escapedValue) + : state.isFacetRefined(facet, f.escapedValue); + }); + + return content; + }, + function (e) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + throw e; + } + ); +}; + /** * Sets the text query used for the search. * diff --git a/packages/instantsearch.js/src/lib/InstantSearch.ts b/packages/instantsearch.js/src/lib/InstantSearch.ts index 89b673f458..1eef6c5508 100644 --- a/packages/instantsearch.js/src/lib/InstantSearch.ts +++ b/packages/instantsearch.js/src/lib/InstantSearch.ts @@ -589,6 +589,11 @@ See documentation: ${createDocumentationLink({ persistHierarchicalRootCount: this.future.persistHierarchicalRootCount, }); + if (this.compositionID) { + mainHelper.searchForFacetValues = + mainHelper.searchForCompositionFacetValues.bind(mainHelper); + } + mainHelper.search = () => { this.status = 'loading'; this.scheduleRender(false);