react-instantsearch 7.7.0 → 7.7.2

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.
@@ -7,7 +7,7 @@
7
7
 
8
8
  var React__default = 'default' in React ? React['default'] : React;
9
9
 
10
- var version = '7.7.0';
10
+ var version = '7.7.2';
11
11
 
12
12
  // Copyright Joyent, Inc. and other Node contributors.
13
13
  //
@@ -335,12 +335,15 @@
335
335
  * This event contains a {@link SearchResults} object and the
336
336
  * {@link SearchParameters} corresponding to this answer.
337
337
  * @param {AlgoliaSearchHelper} mainHelper the main helper
338
- * @param {function} fn the function to create the derived state
338
+ * @param {function} fn the function to create the derived state for search
339
+ * @param {function} recommendFn the function to create the derived state for recommendations
339
340
  */
340
- function DerivedHelper(mainHelper, fn) {
341
+ function DerivedHelper(mainHelper, fn, recommendFn) {
341
342
  this.main = mainHelper;
342
343
  this.fn = fn;
344
+ this.recommendFn = recommendFn;
343
345
  this.lastResults = null;
346
+ this.lastRecommendResults = null;
344
347
  }
345
348
 
346
349
  inherits_1(DerivedHelper, events);
@@ -359,6 +362,10 @@
359
362
  return this.fn(parameters);
360
363
  };
361
364
 
365
+ DerivedHelper.prototype.getModifiedRecommendState = function (parameters) {
366
+ return this.recommendFn(parameters);
367
+ };
368
+
362
369
  var DerivedHelper_1 = DerivedHelper;
363
370
 
364
371
  /**
@@ -497,6 +504,92 @@
497
504
 
498
505
  var omit = _objectWithoutPropertiesLoose;
499
506
 
507
+ /**
508
+ * RecommendParameters is the data structure that contains all the information
509
+ * usable for getting recommendations from the Algolia API. It doesn't do the
510
+ * search itself, nor does it contains logic about the parameters.
511
+ * It is an immutable object, therefore it has been created in a way that each
512
+ * changes does not change the object itself but returns a copy with the
513
+ * modification.
514
+ * This object should probably not be instantiated outside of the helper. It
515
+ * will be provided when needed.
516
+ * @constructor
517
+ * @classdesc contains all the parameters for recommendations
518
+ * @param {RecommendParametersOptions} opts the options to create the object
519
+ */
520
+ function RecommendParameters(opts) {
521
+ opts = opts || {};
522
+ this.params = opts.params || [];
523
+ }
524
+
525
+ RecommendParameters.prototype = {
526
+ constructor: RecommendParameters,
527
+
528
+ addParams: function (params) {
529
+ var newParams = this.params.slice();
530
+ var existingParamsIndex = this.params.findIndex(function (currentParams) {
531
+ return currentParams.$$id === params.$$id;
532
+ });
533
+
534
+ if (existingParamsIndex !== -1) {
535
+ newParams.splice(existingParamsIndex, 1, params);
536
+ } else {
537
+ newParams.push(params);
538
+ }
539
+
540
+ return new RecommendParameters({ params: newParams });
541
+ },
542
+
543
+ removeParams: function (id) {
544
+ return new RecommendParameters({
545
+ params: this.params.filter(function (param) {
546
+ return param.$$id !== id;
547
+ }),
548
+ });
549
+ },
550
+
551
+ addFrequentlyBoughtTogether: function (params) {
552
+ return this.addParams(
553
+ Object.assign({}, params, { model: 'bought-together' })
554
+ );
555
+ },
556
+
557
+ addRelatedProducts: function (params) {
558
+ return this.addParams(
559
+ Object.assign({}, params, { model: 'related-products' })
560
+ );
561
+ },
562
+
563
+ addTrendingItems: function (params) {
564
+ return this.addParams(
565
+ Object.assign({}, params, { model: 'trending-items' })
566
+ );
567
+ },
568
+
569
+ addTrendingFacets: function (params) {
570
+ return this.addParams(
571
+ Object.assign({}, params, { model: 'trending-facets' })
572
+ );
573
+ },
574
+
575
+ addLookingSimilar: function (params) {
576
+ return this.addParams(
577
+ Object.assign({}, params, { model: 'looking-similar' })
578
+ );
579
+ },
580
+
581
+ _buildQueries: function (indexName) {
582
+ return this.params.map(function (params) {
583
+ var query = Object.assign({}, params, { indexName: indexName });
584
+ delete query.$$id;
585
+
586
+ return query;
587
+ });
588
+ },
589
+ };
590
+
591
+ var RecommendParameters_1 = RecommendParameters;
592
+
500
593
  function sortObject(obj) {
501
594
  return Object.keys(obj)
502
595
  .sort()
@@ -4344,7 +4437,7 @@
4344
4437
 
4345
4438
  var SearchResults_1 = SearchResults;
4346
4439
 
4347
- var version$1 = '3.16.3';
4440
+ var version$1 = '3.18.0';
4348
4441
 
4349
4442
  var escapeFacetValue$3 = escapeFacetValue_1.escapeFacetValue;
4350
4443
 
@@ -4356,6 +4449,7 @@
4356
4449
 
4357
4450
 
4358
4451
 
4452
+
4359
4453
  /**
4360
4454
  * Event triggered when a parameter is set or updated
4361
4455
  * @event AlgoliaSearchHelper#event:change
@@ -4469,11 +4563,18 @@
4469
4563
  var opts = options || {};
4470
4564
  opts.index = index;
4471
4565
  this.state = SearchParameters_1.make(opts);
4566
+ this.recommendState = new RecommendParameters_1({
4567
+ params: opts.recommendState,
4568
+ });
4472
4569
  this.lastResults = null;
4570
+ this.lastRecommendResults = null;
4473
4571
  this._queryId = 0;
4572
+ this._recommendQueryId = 0;
4474
4573
  this._lastQueryIdReceived = -1;
4574
+ this._lastRecommendQueryIdReceived = -1;
4475
4575
  this.derivedHelpers = [];
4476
4576
  this._currentNbQueries = 0;
4577
+ this._currentNbRecommendQueries = 0;
4477
4578
  this._searchResultsOptions = searchResultsOptions;
4478
4579
  }
4479
4580
 
@@ -4500,6 +4601,21 @@
4500
4601
  return this;
4501
4602
  };
4502
4603
 
4604
+ /**
4605
+ * Sends the recommendation queries set in the state. When the method is
4606
+ * called, it triggers a `fetch` event. The results will be available through
4607
+ * the `result` event. If an error occurs, an `error` will be fired instead.
4608
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
4609
+ * @fires fetch
4610
+ * @fires result
4611
+ * @fires error
4612
+ * @chainable
4613
+ */
4614
+ AlgoliaSearchHelper.prototype.recommend = function () {
4615
+ this._recommend();
4616
+ return this;
4617
+ };
4618
+
4503
4619
  /**
4504
4620
  * Gets the search query parameters that would be sent to the Algolia Client
4505
4621
  * for the hits
@@ -4996,6 +5112,86 @@
4996
5112
  return this;
4997
5113
  };
4998
5114
 
5115
+ /**
5116
+ * Adds a "frequently bought together" recommendation query.
5117
+ *
5118
+ * @param {FrequentlyBoughtTogetherQuery} params the parameters for the recommendation
5119
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
5120
+ * @fires change
5121
+ * @chainable
5122
+ */
5123
+ AlgoliaSearchHelper.prototype.addFrequentlyBoughtTogether = function (params) {
5124
+ this._recommendChange({
5125
+ state: this.recommendState.addFrequentlyBoughtTogether(params),
5126
+ });
5127
+
5128
+ return this;
5129
+ };
5130
+
5131
+ /**
5132
+ * Adds a "related products" recommendation query.
5133
+ *
5134
+ * @param {RelatedProductsQuery} params the parameters for the recommendation
5135
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
5136
+ * @fires change
5137
+ * @chainable
5138
+ */
5139
+ AlgoliaSearchHelper.prototype.addRelatedProducts = function (params) {
5140
+ this._recommendChange({
5141
+ state: this.recommendState.addRelatedProducts(params),
5142
+ });
5143
+
5144
+ return this;
5145
+ };
5146
+
5147
+ /**
5148
+ * Adds a "trending items" recommendation query.
5149
+ *
5150
+ * @param {TrendingItemsQuery} params the parameters for the recommendation
5151
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
5152
+ * @fires change
5153
+ * @chainable
5154
+ */
5155
+ AlgoliaSearchHelper.prototype.addTrendingItems = function (params) {
5156
+ this._recommendChange({
5157
+ state: this.recommendState.addTrendingItems(params),
5158
+ });
5159
+
5160
+ return this;
5161
+ };
5162
+
5163
+ /**
5164
+ * Adds a "trending facets" recommendation query.
5165
+ *
5166
+ * @param {TrendingFacetsQuery} params the parameters for the recommendation
5167
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
5168
+ * @fires change
5169
+ * @chainable
5170
+ */
5171
+ AlgoliaSearchHelper.prototype.addTrendingFacets = function (params) {
5172
+ this._recommendChange({
5173
+ state: this.recommendState.addTrendingFacets(params),
5174
+ });
5175
+
5176
+ return this;
5177
+ };
5178
+
5179
+ /**
5180
+ * Adds a "looking similar" recommendation query.
5181
+ *
5182
+ * @param {LookingSimilarQuery} params the parameters for the recommendation
5183
+ * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
5184
+ * @fires change
5185
+ * @chainable
5186
+ */
5187
+ AlgoliaSearchHelper.prototype.addLookingSimilar = function (params) {
5188
+ this._recommendChange({
5189
+ state: this.recommendState.addLookingSimilar(params),
5190
+ });
5191
+
5192
+ return this;
5193
+ };
5194
+
4999
5195
  /**
5000
5196
  * Removes an numeric filter to an attribute with the `operator` and `value` provided. If the
5001
5197
  * filter is not set, it doesn't change the filters.
@@ -5165,6 +5361,86 @@
5165
5361
  return this;
5166
5362
  };
5167
5363
 
5364
+ /**
5365
+ * Removes a "frequently bought together" recommendation query.
5366
+ *
5367
+ * @param {string} id identifier of the recommendation widget
5368
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
5369
+ * @fires change
5370
+ * @chainable
5371
+ */
5372
+ AlgoliaSearchHelper.prototype.removeFrequentlyBoughtTogether = function (id) {
5373
+ this._recommendChange({
5374
+ state: this.recommendState.removeParams(id),
5375
+ });
5376
+
5377
+ return this;
5378
+ };
5379
+
5380
+ /**
5381
+ * Removes a "related products" recommendation query.
5382
+ *
5383
+ * @param {string} id identifier of the recommendation widget
5384
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
5385
+ * @fires change
5386
+ * @chainable
5387
+ */
5388
+ AlgoliaSearchHelper.prototype.removeRelatedProducts = function (id) {
5389
+ this._recommendChange({
5390
+ state: this.recommendState.removeParams(id),
5391
+ });
5392
+
5393
+ return this;
5394
+ };
5395
+
5396
+ /**
5397
+ * Removes a "trending items" recommendation query.
5398
+ *
5399
+ * @param {string} id identifier of the recommendation widget
5400
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
5401
+ * @fires change
5402
+ * @chainable
5403
+ */
5404
+ AlgoliaSearchHelper.prototype.removeTrendingItems = function (id) {
5405
+ this._recommendChange({
5406
+ state: this.recommendState.removeParams(id),
5407
+ });
5408
+
5409
+ return this;
5410
+ };
5411
+
5412
+ /**
5413
+ * Removes a "trending facets" recommendation query.
5414
+ *
5415
+ * @param {string} id identifier of the recommendation widget
5416
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
5417
+ * @fires change
5418
+ * @chainable
5419
+ */
5420
+ AlgoliaSearchHelper.prototype.removeTrendingFacets = function (id) {
5421
+ this._recommendChange({
5422
+ state: this.recommendState.removeParams(id),
5423
+ });
5424
+
5425
+ return this;
5426
+ };
5427
+
5428
+ /**
5429
+ * Removes a "looking similar" recommendation query.
5430
+ *
5431
+ * @param {string} id identifier of the recommendation widget
5432
+ * @returns {AlgoliaSearchHelper} Method is chainable, it returns itself
5433
+ * @fires change
5434
+ * @chainable
5435
+ */
5436
+ AlgoliaSearchHelper.prototype.removeLookingSimilar = function (id) {
5437
+ this._recommendChange({
5438
+ state: this.recommendState.removeParams(id),
5439
+ });
5440
+
5441
+ return this;
5442
+ };
5443
+
5168
5444
  /**
5169
5445
  * Adds or removes an exclusion filter to a faceted attribute with the `value` provided. If
5170
5446
  * the value is set then it removes it, otherwise it adds the filter.
@@ -5732,6 +6008,85 @@
5732
6008
  return undefined;
5733
6009
  };
5734
6010
 
6011
+ AlgoliaSearchHelper.prototype._recommend = function () {
6012
+ var searchState = this.state;
6013
+ var recommendState = this.recommendState;
6014
+ var index = this.getIndex();
6015
+ var states = [{ state: recommendState, index: index, helper: this }];
6016
+
6017
+ this.emit('fetch', {
6018
+ recommend: {
6019
+ state: recommendState,
6020
+ results: this.lastRecommendResults,
6021
+ },
6022
+ });
6023
+
6024
+ var derivedQueries = this.derivedHelpers.map(function (derivedHelper) {
6025
+ var derivedIndex = derivedHelper.getModifiedState(searchState).index;
6026
+ if (!derivedIndex) {
6027
+ return [];
6028
+ }
6029
+
6030
+ // Contrary to what is done when deriving the search state, we don't want to
6031
+ // provide the current recommend state to the derived helper, as it would
6032
+ // inherit unwanted queries. We instead provide an empty recommend state.
6033
+ var derivedState = derivedHelper.getModifiedRecommendState(
6034
+ new RecommendParameters_1()
6035
+ );
6036
+ states.push({
6037
+ state: derivedState,
6038
+ index: derivedIndex,
6039
+ helper: derivedHelper,
6040
+ });
6041
+
6042
+ derivedHelper.emit('fetch', {
6043
+ recommend: {
6044
+ state: derivedState,
6045
+ results: derivedHelper.lastRecommendResults,
6046
+ },
6047
+ });
6048
+
6049
+ return derivedState._buildQueries(derivedIndex);
6050
+ });
6051
+
6052
+ var queries = Array.prototype.concat.apply(
6053
+ this.recommendState._buildQueries(index),
6054
+ derivedQueries
6055
+ );
6056
+
6057
+ if (queries.length === 0) {
6058
+ return;
6059
+ }
6060
+
6061
+ if (
6062
+ queries.length > 0 &&
6063
+ typeof this.client.getRecommendations === 'undefined'
6064
+ ) {
6065
+ // eslint-disable-next-line no-console
6066
+ console.warn(
6067
+ 'Please update algoliasearch/lite to the latest version in order to use recommendations widgets.'
6068
+ );
6069
+ return;
6070
+ }
6071
+
6072
+ var queryId = this._recommendQueryId++;
6073
+ this._currentNbRecommendQueries++;
6074
+
6075
+ try {
6076
+ this.client
6077
+ .getRecommendations(queries)
6078
+ .then(this._dispatchRecommendResponse.bind(this, queryId, states))
6079
+ .catch(this._dispatchRecommendError.bind(this, queryId));
6080
+ } catch (error) {
6081
+ // If we reach this part, we're in an internal error state
6082
+ this.emit('error', {
6083
+ error: error,
6084
+ });
6085
+ }
6086
+
6087
+ return;
6088
+ };
6089
+
5735
6090
  /**
5736
6091
  * Transform the responses as sent by the server and transform them into a user
5737
6092
  * usable object that merge the results of all the batch requests. It will dispatch
@@ -5791,6 +6146,53 @@
5791
6146
  });
5792
6147
  };
5793
6148
 
6149
+ AlgoliaSearchHelper.prototype._dispatchRecommendResponse = function (
6150
+ queryId,
6151
+ states,
6152
+ content
6153
+ ) {
6154
+ // @TODO remove the number of outdated queries discarded instead of just one
6155
+
6156
+ if (queryId < this._lastRecommendQueryIdReceived) {
6157
+ // Outdated answer
6158
+ return;
6159
+ }
6160
+
6161
+ this._currentNbRecommendQueries -=
6162
+ queryId - this._lastRecommendQueryIdReceived;
6163
+ this._lastRecommendQueryIdReceived = queryId;
6164
+
6165
+ if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');
6166
+
6167
+ var results = content.results.slice();
6168
+
6169
+ states.forEach(function (s) {
6170
+ var state = s.state;
6171
+ var helper = s.helper;
6172
+
6173
+ if (!s.index) {
6174
+ // eslint-disable-next-line no-warning-comments
6175
+ // TODO: emit "result" event when events for Recommend are implemented
6176
+ helper.emit('recommend:result', {
6177
+ results: null,
6178
+ state: state,
6179
+ });
6180
+ return;
6181
+ }
6182
+
6183
+ helper.lastRecommendResults = results;
6184
+
6185
+ // eslint-disable-next-line no-warning-comments
6186
+ // TODO: emit "result" event when events for Recommend are implemented
6187
+ helper.emit('recommend:result', {
6188
+ recommend: {
6189
+ results: helper.lastRecommendResults,
6190
+ state: state,
6191
+ },
6192
+ });
6193
+ });
6194
+ };
6195
+
5794
6196
  AlgoliaSearchHelper.prototype._dispatchAlgoliaError = function (
5795
6197
  queryId,
5796
6198
  error
@@ -5810,6 +6212,26 @@
5810
6212
  if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');
5811
6213
  };
5812
6214
 
6215
+ AlgoliaSearchHelper.prototype._dispatchRecommendError = function (
6216
+ queryId,
6217
+ error
6218
+ ) {
6219
+ if (queryId < this._lastRecommendQueryIdReceived) {
6220
+ // Outdated answer
6221
+ return;
6222
+ }
6223
+
6224
+ this._currentNbRecommendQueries -=
6225
+ queryId - this._lastRecommendQueryIdReceived;
6226
+ this._lastRecommendQueryIdReceived = queryId;
6227
+
6228
+ this.emit('error', {
6229
+ error: error,
6230
+ });
6231
+
6232
+ if (this._currentNbRecommendQueries === 0) this.emit('recommendQueueEmpty');
6233
+ };
6234
+
5813
6235
  AlgoliaSearchHelper.prototype.containsRefinement = function (
5814
6236
  query,
5815
6237
  facetFilters,
@@ -5852,6 +6274,27 @@
5852
6274
  }
5853
6275
  };
5854
6276
 
6277
+ AlgoliaSearchHelper.prototype._recommendChange = function (event) {
6278
+ var state = event.state;
6279
+
6280
+ if (state !== this.recommendState) {
6281
+ this.recommendState = state;
6282
+
6283
+ // eslint-disable-next-line no-warning-comments
6284
+ // TODO: emit "change" event when events for Recommend are implemented
6285
+ this.emit('recommend:change', {
6286
+ search: {
6287
+ results: this.lastResults,
6288
+ state: this.state,
6289
+ },
6290
+ recommend: {
6291
+ results: this.lastRecommendResults,
6292
+ state: this.recommendState,
6293
+ },
6294
+ });
6295
+ }
6296
+ };
6297
+
5855
6298
  /**
5856
6299
  * Clears the cache of the underlying Algolia client.
5857
6300
  * @return {AlgoliaSearchHelper} Method is chainable, it returns itself
@@ -5903,10 +6346,11 @@
5903
6346
  * and the SearchParameters that is returned by the call of the
5904
6347
  * parameter function.
5905
6348
  * @param {function} fn SearchParameters -> SearchParameters
6349
+ * @param {function} recommendFn RecommendParameters -> RecommendParameters
5906
6350
  * @return {DerivedHelper} a new DerivedHelper
5907
6351
  */
5908
- AlgoliaSearchHelper.prototype.derive = function (fn) {
5909
- var derivedHelper = new DerivedHelper_1(this, fn);
6352
+ AlgoliaSearchHelper.prototype.derive = function (fn, recommendFn) {
6353
+ var derivedHelper = new DerivedHelper_1(this, fn, recommendFn);
5910
6354
  this.derivedHelpers.push(derivedHelper);
5911
6355
  return derivedHelper;
5912
6356
  };
@@ -6008,6 +6452,13 @@
6008
6452
  */
6009
6453
  algoliasearchHelper.SearchParameters = SearchParameters_1;
6010
6454
 
6455
+ /**
6456
+ * Constructor for the object containing all the parameters for Recommend.
6457
+ * @member module:algoliasearchHelper.RecommendParameters
6458
+ * @type {RecommendParameters}
6459
+ */
6460
+ algoliasearchHelper.RecommendParameters = RecommendParameters_1;
6461
+
6011
6462
  /**
6012
6463
  * Constructor for the object containing the results of the search.
6013
6464
  * @member module:algoliasearchHelper.SearchResults
@@ -8631,7 +9082,7 @@
8631
9082
 
8632
9083
  // Scenario 1: the widget is added for the first time.
8633
9084
  if (!cleanupTimerRef.current) {
8634
- if (!shouldAddWidgetEarly) {
9085
+ if (!shouldSsr) {
8635
9086
  parentIndex.addWidgets([widget]);
8636
9087
  }
8637
9088
  }
@@ -8668,7 +9119,7 @@
8668
9119
  });
8669
9120
  });
8670
9121
  };
8671
- }, [parentIndex, widget, shouldAddWidgetEarly, search, props]);
9122
+ }, [parentIndex, widget, shouldSsr, search, props]);
8672
9123
  if (shouldAddWidgetEarly || (waitingForResultsRef === null || waitingForResultsRef === void 0 ? void 0 : (_waitingForResultsRef = waitingForResultsRef.current) === null || _waitingForResultsRef === void 0 ? void 0 : _waitingForResultsRef.status) === 'pending') {
8673
9124
  parentIndex.addWidgets([widget]);
8674
9125
  }
@@ -9296,7 +9747,8 @@
9296
9747
  return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
9297
9748
  }, _typeof$g(obj);
9298
9749
  }
9299
- var _excluded$3 = ["initialSearchParameters"];
9750
+ var _excluded$3 = ["initialSearchParameters"],
9751
+ _excluded2$1 = ["initialRecommendParameters"];
9300
9752
  function ownKeys$d(object, enumerableOnly) {
9301
9753
  var keys = Object.keys(object);
9302
9754
  if (Object.getOwnPropertySymbols) {
@@ -9408,6 +9860,7 @@
9408
9860
  */
9409
9861
  function privateHelperSetState(helper, _ref) {
9410
9862
  var state = _ref.state,
9863
+ recommendState = _ref.recommendState,
9411
9864
  isPageReset = _ref.isPageReset,
9412
9865
  _uiState = _ref._uiState;
9413
9866
  if (state !== helper.state) {
@@ -9419,7 +9872,14 @@
9419
9872
  _uiState: _uiState
9420
9873
  });
9421
9874
  }
9875
+ if (recommendState !== helper.recommendState) {
9876
+ helper.recommendState = recommendState;
9877
+
9878
+ // eslint-disable-next-line no-warning-comments
9879
+ // TODO: emit "change" event when events for Recommend are implemented
9880
+ }
9422
9881
  }
9882
+
9423
9883
  function getLocalWidgetsUiState(widgets, widgetStateOptions) {
9424
9884
  var initialUiState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
9425
9885
  return widgets.reduce(function (uiState, widget) {
@@ -9438,15 +9898,26 @@
9438
9898
  function getLocalWidgetsSearchParameters(widgets, widgetSearchParametersOptions) {
9439
9899
  var initialSearchParameters = widgetSearchParametersOptions.initialSearchParameters,
9440
9900
  rest = _objectWithoutProperties$3(widgetSearchParametersOptions, _excluded$3);
9441
- return widgets.filter(function (widget) {
9442
- return !isIndexWidget(widget);
9443
- }).reduce(function (state, widget) {
9444
- if (!widget.getWidgetSearchParameters) {
9901
+ return widgets.reduce(function (state, widget) {
9902
+ if (!widget.getWidgetSearchParameters || isIndexWidget(widget)) {
9445
9903
  return state;
9446
9904
  }
9905
+ if (widget.dependsOn === 'search' && widget.getWidgetParameters) {
9906
+ return widget.getWidgetParameters(state, rest);
9907
+ }
9447
9908
  return widget.getWidgetSearchParameters(state, rest);
9448
9909
  }, initialSearchParameters);
9449
9910
  }
9911
+ function getLocalWidgetsRecommendParameters(widgets, widgetRecommendParametersOptions) {
9912
+ var initialRecommendParameters = widgetRecommendParametersOptions.initialRecommendParameters,
9913
+ rest = _objectWithoutProperties$3(widgetRecommendParametersOptions, _excluded2$1);
9914
+ return widgets.reduce(function (state, widget) {
9915
+ if (!isIndexWidget(widget) && widget.dependsOn === 'recommend' && widget.getWidgetParameters) {
9916
+ return widget.getWidgetParameters(state, rest);
9917
+ }
9918
+ return state;
9919
+ }, initialRecommendParameters);
9920
+ }
9450
9921
  function resetPageFromWidgets(widgets) {
9451
9922
  var indexWidgets = widgets.filter(isIndexWidget);
9452
9923
  if (indexWidgets.length === 0) {
@@ -9456,6 +9927,7 @@
9456
9927
  var widgetHelper = widget.getHelper();
9457
9928
  privateHelperSetState(widgetHelper, {
9458
9929
  state: widgetHelper.state.resetPage(),
9930
+ recommendState: widgetHelper.recommendState,
9459
9931
  isPageReset: true
9460
9932
  });
9461
9933
  resetPageFromWidgets(widget.getWidgets());
@@ -9551,6 +10023,10 @@
9551
10023
  uiState: localUiState,
9552
10024
  initialSearchParameters: helper.state
9553
10025
  }),
10026
+ recommendState: getLocalWidgetsRecommendParameters(localWidgets, {
10027
+ uiState: localUiState,
10028
+ initialRecommendParameters: helper.recommendState
10029
+ }),
9554
10030
  _uiState: localUiState
9555
10031
  });
9556
10032
 
@@ -9647,11 +10123,16 @@
9647
10123
  index: indexName
9648
10124
  })
9649
10125
  });
10126
+ var recommendParameters = getLocalWidgetsRecommendParameters(localWidgets, {
10127
+ uiState: localUiState,
10128
+ initialRecommendParameters: new algoliasearchHelper_1.RecommendParameters()
10129
+ });
9650
10130
 
9651
10131
  // This Helper is only used for state management we do not care about the
9652
10132
  // `searchClient`. Only the "main" Helper created at the `InstantSearch`
9653
10133
  // level is aware of the client.
9654
10134
  helper = algoliasearchHelper_1({}, parameters.index, parameters);
10135
+ helper.recommendState = recommendParameters;
9655
10136
 
9656
10137
  // We forward the call to `search` to the "main" instance of the Helper
9657
10138
  // which is responsible for managing the queries (it's the only one that is
@@ -9682,6 +10163,8 @@
9682
10163
  };
9683
10164
  derivedHelper = mainHelper.derive(function () {
9684
10165
  return mergeSearchParameters.apply(void 0, [mainHelper.state].concat(_toConsumableArray$1(resolveSearchParameters(_this3))));
10166
+ }, function () {
10167
+ return _this3.getHelper().recommendState;
9685
10168
  });
9686
10169
  var indexInitialResults = (_instantSearchInstanc = instantSearchInstance._initialResults) === null || _instantSearchInstanc === void 0 ? void 0 : _instantSearchInstanc[this.getIndexId()];
9687
10170
  if (indexInitialResults) {
@@ -9724,6 +10207,21 @@
9724
10207
  lastValidSearchParameters = results === null || results === void 0 ? void 0 : results._state;
9725
10208
  });
9726
10209
 
10210
+ // eslint-disable-next-line no-warning-comments
10211
+ // TODO: listen to "result" event when events for Recommend are implemented
10212
+ derivedHelper.on('recommend:result', function (_ref5) {
10213
+ var recommend = _ref5.recommend;
10214
+ // The index does not render the results it schedules a new render
10215
+ // to let all the other indices emit their own results. It allows us to
10216
+ // run the render process in one pass.
10217
+ instantSearchInstance.scheduleRender();
10218
+
10219
+ // the derived helper is the one which actually searches, but the helper
10220
+ // which is exposed e.g. via instance.helper, doesn't search, and thus
10221
+ // does not have access to lastRecommendResults.
10222
+ helper.lastRecommendResults = recommend.results;
10223
+ });
10224
+
9727
10225
  // We compute the render state before calling `init` in a separate loop
9728
10226
  // to construct the whole render state object that is then passed to
9729
10227
  // `init`.
@@ -9770,9 +10268,9 @@
9770
10268
  instantSearchInstance.scheduleRender();
9771
10269
  }
9772
10270
  },
9773
- render: function render(_ref5) {
10271
+ render: function render(_ref6) {
9774
10272
  var _this4 = this;
9775
- var instantSearchInstance = _ref5.instantSearchInstance;
10273
+ var instantSearchInstance = _ref6.instantSearchInstance;
9776
10274
  // we can't attach a listener to the error event of search, as the error
9777
10275
  // then would no longer be thrown for global handlers.
9778
10276
  if (instantSearchInstance.status === 'error' && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
@@ -9782,6 +10280,14 @@
9782
10280
  // We only render index widgets if there are no results.
9783
10281
  // This makes sure `render` is never called with `results` being `null`.
9784
10282
  var widgetsToRender = this.getResults() ? localWidgets : localWidgets.filter(isIndexWidget);
10283
+ widgetsToRender = widgetsToRender.filter(function (widget) {
10284
+ if (!widget.shouldRender) {
10285
+ return true;
10286
+ }
10287
+ return widget.shouldRender({
10288
+ instantSearchInstance: instantSearchInstance
10289
+ });
10290
+ });
9785
10291
  widgetsToRender.forEach(function (widget) {
9786
10292
  if (widget.getRenderState) {
9787
10293
  var renderState = widget.getRenderState(instantSearchInstance.renderState[_this4.getIndexId()] || {}, createRenderArgs(instantSearchInstance, _this4));
@@ -9839,8 +10345,8 @@
9839
10345
  getWidgetState: function getWidgetState(uiState) {
9840
10346
  return this.getWidgetUiState(uiState);
9841
10347
  },
9842
- getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref6) {
9843
- var uiState = _ref6.uiState;
10348
+ getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref7) {
10349
+ var uiState = _ref7.uiState;
9844
10350
  return getLocalWidgetsSearchParameters(localWidgets, {
9845
10351
  uiState: uiState,
9846
10352
  initialSearchParameters: searchParameters
@@ -9860,10 +10366,10 @@
9860
10366
  }
9861
10367
  };
9862
10368
  };
9863
- function storeRenderState(_ref7) {
9864
- var renderState = _ref7.renderState,
9865
- instantSearchInstance = _ref7.instantSearchInstance,
9866
- parent = _ref7.parent;
10369
+ function storeRenderState(_ref8) {
10370
+ var renderState = _ref8.renderState,
10371
+ instantSearchInstance = _ref8.instantSearchInstance,
10372
+ parent = _ref8.parent;
9867
10373
  var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
9868
10374
  instantSearchInstance.renderState = _objectSpread$d(_objectSpread$d({}, instantSearchInstance.renderState), {}, _defineProperty$d({}, parentIndexName, _objectSpread$d(_objectSpread$d({}, instantSearchInstance.renderState[parentIndexName]), renderState)));
9869
10375
  }
@@ -12205,7 +12711,7 @@
12205
12711
  };
12206
12712
  }
12207
12713
 
12208
- var version$3 = '4.66.0';
12714
+ var version$3 = '4.67.0';
12209
12715
 
12210
12716
  function _typeof$o(obj) {
12211
12717
  "@babel/helpers - typeof";
@@ -12699,7 +13205,7 @@
12699
13205
  // under the hood, we have a different implementation. It should be
12700
13206
  // completely transparent for the rest of the codebase. Only this module
12701
13207
  // is impacted.
12702
- return mainHelper.searchOnlyWithDerivedHelpers();
13208
+ return mainHelper.searchOnlyWithDerivedHelpers() && mainHelper.recommend();
12703
13209
  };
12704
13210
  if (this._searchFunction) {
12705
13211
  // this client isn't used to actually search, but required for the helper
@@ -14893,6 +15399,8 @@
14893
15399
  if (!escapeHTML) {
14894
15400
  return state;
14895
15401
  }
15402
+
15403
+ // @MAJOR: set this globally, not in the Hits widget to allow Hits to be conditionally used
14896
15404
  return state.setQueryParameters(TAG_PLACEHOLDER);
14897
15405
  }
14898
15406
  };
@@ -15135,7 +15643,7 @@
15135
15643
  }, _typeof$y(obj);
15136
15644
  }
15137
15645
  var _excluded$9 = ["page"],
15138
- _excluded2$1 = ["clickAnalytics", "userToken"];
15646
+ _excluded2$2 = ["clickAnalytics", "userToken"];
15139
15647
  function ownKeys$s(object, enumerableOnly) {
15140
15648
  var keys = Object.keys(object);
15141
15649
  if (Object.getOwnPropertySymbols) {
@@ -15251,7 +15759,7 @@
15251
15759
  var _ref2 = state || {},
15252
15760
  clickAnalytics = _ref2.clickAnalytics,
15253
15761
  userToken = _ref2.userToken,
15254
- rest = _objectWithoutProperties$9(_ref2, _excluded2$1);
15762
+ rest = _objectWithoutProperties$9(_ref2, _excluded2$2);
15255
15763
  return rest;
15256
15764
  }
15257
15765
  function getInMemoryCache() {
@@ -15472,6 +15980,7 @@
15472
15980
  var uiState = _ref10.uiState;
15473
15981
  var widgetSearchParameters = searchParameters;
15474
15982
  if (escapeHTML) {
15983
+ // @MAJOR: set this globally, not in the InfiniteHits widget to allow InfiniteHits to be conditionally used
15475
15984
  widgetSearchParameters = searchParameters.setQueryParameters(TAG_PLACEHOLDER);
15476
15985
  }
15477
15986
 
@@ -17189,7 +17698,7 @@
17189
17698
  }, _typeof$F(obj);
17190
17699
  }
17191
17700
  var _excluded$b = ["name", "escapedValue"],
17192
- _excluded2$2 = ["escapedValue", "value"];
17701
+ _excluded2$3 = ["escapedValue", "value"];
17193
17702
  function ownKeys$y(object, enumerableOnly) {
17194
17703
  var keys = Object.keys(object);
17195
17704
  if (Object.getOwnPropertySymbols) {
@@ -17374,7 +17883,7 @@
17374
17883
  var normalizedFacetValues = transformItems(facetValues.map(function (_ref3) {
17375
17884
  var escapedValue = _ref3.escapedValue,
17376
17885
  value = _ref3.value,
17377
- item = _objectWithoutProperties$b(_ref3, _excluded2$2);
17886
+ item = _objectWithoutProperties$b(_ref3, _excluded2$3);
17378
17887
  return _objectSpread$y(_objectSpread$y({}, item), {}, {
17379
17888
  value: escapedValue,
17380
17889
  label: value
@@ -19538,7 +20047,7 @@
19538
20047
  }
19539
20048
 
19540
20049
  var _excluded$p = ["escapeHTML", "transformItems", "hitComponent"],
19541
- _excluded2$3 = ["hit", "index"];
20050
+ _excluded2$4 = ["hit", "index"];
19542
20051
  // @MAJOR: Move default hit component back to the UI library
19543
20052
  // once flavour specificities are erased
19544
20053
  function DefaultHitComponent(_ref) {
@@ -19570,7 +20079,7 @@
19570
20079
  var itemComponent = function itemComponent(_ref3) {
19571
20080
  var hit = _ref3.hit,
19572
20081
  index = _ref3.index,
19573
- itemProps = _objectWithoutProperties$c(_ref3, _excluded2$3);
20082
+ itemProps = _objectWithoutProperties$c(_ref3, _excluded2$4);
19574
20083
  return /*#__PURE__*/React__default.createElement("li", _extends$1({
19575
20084
  key: hit.objectID
19576
20085
  }, itemProps), /*#__PURE__*/React__default.createElement(HitComponent, {
@@ -19818,7 +20327,7 @@
19818
20327
  }
19819
20328
 
19820
20329
  var _excluded$w = ["pages", "currentPage", "nbPages", "isFirstPage", "isLastPage", "showFirst", "showPrevious", "showNext", "showLast", "createURL", "onNavigate", "translations", "classNames"],
19821
- _excluded2$4 = ["isDisabled", "className", "classNames", "href", "onClick"];
20330
+ _excluded2$5 = ["isDisabled", "className", "classNames", "href", "onClick"];
19822
20331
  function Pagination(_ref) {
19823
20332
  var pages = _ref.pages,
19824
20333
  currentPage = _ref.currentPage,
@@ -19909,7 +20418,7 @@
19909
20418
  classNames = _ref2.classNames,
19910
20419
  href = _ref2.href,
19911
20420
  _onClick = _ref2.onClick,
19912
- props = _objectWithoutProperties$c(_ref2, _excluded2$4);
20421
+ props = _objectWithoutProperties$c(_ref2, _excluded2$5);
19913
20422
  if (isDisabled) {
19914
20423
  return /*#__PURE__*/React__default.createElement("li", {
19915
20424
  className: cx('ais-Pagination-item', classNames.item, 'ais-Pagination-item--disabled', classNames.disabledItem, className)
@@ -20185,7 +20694,7 @@
20185
20694
  translations = _ref.translations,
20186
20695
  props = _objectWithoutProperties$c(_ref, _excluded$B);
20187
20696
  return /*#__PURE__*/React__default.createElement("div", _extends$1({}, props, {
20188
- className: cx('ais-RefinementList', classNames.root, !canRefine && cx('ais-RefinementList--noRefinement', classNames.noRefinementRoot), className)
20697
+ className: cx('ais-RefinementList', classNames.root, items.length === 0 && cx('ais-RefinementList--noRefinement', classNames.noRefinementRoot), className)
20189
20698
  }), searchBox && /*#__PURE__*/React__default.createElement("div", {
20190
20699
  className: cx('ais-RefinementList-searchBox', classNames.searchBox)
20191
20700
  }, searchBox), noResults ? /*#__PURE__*/React__default.createElement("div", {