instantsearch.js 4.66.1 → 4.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! InstantSearch.js 4.66.1 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
1
+ /*! InstantSearch.js 4.68.0 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -2666,6 +2666,7 @@
2666
2666
  });
2667
2667
  },
2668
2668
  getWidgetRenderState: function getWidgetRenderState(_ref2) {
2669
+ var _results$renderingCon, _results$renderingCon2, _results$renderingCon3;
2669
2670
  var results = _ref2.results,
2670
2671
  helper = _ref2.helper,
2671
2672
  instantSearchInstance = _ref2.instantSearchInstance;
@@ -2691,6 +2692,7 @@
2691
2692
  return {
2692
2693
  hits: [],
2693
2694
  results: undefined,
2695
+ banner: undefined,
2694
2696
  sendEvent: sendEvent,
2695
2697
  bindEvent: bindEvent,
2696
2698
  widgetParams: widgetParams
@@ -2704,9 +2706,11 @@
2704
2706
  var transformedHits = transformItems(hitsWithAbsolutePositionAndQueryID, {
2705
2707
  results: results
2706
2708
  });
2709
+ var banner = (_results$renderingCon = results.renderingContent) === null || _results$renderingCon === void 0 ? void 0 : (_results$renderingCon2 = _results$renderingCon.widgets) === null || _results$renderingCon2 === void 0 ? void 0 : (_results$renderingCon3 = _results$renderingCon2.banners) === null || _results$renderingCon3 === void 0 ? void 0 : _results$renderingCon3[0];
2707
2710
  return {
2708
2711
  hits: transformedHits,
2709
2712
  results: results,
2713
+ banner: banner,
2710
2714
  sendEvent: sendEvent,
2711
2715
  bindEvent: bindEvent,
2712
2716
  widgetParams: widgetParams
@@ -6101,12 +6105,15 @@
6101
6105
  * This event contains a {@link SearchResults} object and the
6102
6106
  * {@link SearchParameters} corresponding to this answer.
6103
6107
  * @param {AlgoliaSearchHelper} mainHelper the main helper
6104
- * @param {function} fn the function to create the derived state
6108
+ * @param {function} fn the function to create the derived state for search
6109
+ * @param {function} recommendFn the function to create the derived state for recommendations
6105
6110
  */
6106
- function DerivedHelper(mainHelper, fn) {
6111
+ function DerivedHelper(mainHelper, fn, recommendFn) {
6107
6112
  this.main = mainHelper;
6108
6113
  this.fn = fn;
6114
+ this.recommendFn = recommendFn;
6109
6115
  this.lastResults = null;
6116
+ this.lastRecommendResults = null;
6110
6117
  }
6111
6118
 
6112
6119
  inherits_1(DerivedHelper, events);
@@ -6125,6 +6132,10 @@
6125
6132
  return this.fn(parameters);
6126
6133
  };
6127
6134
 
6135
+ DerivedHelper.prototype.getModifiedRecommendState = function (parameters) {
6136
+ return this.recommendFn(parameters);
6137
+ };
6138
+
6128
6139
  var DerivedHelper_1 = DerivedHelper;
6129
6140
 
6130
6141
  /**
@@ -6285,7 +6296,18 @@
6285
6296
  constructor: RecommendParameters,
6286
6297
 
6287
6298
  addParams: function (params) {
6288
- return new RecommendParameters({ params: this.params.concat(params) });
6299
+ var newParams = this.params.slice();
6300
+ var existingParamsIndex = this.params.findIndex(function (currentParams) {
6301
+ return currentParams.$$id === params.$$id;
6302
+ });
6303
+
6304
+ if (existingParamsIndex !== -1) {
6305
+ newParams.splice(existingParamsIndex, 1, params);
6306
+ } else {
6307
+ newParams.push(params);
6308
+ }
6309
+
6310
+ return new RecommendParameters({ params: newParams });
6289
6311
  },
6290
6312
 
6291
6313
  removeParams: function (id) {
@@ -6295,6 +6317,45 @@
6295
6317
  }),
6296
6318
  });
6297
6319
  },
6320
+
6321
+ addFrequentlyBoughtTogether: function (params) {
6322
+ return this.addParams(
6323
+ Object.assign({}, params, { model: 'bought-together' })
6324
+ );
6325
+ },
6326
+
6327
+ addRelatedProducts: function (params) {
6328
+ return this.addParams(
6329
+ Object.assign({}, params, { model: 'related-products' })
6330
+ );
6331
+ },
6332
+
6333
+ addTrendingItems: function (params) {
6334
+ return this.addParams(
6335
+ Object.assign({}, params, { model: 'trending-items' })
6336
+ );
6337
+ },
6338
+
6339
+ addTrendingFacets: function (params) {
6340
+ return this.addParams(
6341
+ Object.assign({}, params, { model: 'trending-facets' })
6342
+ );
6343
+ },
6344
+
6345
+ addLookingSimilar: function (params) {
6346
+ return this.addParams(
6347
+ Object.assign({}, params, { model: 'looking-similar' })
6348
+ );
6349
+ },
6350
+
6351
+ _buildQueries: function (indexName) {
6352
+ return this.params.map(function (params) {
6353
+ var query = Object.assign({}, params, { indexName: indexName });
6354
+ delete query.$$id;
6355
+
6356
+ return query;
6357
+ });
6358
+ },
6298
6359
  };
6299
6360
 
6300
6361
  var RecommendParameters_1 = RecommendParameters;
@@ -10146,7 +10207,7 @@
10146
10207
 
10147
10208
  var SearchResults_1 = SearchResults;
10148
10209
 
10149
- var version = '3.17.0';
10210
+ var version = '3.19.0';
10150
10211
 
10151
10212
  var escapeFacetValue$4 = escapeFacetValue_1.escapeFacetValue;
10152
10213
 
@@ -10276,10 +10337,14 @@
10276
10337
  params: opts.recommendState,
10277
10338
  });
10278
10339
  this.lastResults = null;
10340
+ this.lastRecommendResults = null;
10279
10341
  this._queryId = 0;
10342
+ this._recommendQueryId = 0;
10280
10343
  this._lastQueryIdReceived = -1;
10344
+ this._lastRecommendQueryIdReceived = -1;
10281
10345
  this.derivedHelpers = [];
10282
10346
  this._currentNbQueries = 0;
10347
+ this._currentNbRecommendQueries = 0;
10283
10348
  this._searchResultsOptions = searchResultsOptions;
10284
10349
  }
10285
10350
 
@@ -10306,6 +10371,21 @@
10306
10371
  return this;
10307
10372
  };
10308
10373
 
10374
+ /**
10375
+ * Sends the recommendation queries set in the state. When the method is
10376
+ * called, it triggers a `fetch` event. The results will be available through
10377
+ * the `result` event. If an error occurs, an `error` will be fired instead.
10378
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10379
+ * @fires fetch
10380
+ * @fires result
10381
+ * @fires error
10382
+ * @chainable
10383
+ */
10384
+ AlgoliaSearchHelper.prototype.recommend = function () {
10385
+ this._recommend();
10386
+ return this;
10387
+ };
10388
+
10309
10389
  /**
10310
10390
  * Gets the search query parameters that would be sent to the Algolia Client
10311
10391
  * for the hits
@@ -10802,6 +10882,86 @@
10802
10882
  return this;
10803
10883
  };
10804
10884
 
10885
+ /**
10886
+ * Adds a "frequently bought together" recommendation query.
10887
+ *
10888
+ * @param {FrequentlyBoughtTogetherQuery} params the parameters for the recommendation
10889
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10890
+ * @fires change
10891
+ * @chainable
10892
+ */
10893
+ AlgoliaSearchHelper.prototype.addFrequentlyBoughtTogether = function (params) {
10894
+ this._recommendChange({
10895
+ state: this.recommendState.addFrequentlyBoughtTogether(params),
10896
+ });
10897
+
10898
+ return this;
10899
+ };
10900
+
10901
+ /**
10902
+ * Adds a "related products" recommendation query.
10903
+ *
10904
+ * @param {RelatedProductsQuery} params the parameters for the recommendation
10905
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10906
+ * @fires change
10907
+ * @chainable
10908
+ */
10909
+ AlgoliaSearchHelper.prototype.addRelatedProducts = function (params) {
10910
+ this._recommendChange({
10911
+ state: this.recommendState.addRelatedProducts(params),
10912
+ });
10913
+
10914
+ return this;
10915
+ };
10916
+
10917
+ /**
10918
+ * Adds a "trending items" recommendation query.
10919
+ *
10920
+ * @param {TrendingItemsQuery} params the parameters for the recommendation
10921
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10922
+ * @fires change
10923
+ * @chainable
10924
+ */
10925
+ AlgoliaSearchHelper.prototype.addTrendingItems = function (params) {
10926
+ this._recommendChange({
10927
+ state: this.recommendState.addTrendingItems(params),
10928
+ });
10929
+
10930
+ return this;
10931
+ };
10932
+
10933
+ /**
10934
+ * Adds a "trending facets" recommendation query.
10935
+ *
10936
+ * @param {TrendingFacetsQuery} params the parameters for the recommendation
10937
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10938
+ * @fires change
10939
+ * @chainable
10940
+ */
10941
+ AlgoliaSearchHelper.prototype.addTrendingFacets = function (params) {
10942
+ this._recommendChange({
10943
+ state: this.recommendState.addTrendingFacets(params),
10944
+ });
10945
+
10946
+ return this;
10947
+ };
10948
+
10949
+ /**
10950
+ * Adds a "looking similar" recommendation query.
10951
+ *
10952
+ * @param {LookingSimilarQuery} params the parameters for the recommendation
10953
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
10954
+ * @fires change
10955
+ * @chainable
10956
+ */
10957
+ AlgoliaSearchHelper.prototype.addLookingSimilar = function (params) {
10958
+ this._recommendChange({
10959
+ state: this.recommendState.addLookingSimilar(params),
10960
+ });
10961
+
10962
+ return this;
10963
+ };
10964
+
10805
10965
  /**
10806
10966
  * Removes an numeric filter to an attribute with the `operator` and `value` provided. If the
10807
10967
  * filter is not set, it doesn't change the filters.
@@ -10971,6 +11131,86 @@
10971
11131
  return this;
10972
11132
  };
10973
11133
 
11134
+ /**
11135
+ * Removes a "frequently bought together" recommendation query.
11136
+ *
11137
+ * @param {string} id identifier of the recommendation widget
11138
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
11139
+ * @fires change
11140
+ * @chainable
11141
+ */
11142
+ AlgoliaSearchHelper.prototype.removeFrequentlyBoughtTogether = function (id) {
11143
+ this._recommendChange({
11144
+ state: this.recommendState.removeParams(id),
11145
+ });
11146
+
11147
+ return this;
11148
+ };
11149
+
11150
+ /**
11151
+ * Removes a "related products" recommendation query.
11152
+ *
11153
+ * @param {string} id identifier of the recommendation widget
11154
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
11155
+ * @fires change
11156
+ * @chainable
11157
+ */
11158
+ AlgoliaSearchHelper.prototype.removeRelatedProducts = function (id) {
11159
+ this._recommendChange({
11160
+ state: this.recommendState.removeParams(id),
11161
+ });
11162
+
11163
+ return this;
11164
+ };
11165
+
11166
+ /**
11167
+ * Removes a "trending items" recommendation query.
11168
+ *
11169
+ * @param {string} id identifier of the recommendation widget
11170
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
11171
+ * @fires change
11172
+ * @chainable
11173
+ */
11174
+ AlgoliaSearchHelper.prototype.removeTrendingItems = function (id) {
11175
+ this._recommendChange({
11176
+ state: this.recommendState.removeParams(id),
11177
+ });
11178
+
11179
+ return this;
11180
+ };
11181
+
11182
+ /**
11183
+ * Removes a "trending facets" recommendation query.
11184
+ *
11185
+ * @param {string} id identifier of the recommendation widget
11186
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
11187
+ * @fires change
11188
+ * @chainable
11189
+ */
11190
+ AlgoliaSearchHelper.prototype.removeTrendingFacets = function (id) {
11191
+ this._recommendChange({
11192
+ state: this.recommendState.removeParams(id),
11193
+ });
11194
+
11195
+ return this;
11196
+ };
11197
+
11198
+ /**
11199
+ * Removes a "looking similar" recommendation query.
11200
+ *
11201
+ * @param {string} id identifier of the recommendation widget
11202
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
11203
+ * @fires change
11204
+ * @chainable
11205
+ */
11206
+ AlgoliaSearchHelper.prototype.removeLookingSimilar = function (id) {
11207
+ this._recommendChange({
11208
+ state: this.recommendState.removeParams(id),
11209
+ });
11210
+
11211
+ return this;
11212
+ };
11213
+
10974
11214
  /**
10975
11215
  * Adds or removes an exclusion filter to a faceted attribute with the `value` provided. If
10976
11216
  * the value is set then it removes it, otherwise it adds the filter.
@@ -11538,6 +11778,85 @@
11538
11778
  return undefined;
11539
11779
  };
11540
11780
 
11781
+ AlgoliaSearchHelper.prototype._recommend = function () {
11782
+ var searchState = this.state;
11783
+ var recommendState = this.recommendState;
11784
+ var index = this.getIndex();
11785
+ var states = [{ state: recommendState, index: index, helper: this }];
11786
+
11787
+ this.emit('fetch', {
11788
+ recommend: {
11789
+ state: recommendState,
11790
+ results: this.lastRecommendResults,
11791
+ },
11792
+ });
11793
+
11794
+ var derivedQueries = this.derivedHelpers.map(function (derivedHelper) {
11795
+ var derivedIndex = derivedHelper.getModifiedState(searchState).index;
11796
+ if (!derivedIndex) {
11797
+ return [];
11798
+ }
11799
+
11800
+ // Contrary to what is done when deriving the search state, we don't want to
11801
+ // provide the current recommend state to the derived helper, as it would
11802
+ // inherit unwanted queries. We instead provide an empty recommend state.
11803
+ var derivedState = derivedHelper.getModifiedRecommendState(
11804
+ new RecommendParameters_1()
11805
+ );
11806
+ states.push({
11807
+ state: derivedState,
11808
+ index: derivedIndex,
11809
+ helper: derivedHelper,
11810
+ });
11811
+
11812
+ derivedHelper.emit('fetch', {
11813
+ recommend: {
11814
+ state: derivedState,
11815
+ results: derivedHelper.lastRecommendResults,
11816
+ },
11817
+ });
11818
+
11819
+ return derivedState._buildQueries(derivedIndex);
11820
+ });
11821
+
11822
+ var queries = Array.prototype.concat.apply(
11823
+ this.recommendState._buildQueries(index),
11824
+ derivedQueries
11825
+ );
11826
+
11827
+ if (queries.length === 0) {
11828
+ return;
11829
+ }
11830
+
11831
+ if (
11832
+ queries.length > 0 &&
11833
+ typeof this.client.getRecommendations === 'undefined'
11834
+ ) {
11835
+ // eslint-disable-next-line no-console
11836
+ console.warn(
11837
+ 'Please update algoliasearch/lite to the latest version in order to use recommendations widgets.'
11838
+ );
11839
+ return;
11840
+ }
11841
+
11842
+ var queryId = this._recommendQueryId++;
11843
+ this._currentNbRecommendQueries++;
11844
+
11845
+ try {
11846
+ this.client
11847
+ .getRecommendations(queries)
11848
+ .then(this._dispatchRecommendResponse.bind(this, queryId, states))
11849
+ .catch(this._dispatchRecommendError.bind(this, queryId));
11850
+ } catch (error) {
11851
+ // If we reach this part, we're in an internal error state
11852
+ this.emit('error', {
11853
+ error: error,
11854
+ });
11855
+ }
11856
+
11857
+ return;
11858
+ };
11859
+
11541
11860
  /**
11542
11861
  * Transform the responses as sent by the server and transform them into a user
11543
11862
  * usable object that merge the results of all the batch requests. It will dispatch
@@ -11597,6 +11916,53 @@
11597
11916
  });
11598
11917
  };
11599
11918
 
11919
+ AlgoliaSearchHelper.prototype._dispatchRecommendResponse = function (
11920
+ queryId,
11921
+ states,
11922
+ content
11923
+ ) {
11924
+ // @TODO remove the number of outdated queries discarded instead of just one
11925
+
11926
+ if (queryId < this._lastRecommendQueryIdReceived) {
11927
+ // Outdated answer
11928
+ return;
11929
+ }
11930
+
11931
+ this._currentNbRecommendQueries -=
11932
+ queryId - this._lastRecommendQueryIdReceived;
11933
+ this._lastRecommendQueryIdReceived = queryId;
11934
+
11935
+ if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');
11936
+
11937
+ var results = content.results.slice();
11938
+
11939
+ states.forEach(function (s) {
11940
+ var state = s.state;
11941
+ var helper = s.helper;
11942
+
11943
+ if (!s.index) {
11944
+ // eslint-disable-next-line no-warning-comments
11945
+ // TODO: emit "result" event when events for Recommend are implemented
11946
+ helper.emit('recommend:result', {
11947
+ results: null,
11948
+ state: state,
11949
+ });
11950
+ return;
11951
+ }
11952
+
11953
+ helper.lastRecommendResults = results;
11954
+
11955
+ // eslint-disable-next-line no-warning-comments
11956
+ // TODO: emit "result" event when events for Recommend are implemented
11957
+ helper.emit('recommend:result', {
11958
+ recommend: {
11959
+ results: helper.lastRecommendResults,
11960
+ state: state,
11961
+ },
11962
+ });
11963
+ });
11964
+ };
11965
+
11600
11966
  AlgoliaSearchHelper.prototype._dispatchAlgoliaError = function (
11601
11967
  queryId,
11602
11968
  error
@@ -11616,6 +11982,26 @@
11616
11982
  if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');
11617
11983
  };
11618
11984
 
11985
+ AlgoliaSearchHelper.prototype._dispatchRecommendError = function (
11986
+ queryId,
11987
+ error
11988
+ ) {
11989
+ if (queryId < this._lastRecommendQueryIdReceived) {
11990
+ // Outdated answer
11991
+ return;
11992
+ }
11993
+
11994
+ this._currentNbRecommendQueries -=
11995
+ queryId - this._lastRecommendQueryIdReceived;
11996
+ this._lastRecommendQueryIdReceived = queryId;
11997
+
11998
+ this.emit('error', {
11999
+ error: error,
12000
+ });
12001
+
12002
+ if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');
12003
+ };
12004
+
11619
12005
  AlgoliaSearchHelper.prototype.containsRefinement = function (
11620
12006
  query,
11621
12007
  facetFilters,
@@ -11666,6 +12052,16 @@
11666
12052
 
11667
12053
  // eslint-disable-next-line no-warning-comments
11668
12054
  // TODO: emit "change" event when events for Recommend are implemented
12055
+ this.emit('recommend:change', {
12056
+ search: {
12057
+ results: this.lastResults,
12058
+ state: this.state,
12059
+ },
12060
+ recommend: {
12061
+ results: this.lastRecommendResults,
12062
+ state: this.recommendState,
12063
+ },
12064
+ });
11669
12065
  }
11670
12066
  };
11671
12067
 
@@ -11720,10 +12116,11 @@
11720
12116
  * and the SearchParameters that is returned by the call of the
11721
12117
  * parameter function.
11722
12118
  * @param {function} fn SearchParameters -> SearchParameters
12119
+ * @param {function} recommendFn RecommendParameters -> RecommendParameters
11723
12120
  * @return {DerivedHelper} a new DerivedHelper
11724
12121
  */
11725
- AlgoliaSearchHelper.prototype.derive = function (fn) {
11726
- var derivedHelper = new DerivedHelper_1(this, fn);
12122
+ AlgoliaSearchHelper.prototype.derive = function (fn, recommendFn) {
12123
+ var derivedHelper = new DerivedHelper_1(this, fn, recommendFn);
11727
12124
  this.derivedHelpers.push(derivedHelper);
11728
12125
  return derivedHelper;
11729
12126
  };
@@ -11825,6 +12222,13 @@
11825
12222
  */
11826
12223
  algoliasearchHelper.SearchParameters = SearchParameters_1;
11827
12224
 
12225
+ /**
12226
+ * Constructor for the object containing all the parameters for Recommend.
12227
+ * @member module:algoliasearchHelper.RecommendParameters
12228
+ * @type {RecommendParameters}
12229
+ */
12230
+ algoliasearchHelper.RecommendParameters = RecommendParameters_1;
12231
+
11828
12232
  /**
11829
12233
  * Constructor for the object containing the results of the search.
11830
12234
  * @member module:algoliasearchHelper.SearchResults
@@ -14413,7 +14817,8 @@
14413
14817
  };
14414
14818
  };
14415
14819
 
14416
- var _excluded$7 = ["initialSearchParameters"];
14820
+ var _excluded$7 = ["initialSearchParameters"],
14821
+ _excluded2$2 = ["initialRecommendParameters"];
14417
14822
  var withUsage$q = createDocumentationMessageGenerator({
14418
14823
  name: 'index-widget'
14419
14824
  });
@@ -14424,6 +14829,7 @@
14424
14829
  */
14425
14830
  function privateHelperSetState(helper, _ref) {
14426
14831
  var state = _ref.state,
14832
+ recommendState = _ref.recommendState,
14427
14833
  isPageReset = _ref.isPageReset,
14428
14834
  _uiState = _ref._uiState;
14429
14835
  if (state !== helper.state) {
@@ -14435,7 +14841,14 @@
14435
14841
  _uiState: _uiState
14436
14842
  });
14437
14843
  }
14844
+ if (recommendState !== helper.recommendState) {
14845
+ helper.recommendState = recommendState;
14846
+
14847
+ // eslint-disable-next-line no-warning-comments
14848
+ // TODO: emit "change" event when events for Recommend are implemented
14849
+ }
14438
14850
  }
14851
+
14439
14852
  function getLocalWidgetsUiState(widgets, widgetStateOptions) {
14440
14853
  var initialUiState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
14441
14854
  return widgets.reduce(function (uiState, widget) {
@@ -14454,15 +14867,26 @@
14454
14867
  function getLocalWidgetsSearchParameters(widgets, widgetSearchParametersOptions) {
14455
14868
  var initialSearchParameters = widgetSearchParametersOptions.initialSearchParameters,
14456
14869
  rest = _objectWithoutProperties(widgetSearchParametersOptions, _excluded$7);
14457
- return widgets.filter(function (widget) {
14458
- return !isIndexWidget(widget);
14459
- }).reduce(function (state, widget) {
14460
- if (!widget.getWidgetSearchParameters) {
14870
+ return widgets.reduce(function (state, widget) {
14871
+ if (!widget.getWidgetSearchParameters || isIndexWidget(widget)) {
14461
14872
  return state;
14462
14873
  }
14874
+ if (widget.dependsOn === 'search' && widget.getWidgetParameters) {
14875
+ return widget.getWidgetParameters(state, rest);
14876
+ }
14463
14877
  return widget.getWidgetSearchParameters(state, rest);
14464
14878
  }, initialSearchParameters);
14465
14879
  }
14880
+ function getLocalWidgetsRecommendParameters(widgets, widgetRecommendParametersOptions) {
14881
+ var initialRecommendParameters = widgetRecommendParametersOptions.initialRecommendParameters,
14882
+ rest = _objectWithoutProperties(widgetRecommendParametersOptions, _excluded2$2);
14883
+ return widgets.reduce(function (state, widget) {
14884
+ if (!isIndexWidget(widget) && widget.dependsOn === 'recommend' && widget.getWidgetParameters) {
14885
+ return widget.getWidgetParameters(state, rest);
14886
+ }
14887
+ return state;
14888
+ }, initialRecommendParameters);
14889
+ }
14466
14890
  function resetPageFromWidgets(widgets) {
14467
14891
  var indexWidgets = widgets.filter(isIndexWidget);
14468
14892
  if (indexWidgets.length === 0) {
@@ -14472,6 +14896,7 @@
14472
14896
  var widgetHelper = widget.getHelper();
14473
14897
  privateHelperSetState(widgetHelper, {
14474
14898
  state: widgetHelper.state.resetPage(),
14899
+ recommendState: widgetHelper.recommendState,
14475
14900
  isPageReset: true
14476
14901
  });
14477
14902
  resetPageFromWidgets(widget.getWidgets());
@@ -14530,9 +14955,18 @@
14530
14955
  },
14531
14956
  getScopedResults: function getScopedResults() {
14532
14957
  var widgetParent = this.getParent();
14533
-
14534
- // If the widget is the root, we consider itself as the only sibling.
14535
- var widgetSiblings = widgetParent ? widgetParent.getWidgets() : [this];
14958
+ var widgetSiblings;
14959
+ if (widgetParent) {
14960
+ widgetSiblings = widgetParent.getWidgets();
14961
+ } else if (indexName.length === 0) {
14962
+ // The widget is the root but has no index name:
14963
+ // we resolve results from its children index widgets
14964
+ widgetSiblings = this.getWidgets();
14965
+ } else {
14966
+ // The widget is the root and has an index name:
14967
+ // we consider itself as the only sibling
14968
+ widgetSiblings = [this];
14969
+ }
14536
14970
  return resolveScopedResultsFromWidgets(widgetSiblings);
14537
14971
  },
14538
14972
  getParent: function getParent() {
@@ -14567,6 +15001,10 @@
14567
15001
  uiState: localUiState,
14568
15002
  initialSearchParameters: helper.state
14569
15003
  }),
15004
+ recommendState: getLocalWidgetsRecommendParameters(localWidgets, {
15005
+ uiState: localUiState,
15006
+ initialRecommendParameters: helper.recommendState
15007
+ }),
14570
15008
  _uiState: localUiState
14571
15009
  });
14572
15010
 
@@ -14663,11 +15101,16 @@
14663
15101
  index: indexName
14664
15102
  })
14665
15103
  });
15104
+ var recommendParameters = getLocalWidgetsRecommendParameters(localWidgets, {
15105
+ uiState: localUiState,
15106
+ initialRecommendParameters: new algoliasearchHelper_1.RecommendParameters()
15107
+ });
14666
15108
 
14667
15109
  // This Helper is only used for state management we do not care about the
14668
15110
  // `searchClient`. Only the "main" Helper created at the `InstantSearch`
14669
15111
  // level is aware of the client.
14670
15112
  helper = algoliasearchHelper_1({}, parameters.index, parameters);
15113
+ helper.recommendState = recommendParameters;
14671
15114
 
14672
15115
  // We forward the call to `search` to the "main" instance of the Helper
14673
15116
  // which is responsible for managing the queries (it's the only one that is
@@ -14698,6 +15141,8 @@
14698
15141
  };
14699
15142
  derivedHelper = mainHelper.derive(function () {
14700
15143
  return mergeSearchParameters.apply(void 0, [mainHelper.state].concat(_toConsumableArray(resolveSearchParameters(_this3))));
15144
+ }, function () {
15145
+ return _this3.getHelper().recommendState;
14701
15146
  });
14702
15147
  var indexInitialResults = (_instantSearchInstanc = instantSearchInstance._initialResults) === null || _instantSearchInstanc === void 0 ? void 0 : _instantSearchInstanc[this.getIndexId()];
14703
15148
  if (indexInitialResults) {
@@ -14746,6 +15191,21 @@
14746
15191
  lastValidSearchParameters = results === null || results === void 0 ? void 0 : results._state;
14747
15192
  });
14748
15193
 
15194
+ // eslint-disable-next-line no-warning-comments
15195
+ // TODO: listen to "result" event when events for Recommend are implemented
15196
+ derivedHelper.on('recommend:result', function (_ref5) {
15197
+ var recommend = _ref5.recommend;
15198
+ // The index does not render the results it schedules a new render
15199
+ // to let all the other indices emit their own results. It allows us to
15200
+ // run the render process in one pass.
15201
+ instantSearchInstance.scheduleRender();
15202
+
15203
+ // the derived helper is the one which actually searches, but the helper
15204
+ // which is exposed e.g. via instance.helper, doesn't search, and thus
15205
+ // does not have access to lastRecommendResults.
15206
+ helper.lastRecommendResults = recommend.results;
15207
+ });
15208
+
14749
15209
  // We compute the render state before calling `init` in a separate loop
14750
15210
  // to construct the whole render state object that is then passed to
14751
15211
  // `init`.
@@ -14796,9 +15256,9 @@
14796
15256
  instantSearchInstance.scheduleRender();
14797
15257
  }
14798
15258
  },
14799
- render: function render(_ref5) {
15259
+ render: function render(_ref6) {
14800
15260
  var _this4 = this;
14801
- var instantSearchInstance = _ref5.instantSearchInstance;
15261
+ var instantSearchInstance = _ref6.instantSearchInstance;
14802
15262
  // we can't attach a listener to the error event of search, as the error
14803
15263
  // then would no longer be thrown for global handlers.
14804
15264
  if (instantSearchInstance.status === 'error' && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
@@ -14808,6 +15268,14 @@
14808
15268
  // We only render index widgets if there are no results.
14809
15269
  // This makes sure `render` is never called with `results` being `null`.
14810
15270
  var widgetsToRender = this.getResults() ? localWidgets : localWidgets.filter(isIndexWidget);
15271
+ widgetsToRender = widgetsToRender.filter(function (widget) {
15272
+ if (!widget.shouldRender) {
15273
+ return true;
15274
+ }
15275
+ return widget.shouldRender({
15276
+ instantSearchInstance: instantSearchInstance
15277
+ });
15278
+ });
14811
15279
  widgetsToRender.forEach(function (widget) {
14812
15280
  if (widget.getRenderState) {
14813
15281
  var renderState = widget.getRenderState(instantSearchInstance.renderState[_this4.getIndexId()] || {}, createRenderArgs(instantSearchInstance, _this4));
@@ -14866,8 +15334,8 @@
14866
15334
  _warning(false, 'The `getWidgetState` method is renamed `getWidgetUiState` and will no longer exist under that name in InstantSearch.js 5.x. Please use `getWidgetUiState` instead.') ;
14867
15335
  return this.getWidgetUiState(uiState);
14868
15336
  },
14869
- getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref6) {
14870
- var uiState = _ref6.uiState;
15337
+ getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref7) {
15338
+ var uiState = _ref7.uiState;
14871
15339
  return getLocalWidgetsSearchParameters(localWidgets, {
14872
15340
  uiState: uiState,
14873
15341
  initialSearchParameters: searchParameters
@@ -14887,10 +15355,10 @@
14887
15355
  }
14888
15356
  };
14889
15357
  };
14890
- function storeRenderState(_ref7) {
14891
- var renderState = _ref7.renderState,
14892
- instantSearchInstance = _ref7.instantSearchInstance,
14893
- parent = _ref7.parent;
15358
+ function storeRenderState(_ref8) {
15359
+ var renderState = _ref8.renderState,
15360
+ instantSearchInstance = _ref8.instantSearchInstance,
15361
+ parent = _ref8.parent;
14894
15362
  var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
14895
15363
  instantSearchInstance.renderState = _objectSpread2(_objectSpread2({}, instantSearchInstance.renderState), {}, _defineProperty({}, parentIndexName, _objectSpread2(_objectSpread2({}, instantSearchInstance.renderState[parentIndexName]), renderState)));
14896
15364
  }
@@ -14960,7 +15428,7 @@
14960
15428
  };
14961
15429
  }
14962
15430
 
14963
- var version$1 = '4.66.1';
15431
+ var version$1 = '4.68.0';
14964
15432
 
14965
15433
  var withUsage$r = createDocumentationMessageGenerator({
14966
15434
  name: 'instantsearch'
@@ -15323,7 +15791,7 @@
15323
15791
  // under the hood, we have a different implementation. It should be
15324
15792
  // completely transparent for the rest of the codebase. Only this module
15325
15793
  // is impacted.
15326
- return mainHelper.searchOnlyWithDerivedHelpers();
15794
+ return mainHelper.searchOnlyWithDerivedHelpers() && mainHelper.recommend();
15327
15795
  };
15328
15796
  if (this._searchFunction) {
15329
15797
  // this client isn't used to actually search, but required for the helper
@@ -15730,12 +16198,43 @@
15730
16198
  };
15731
16199
  }
15732
16200
 
15733
- var _excluded$a = ["classNames", "hits", "itemComponent", "sendEvent", "emptyComponent"];
16201
+ var _excluded$a = ["classNames", "hits", "itemComponent", "sendEvent", "emptyComponent", "banner", "bannerComponent"];
15734
16202
 
15735
16203
  // Should be imported from a shared package in the future
15736
16204
 
15737
- function createHitsComponent(_ref) {
16205
+ function createDefaultBannerComponent(_ref) {
15738
16206
  var createElement = _ref.createElement;
16207
+ return function DefaultBanner(_ref2) {
16208
+ var _banner$link;
16209
+ var classNames = _ref2.classNames,
16210
+ banner = _ref2.banner;
16211
+ if (!banner.image.urls[0].url) {
16212
+ return null;
16213
+ }
16214
+ return createElement("aside", {
16215
+ className: cx('ais-Hits-banner', classNames.bannerRoot)
16216
+ }, (_banner$link = banner.link) !== null && _banner$link !== void 0 && _banner$link.url ? createElement("a", {
16217
+ className: cx('ais-Hits-banner-link', classNames.bannerLink),
16218
+ href: banner.link.url,
16219
+ target: banner.link.target
16220
+ }, createElement("img", {
16221
+ className: cx('ais-Hits-banner-image', classNames.bannerImage),
16222
+ src: banner.image.urls[0].url,
16223
+ alt: banner.image.title
16224
+ })) : createElement("img", {
16225
+ className: cx('ais-Hits-banner-image', classNames.bannerImage),
16226
+ src: banner.image.urls[0].url,
16227
+ alt: banner.image.title
16228
+ }));
16229
+ };
16230
+ }
16231
+ function createHitsComponent(_ref3) {
16232
+ var createElement = _ref3.createElement,
16233
+ Fragment = _ref3.Fragment;
16234
+ var DefaultBannerComponent = createDefaultBannerComponent({
16235
+ createElement: createElement,
16236
+ Fragment: Fragment
16237
+ });
15739
16238
  return function Hits(userProps) {
15740
16239
  var _userProps$classNames = userProps.classNames,
15741
16240
  classNames = _userProps$classNames === void 0 ? {} : _userProps$classNames,
@@ -15743,15 +16242,18 @@
15743
16242
  ItemComponent = userProps.itemComponent,
15744
16243
  sendEvent = userProps.sendEvent,
15745
16244
  EmptyComponent = userProps.emptyComponent,
16245
+ banner = userProps.banner,
16246
+ BannerComponent = userProps.bannerComponent,
15746
16247
  props = _objectWithoutProperties$1(userProps, _excluded$a);
15747
- if (hits.length === 0 && EmptyComponent) {
15748
- return createElement(EmptyComponent, {
15749
- className: cx('ais-Hits', classNames.root, cx('ais-Hits--empty', classNames.emptyRoot), props.className)
15750
- });
15751
- }
15752
16248
  return createElement("div", _extends$1({}, props, {
15753
16249
  className: cx('ais-Hits', classNames.root, hits.length === 0 && cx('ais-Hits--empty', classNames.emptyRoot), props.className)
15754
- }), createElement("ol", {
16250
+ }), banner && (BannerComponent ? createElement(BannerComponent, {
16251
+ className: cx('ais-Hits-banner', classNames.bannerRoot),
16252
+ banner: banner
16253
+ }) : createElement(DefaultBannerComponent, {
16254
+ classNames: classNames,
16255
+ banner: banner
16256
+ })), hits.length === 0 && EmptyComponent ? createElement(EmptyComponent, null) : createElement("ol", {
15755
16257
  className: cx('ais-Hits-list', classNames.list)
15756
16258
  }, hits.map(function (hit, index) {
15757
16259
  return createElement(ItemComponent, {
@@ -16636,7 +17138,7 @@
16636
17138
  }
16637
17139
 
16638
17140
  var _excluded$e = ["hit", "attribute", "cssClasses"],
16639
- _excluded2$2 = ["isHighlighted"];
17141
+ _excluded2$3 = ["isHighlighted"];
16640
17142
  function ReverseHighlight$1(_ref) {
16641
17143
  var hit = _ref.hit,
16642
17144
  attribute = _ref.attribute,
@@ -16649,7 +17151,7 @@
16649
17151
  var value = _ref2.value;
16650
17152
  return getHighlightedParts(unescape$1(value || '')).map(function (_ref3) {
16651
17153
  var isHighlighted = _ref3.isHighlighted,
16652
- rest = _objectWithoutProperties(_ref3, _excluded2$2);
17154
+ rest = _objectWithoutProperties(_ref3, _excluded2$3);
16653
17155
  return _objectSpread2(_objectSpread2({}, rest), {}, {
16654
17156
  isHighlighted: !isHighlighted
16655
17157
  });
@@ -16677,7 +17179,7 @@
16677
17179
  }
16678
17180
 
16679
17181
  var _excluded$g = ["hit", "attribute", "cssClasses"],
16680
- _excluded2$3 = ["isHighlighted"];
17182
+ _excluded2$4 = ["isHighlighted"];
16681
17183
  function ReverseSnippet$1(_ref) {
16682
17184
  var hit = _ref.hit,
16683
17185
  attribute = _ref.attribute,
@@ -16690,7 +17192,7 @@
16690
17192
  var value = _ref2.value;
16691
17193
  return getHighlightedParts(unescape$1(value || '')).map(function (_ref3) {
16692
17194
  var isHighlighted = _ref3.isHighlighted,
16693
- rest = _objectWithoutProperties(_ref3, _excluded2$3);
17195
+ rest = _objectWithoutProperties(_ref3, _excluded2$4);
16694
17196
  return _objectSpread2(_objectSpread2({}, rest), {}, {
16695
17197
  isHighlighted: !isHighlighted
16696
17198
  });
@@ -16812,7 +17314,7 @@
16812
17314
  var fragment = new DocumentFragment();
16813
17315
  var root = document.createElement('div');
16814
17316
  root.innerHTML = this.props.content;
16815
- this.nodes = _toConsumableArray(root.children);
17317
+ this.nodes = _toConsumableArray(root.childNodes);
16816
17318
  this.nodes.forEach(function (node) {
16817
17319
  return fragment.appendChild(node);
16818
17320
  });
@@ -16822,8 +17324,17 @@
16822
17324
  key: "componentWillUnmount",
16823
17325
  value: function componentWillUnmount() {
16824
17326
  this.nodes.forEach(function (node) {
16825
- return node.outerHTML = '';
17327
+ if (node instanceof Element) {
17328
+ node.outerHTML = '';
17329
+ return;
17330
+ }
17331
+ node.nodeValue = '';
16826
17332
  });
17333
+ // if there is one TextNode first and one TextNode last, the
17334
+ // last one's nodeValue will be assigned to the first.
17335
+ if (this.nodes[0].nodeValue) {
17336
+ this.nodes[0].nodeValue = '';
17337
+ }
16827
17338
  }
16828
17339
  }, {
16829
17340
  key: "render",
@@ -18041,7 +18552,7 @@
18041
18552
  };
18042
18553
 
18043
18554
  var _excluded$k = ["initialZoom", "initialPosition", "templates", "cssClasses", "builtInMarker", "customHTMLMarker", "enableRefine", "enableClearMapRefinement", "enableRefineControl", "container", "googleReference"],
18044
- _excluded2$4 = ["item"],
18555
+ _excluded2$5 = ["item"],
18045
18556
  _excluded3 = ["item"];
18046
18557
  var withUsage$y = createDocumentationMessageGenerator({
18047
18558
  name: 'geo-search'
@@ -18143,7 +18654,7 @@
18143
18654
  var customHTMLMarker = isCustomHTMLMarker && _objectSpread2(_objectSpread2({}, defaultCustomHTMLMarker), userCustomHTMLMarker);
18144
18655
  var createBuiltInMarker = function createBuiltInMarker(_ref2) {
18145
18656
  var item = _ref2.item,
18146
- rest = _objectWithoutProperties(_ref2, _excluded2$4);
18657
+ rest = _objectWithoutProperties(_ref2, _excluded2$5);
18147
18658
  return new googleReference.maps.Marker(_objectSpread2(_objectSpread2(_objectSpread2({}, builtInMarker.createOptions(item)), rest), {}, {
18148
18659
  // @ts-expect-error @types/googlemaps doesn't document this
18149
18660
  __id: item.objectID,
@@ -18855,7 +19366,8 @@
18855
19366
  instantSearchInstance = _ref2.instantSearchInstance,
18856
19367
  insights = _ref2.insights,
18857
19368
  bindEvent = _ref2.bindEvent,
18858
- sendEvent = _ref2.sendEvent;
19369
+ sendEvent = _ref2.sendEvent,
19370
+ banner = _ref2.banner;
18859
19371
  if (isFirstRendering) {
18860
19372
  renderState.templateProps = prepareTemplateProps({
18861
19373
  defaultTemplates: defaultTemplates$5,
@@ -18873,7 +19385,8 @@
18873
19385
  return h(Template, _extends({}, renderState.templateProps, {
18874
19386
  rootProps: rootProps,
18875
19387
  templateKey: "empty",
18876
- data: results
19388
+ data: results,
19389
+ rootTagName: "fragment"
18877
19390
  }));
18878
19391
  };
18879
19392
 
@@ -18906,12 +19419,21 @@
18906
19419
  sendEvent: sendEvent
18907
19420
  }));
18908
19421
  };
19422
+ var bannerComponent = function bannerComponent(props) {
19423
+ return h(Template, _extends({}, renderState.templateProps, {
19424
+ templateKey: "banner",
19425
+ data: props,
19426
+ rootTagName: "fragment"
19427
+ }));
19428
+ };
18909
19429
  P(h(Hits, {
18910
19430
  hits: receivedHits,
18911
19431
  itemComponent: itemComponent,
18912
19432
  sendEvent: sendEvent,
18913
19433
  classNames: cssClasses,
18914
- emptyComponent: emptyComponent
19434
+ emptyComponent: emptyComponent,
19435
+ banner: banner,
19436
+ bannerComponent: templates.banner ? bannerComponent : undefined
18915
19437
  }), containerNode);
18916
19438
  };
18917
19439
  };
@@ -20083,7 +20605,7 @@
20083
20605
  };
20084
20606
 
20085
20607
  var _excluded$n = ["placesReference", "defaultPosition"],
20086
- _excluded2$5 = ["places"];
20608
+ _excluded2$6 = ["places"];
20087
20609
 
20088
20610
  /* Places.js is an optional dependency, no error should be reported if the package is missing */
20089
20611
  /** @ts-ignore */
@@ -20139,7 +20661,7 @@
20139
20661
  var hasPositionSet = position !== defaultPosition.join(',');
20140
20662
  if (!hasPositionSet && !state.query) {
20141
20663
  var places = uiState.places,
20142
- uiStateWithoutPlaces = _objectWithoutProperties(uiState, _excluded2$5);
20664
+ uiStateWithoutPlaces = _objectWithoutProperties(uiState, _excluded2$6);
20143
20665
  return uiStateWithoutPlaces;
20144
20666
  }
20145
20667
  return _objectSpread2(_objectSpread2({}, uiState), {}, {