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.
@@ -48,7 +48,7 @@ var RawHtml = /*#__PURE__*/function (_Component) {
48
48
  var fragment = new DocumentFragment();
49
49
  var root = document.createElement('div');
50
50
  root.innerHTML = this.props.content;
51
- this.nodes = _toConsumableArray(root.children);
51
+ this.nodes = _toConsumableArray(root.childNodes);
52
52
  this.nodes.forEach(function (node) {
53
53
  return fragment.appendChild(node);
54
54
  });
@@ -58,8 +58,17 @@ var RawHtml = /*#__PURE__*/function (_Component) {
58
58
  key: "componentWillUnmount",
59
59
  value: function componentWillUnmount() {
60
60
  this.nodes.forEach(function (node) {
61
- return node.outerHTML = '';
61
+ if (node instanceof Element) {
62
+ node.outerHTML = '';
63
+ return;
64
+ }
65
+ node.nodeValue = '';
62
66
  });
67
+ // if there is one TextNode first and one TextNode last, the
68
+ // last one's nodeValue will be assigned to the first.
69
+ if (this.nodes[0].nodeValue) {
70
+ this.nodes[0].nodeValue = '';
71
+ }
63
72
  }
64
73
  }, {
65
74
  key: "render",
@@ -48,6 +48,7 @@ var connectHits = function connectHits(renderFn) {
48
48
  });
49
49
  },
50
50
  getWidgetRenderState: function getWidgetRenderState(_ref2) {
51
+ var _results$renderingCon, _results$renderingCon2, _results$renderingCon3;
51
52
  var results = _ref2.results,
52
53
  helper = _ref2.helper,
53
54
  instantSearchInstance = _ref2.instantSearchInstance;
@@ -73,6 +74,7 @@ var connectHits = function connectHits(renderFn) {
73
74
  return {
74
75
  hits: [],
75
76
  results: undefined,
77
+ banner: undefined,
76
78
  sendEvent: sendEvent,
77
79
  bindEvent: bindEvent,
78
80
  widgetParams: widgetParams
@@ -86,9 +88,11 @@ var connectHits = function connectHits(renderFn) {
86
88
  var transformedHits = transformItems(hitsWithAbsolutePositionAndQueryID, {
87
89
  results: results
88
90
  });
91
+ 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];
89
92
  return {
90
93
  hits: transformedHits,
91
94
  results: results,
95
+ banner: banner,
92
96
  sendEvent: sendEvent,
93
97
  bindEvent: bindEvent,
94
98
  widgetParams: widgetParams
@@ -392,7 +392,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
392
392
  // under the hood, we have a different implementation. It should be
393
393
  // completely transparent for the rest of the codebase. Only this module
394
394
  // is impacted.
395
- return mainHelper.searchOnlyWithDerivedHelpers();
395
+ return mainHelper.searchOnlyWithDerivedHelpers() && mainHelper.recommend();
396
396
  };
397
397
  if (this._searchFunction) {
398
398
  // this client isn't used to actually search, but required for the helper
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = '4.66.1';
7
+ var _default = '4.68.0';
8
8
  exports.default = _default;
@@ -43,7 +43,8 @@ var renderer = function renderer(_ref) {
43
43
  instantSearchInstance = _ref2.instantSearchInstance,
44
44
  insights = _ref2.insights,
45
45
  bindEvent = _ref2.bindEvent,
46
- sendEvent = _ref2.sendEvent;
46
+ sendEvent = _ref2.sendEvent,
47
+ banner = _ref2.banner;
47
48
  if (isFirstRendering) {
48
49
  renderState.templateProps = (0, _templating.prepareTemplateProps)({
49
50
  defaultTemplates: _defaultTemplates.default,
@@ -61,7 +62,8 @@ var renderer = function renderer(_ref) {
61
62
  return (0, _preact.h)(_Template.default, _extends({}, renderState.templateProps, {
62
63
  rootProps: rootProps,
63
64
  templateKey: "empty",
64
- data: results
65
+ data: results,
66
+ rootTagName: "fragment"
65
67
  }));
66
68
  };
67
69
 
@@ -94,12 +96,21 @@ var renderer = function renderer(_ref) {
94
96
  sendEvent: sendEvent
95
97
  }));
96
98
  };
99
+ var bannerComponent = function bannerComponent(props) {
100
+ return (0, _preact.h)(_Template.default, _extends({}, renderState.templateProps, {
101
+ templateKey: "banner",
102
+ data: props,
103
+ rootTagName: "fragment"
104
+ }));
105
+ };
97
106
  (0, _preact.render)((0, _preact.h)(Hits, {
98
107
  hits: receivedHits,
99
108
  itemComponent: itemComponent,
100
109
  sendEvent: sendEvent,
101
110
  classNames: cssClasses,
102
- emptyComponent: emptyComponent
111
+ emptyComponent: emptyComponent,
112
+ banner: banner,
113
+ bannerComponent: templates.banner ? bannerComponent : undefined
103
114
  }), containerNode);
104
115
  };
105
116
  };
@@ -7,7 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.default = void 0;
8
8
  var _algoliasearchHelper = _interopRequireDefault(require("algoliasearch-helper"));
9
9
  var _utils = require("../../lib/utils");
10
- var _excluded = ["initialSearchParameters"];
10
+ var _excluded = ["initialSearchParameters"],
11
+ _excluded2 = ["initialRecommendParameters"];
11
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
13
14
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -32,6 +33,7 @@ var withUsage = (0, _utils.createDocumentationMessageGenerator)({
32
33
  */
33
34
  function privateHelperSetState(helper, _ref) {
34
35
  var state = _ref.state,
36
+ recommendState = _ref.recommendState,
35
37
  isPageReset = _ref.isPageReset,
36
38
  _uiState = _ref._uiState;
37
39
  if (state !== helper.state) {
@@ -43,7 +45,14 @@ function privateHelperSetState(helper, _ref) {
43
45
  _uiState: _uiState
44
46
  });
45
47
  }
48
+ if (recommendState !== helper.recommendState) {
49
+ helper.recommendState = recommendState;
50
+
51
+ // eslint-disable-next-line no-warning-comments
52
+ // TODO: emit "change" event when events for Recommend are implemented
53
+ }
46
54
  }
55
+
47
56
  function getLocalWidgetsUiState(widgets, widgetStateOptions) {
48
57
  var initialUiState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
49
58
  return widgets.reduce(function (uiState, widget) {
@@ -62,15 +71,26 @@ function getLocalWidgetsUiState(widgets, widgetStateOptions) {
62
71
  function getLocalWidgetsSearchParameters(widgets, widgetSearchParametersOptions) {
63
72
  var initialSearchParameters = widgetSearchParametersOptions.initialSearchParameters,
64
73
  rest = _objectWithoutProperties(widgetSearchParametersOptions, _excluded);
65
- return widgets.filter(function (widget) {
66
- return !(0, _utils.isIndexWidget)(widget);
67
- }).reduce(function (state, widget) {
68
- if (!widget.getWidgetSearchParameters) {
74
+ return widgets.reduce(function (state, widget) {
75
+ if (!widget.getWidgetSearchParameters || (0, _utils.isIndexWidget)(widget)) {
69
76
  return state;
70
77
  }
78
+ if (widget.dependsOn === 'search' && widget.getWidgetParameters) {
79
+ return widget.getWidgetParameters(state, rest);
80
+ }
71
81
  return widget.getWidgetSearchParameters(state, rest);
72
82
  }, initialSearchParameters);
73
83
  }
84
+ function getLocalWidgetsRecommendParameters(widgets, widgetRecommendParametersOptions) {
85
+ var initialRecommendParameters = widgetRecommendParametersOptions.initialRecommendParameters,
86
+ rest = _objectWithoutProperties(widgetRecommendParametersOptions, _excluded2);
87
+ return widgets.reduce(function (state, widget) {
88
+ if (!(0, _utils.isIndexWidget)(widget) && widget.dependsOn === 'recommend' && widget.getWidgetParameters) {
89
+ return widget.getWidgetParameters(state, rest);
90
+ }
91
+ return state;
92
+ }, initialRecommendParameters);
93
+ }
74
94
  function resetPageFromWidgets(widgets) {
75
95
  var indexWidgets = widgets.filter(_utils.isIndexWidget);
76
96
  if (indexWidgets.length === 0) {
@@ -80,6 +100,7 @@ function resetPageFromWidgets(widgets) {
80
100
  var widgetHelper = widget.getHelper();
81
101
  privateHelperSetState(widgetHelper, {
82
102
  state: widgetHelper.state.resetPage(),
103
+ recommendState: widgetHelper.recommendState,
83
104
  isPageReset: true
84
105
  });
85
106
  resetPageFromWidgets(widget.getWidgets());
@@ -138,9 +159,18 @@ var index = function index(widgetParams) {
138
159
  },
139
160
  getScopedResults: function getScopedResults() {
140
161
  var widgetParent = this.getParent();
141
-
142
- // If the widget is the root, we consider itself as the only sibling.
143
- var widgetSiblings = widgetParent ? widgetParent.getWidgets() : [this];
162
+ var widgetSiblings;
163
+ if (widgetParent) {
164
+ widgetSiblings = widgetParent.getWidgets();
165
+ } else if (indexName.length === 0) {
166
+ // The widget is the root but has no index name:
167
+ // we resolve results from its children index widgets
168
+ widgetSiblings = this.getWidgets();
169
+ } else {
170
+ // The widget is the root and has an index name:
171
+ // we consider itself as the only sibling
172
+ widgetSiblings = [this];
173
+ }
144
174
  return resolveScopedResultsFromWidgets(widgetSiblings);
145
175
  },
146
176
  getParent: function getParent() {
@@ -175,6 +205,10 @@ var index = function index(widgetParams) {
175
205
  uiState: localUiState,
176
206
  initialSearchParameters: helper.state
177
207
  }),
208
+ recommendState: getLocalWidgetsRecommendParameters(localWidgets, {
209
+ uiState: localUiState,
210
+ initialRecommendParameters: helper.recommendState
211
+ }),
178
212
  _uiState: localUiState
179
213
  });
180
214
 
@@ -271,11 +305,16 @@ var index = function index(widgetParams) {
271
305
  index: indexName
272
306
  })
273
307
  });
308
+ var recommendParameters = getLocalWidgetsRecommendParameters(localWidgets, {
309
+ uiState: localUiState,
310
+ initialRecommendParameters: new _algoliasearchHelper.default.RecommendParameters()
311
+ });
274
312
 
275
313
  // This Helper is only used for state management we do not care about the
276
314
  // `searchClient`. Only the "main" Helper created at the `InstantSearch`
277
315
  // level is aware of the client.
278
316
  helper = (0, _algoliasearchHelper.default)({}, parameters.index, parameters);
317
+ helper.recommendState = recommendParameters;
279
318
 
280
319
  // We forward the call to `search` to the "main" instance of the Helper
281
320
  // which is responsible for managing the queries (it's the only one that is
@@ -306,6 +345,8 @@ var index = function index(widgetParams) {
306
345
  };
307
346
  derivedHelper = mainHelper.derive(function () {
308
347
  return _utils.mergeSearchParameters.apply(void 0, [mainHelper.state].concat(_toConsumableArray((0, _utils.resolveSearchParameters)(_this3))));
348
+ }, function () {
349
+ return _this3.getHelper().recommendState;
309
350
  });
310
351
  var indexInitialResults = (_instantSearchInstanc = instantSearchInstance._initialResults) === null || _instantSearchInstanc === void 0 ? void 0 : _instantSearchInstanc[this.getIndexId()];
311
352
  if (indexInitialResults) {
@@ -354,6 +395,21 @@ var index = function index(widgetParams) {
354
395
  lastValidSearchParameters = results === null || results === void 0 ? void 0 : results._state;
355
396
  });
356
397
 
398
+ // eslint-disable-next-line no-warning-comments
399
+ // TODO: listen to "result" event when events for Recommend are implemented
400
+ derivedHelper.on('recommend:result', function (_ref5) {
401
+ var recommend = _ref5.recommend;
402
+ // The index does not render the results it schedules a new render
403
+ // to let all the other indices emit their own results. It allows us to
404
+ // run the render process in one pass.
405
+ instantSearchInstance.scheduleRender();
406
+
407
+ // the derived helper is the one which actually searches, but the helper
408
+ // which is exposed e.g. via instance.helper, doesn't search, and thus
409
+ // does not have access to lastRecommendResults.
410
+ helper.lastRecommendResults = recommend.results;
411
+ });
412
+
357
413
  // We compute the render state before calling `init` in a separate loop
358
414
  // to construct the whole render state object that is then passed to
359
415
  // `init`.
@@ -404,9 +460,9 @@ var index = function index(widgetParams) {
404
460
  instantSearchInstance.scheduleRender();
405
461
  }
406
462
  },
407
- render: function render(_ref5) {
463
+ render: function render(_ref6) {
408
464
  var _this4 = this;
409
- var instantSearchInstance = _ref5.instantSearchInstance;
465
+ var instantSearchInstance = _ref6.instantSearchInstance;
410
466
  // we can't attach a listener to the error event of search, as the error
411
467
  // then would no longer be thrown for global handlers.
412
468
  if (instantSearchInstance.status === 'error' && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
@@ -416,6 +472,14 @@ var index = function index(widgetParams) {
416
472
  // We only render index widgets if there are no results.
417
473
  // This makes sure `render` is never called with `results` being `null`.
418
474
  var widgetsToRender = this.getResults() ? localWidgets : localWidgets.filter(_utils.isIndexWidget);
475
+ widgetsToRender = widgetsToRender.filter(function (widget) {
476
+ if (!widget.shouldRender) {
477
+ return true;
478
+ }
479
+ return widget.shouldRender({
480
+ instantSearchInstance: instantSearchInstance
481
+ });
482
+ });
419
483
  widgetsToRender.forEach(function (widget) {
420
484
  if (widget.getRenderState) {
421
485
  var renderState = widget.getRenderState(instantSearchInstance.renderState[_this4.getIndexId()] || {}, (0, _utils.createRenderArgs)(instantSearchInstance, _this4));
@@ -474,8 +538,8 @@ var index = function index(widgetParams) {
474
538
  process.env.NODE_ENV === 'development' ? (0, _utils.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.') : void 0;
475
539
  return this.getWidgetUiState(uiState);
476
540
  },
477
- getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref6) {
478
- var uiState = _ref6.uiState;
541
+ getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref7) {
542
+ var uiState = _ref7.uiState;
479
543
  return getLocalWidgetsSearchParameters(localWidgets, {
480
544
  uiState: uiState,
481
545
  initialSearchParameters: searchParameters
@@ -497,10 +561,10 @@ var index = function index(widgetParams) {
497
561
  };
498
562
  var _default = index;
499
563
  exports.default = _default;
500
- function storeRenderState(_ref7) {
501
- var renderState = _ref7.renderState,
502
- instantSearchInstance = _ref7.instantSearchInstance,
503
- parent = _ref7.parent;
564
+ function storeRenderState(_ref8) {
565
+ var renderState = _ref8.renderState,
566
+ instantSearchInstance = _ref8.instantSearchInstance,
567
+ parent = _ref8.parent;
504
568
  var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
505
569
  instantSearchInstance.renderState = _objectSpread(_objectSpread({}, instantSearchInstance.renderState), {}, _defineProperty({}, parentIndexName, _objectSpread(_objectSpread({}, instantSearchInstance.renderState[parentIndexName]), renderState)));
506
570
  }
@@ -15,6 +15,7 @@ import type { InsightsMethodMap as InsightsMethodMap_2 } from 'search-insights';
15
15
  import type * as Places from 'places.js';
16
16
  import type { PlainSearchParameters } from 'algoliasearch-helper';
17
17
  import { default as qs_2 } from 'qs';
18
+ import type { RecommendParameters } from 'algoliasearch-helper';
18
19
  import { SearchClient } from 'algoliasearch-helper/types/algoliasearch.js';
19
20
  import { SearchOptions } from 'algoliasearch-helper/types/algoliasearch.js';
20
21
  import type { SearchParameters } from 'algoliasearch-helper';
@@ -242,7 +243,7 @@ declare type AtLeastOne<TTarget, TMapped = {
242
243
  [Key in keyof TTarget]: Pick<TTarget, Key>;
243
244
  }> = Partial<TTarget> & TMapped[keyof TMapped];
244
245
 
245
- declare type AugmentedWidget<TWidgetFactory extends AnyWidgetFactory, TOverriddenKeys extends keyof Widget = 'init' | 'render' | 'dispose'> = Omit<ReturnType<TWidgetFactory>, TOverriddenKeys> & Pick<Required<Widget>, TOverriddenKeys>;
246
+ declare type AugmentedWidget<TWidgetFactory extends AnyWidgetFactory, TOverriddenKeys extends keyof Widget = 'init' | 'render' | 'dispose'> = Omit<ReturnType<TWidgetFactory>, TOverriddenKeys | 'dependsOn' | 'getWidgetParameters'> & Pick<Required<Widget>, TOverriddenKeys>;
246
247
 
247
248
  declare type AutocompleteConnector = Connector<AutocompleteWidgetDescription, AutocompleteConnectorParams>;
248
249
 
@@ -302,6 +303,8 @@ declare type AutocompleteWidgetDescription = {
302
303
  };
303
304
  };
304
305
 
306
+ declare type Banner = NonNullable<NonNullable<Required<SearchResults<Hit>['renderingContent']>>['widgets']['banners']>[number];
307
+
305
308
  declare type BaseHit = Record<string, unknown>;
306
309
 
307
310
  declare type BindEventForHits = BuiltInBindEventForHits & CustomBindEventForHits;
@@ -1993,6 +1996,10 @@ declare type HitsRenderState<THit extends BaseHit = BaseHit> = {
1993
1996
  * The response from the Algolia API.
1994
1997
  */
1995
1998
  results?: SearchResults<Hit<THit>>;
1999
+ /**
2000
+ * The banner to display above the hits.
2001
+ */
2002
+ banner?: Banner;
1996
2003
  /**
1997
2004
  * Sends an event to the Insights middleware.
1998
2005
  */
@@ -2019,6 +2026,13 @@ declare type HitsTemplates = Partial<{
2019
2026
  /** @deprecated the index in the hits array, use __position instead, which is the absolute position */
2020
2027
  __hitIndex: number;
2021
2028
  }>;
2029
+ /**
2030
+ * Template to use for the banner.
2031
+ */
2032
+ banner: Template<{
2033
+ banner: Required<HitsRenderState['banner']>;
2034
+ className: string;
2035
+ }>;
2022
2036
  }>;
2023
2037
 
2024
2038
  declare type HitsWidget = WidgetFactory<HitsWidgetDescription & {
@@ -4007,6 +4021,13 @@ declare type Read<THit extends BaseHit> = ({ state, }: {
4007
4021
  state: PlainSearchParameters;
4008
4022
  }) => InfiniteHitsCachedHits<THit> | null;
4009
4023
 
4024
+ declare type RecommendWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
4025
+ dependsOn?: 'recommend';
4026
+ getWidgetParameters: (state: RecommendParameters, widgetParametersOptions: {
4027
+ uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
4028
+ }) => RecommendParameters;
4029
+ };
4030
+
4010
4031
  declare type ReconfigurableOptions = Places.ReconfigurableOptions;
4011
4032
 
4012
4033
  /**
@@ -4517,7 +4538,7 @@ declare type RequiredUiStateLifeCycle<TWidgetDescription extends WidgetDescripti
4517
4538
  getWidgetSearchParameters: (state: SearchParameters, widgetSearchParametersOptions: {
4518
4539
  uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
4519
4540
  }) => SearchParameters;
4520
- };
4541
+ } & (SearchWidgetLifeCycle<TWidgetDescription> | RecommendWidgetLifeCycle<TWidgetDescription>);
4521
4542
 
4522
4543
  declare type RequiredWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
4523
4544
  /**
@@ -4528,6 +4549,10 @@ declare type RequiredWidgetLifeCycle<TWidgetDescription extends WidgetDescriptio
4528
4549
  * Called once before the first search.
4529
4550
  */
4530
4551
  init?: (options: InitOptions) => void;
4552
+ /**
4553
+ * Whether `render` should be called
4554
+ */
4555
+ shouldRender?: (options: ShouldRenderOptions) => boolean;
4531
4556
  /**
4532
4557
  * Called after each search response has been received.
4533
4558
  */
@@ -4843,6 +4868,13 @@ declare type SearchBoxWidgetParams = {
4843
4868
  queryHook?: (query: string, hook: (value: string) => void) => void;
4844
4869
  };
4845
4870
 
4871
+ declare type SearchWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
4872
+ dependsOn?: 'search';
4873
+ getWidgetParameters?: (state: SearchParameters, widgetParametersOptions: {
4874
+ uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
4875
+ }) => SearchParameters;
4876
+ };
4877
+
4846
4878
  declare type SendEvent = (...args: [InsightsEvent] | [string, string, string?]) => void;
4847
4879
 
4848
4880
  declare type SendEventForFacet = BuiltInSendEventForFacet & CustomSendEventForFacet;
@@ -4869,6 +4901,10 @@ declare type SharedRenderOptions = {
4869
4901
  createURL: (nextState: SearchParameters | ((state: IndexUiState) => IndexUiState)) => string;
4870
4902
  };
4871
4903
 
4904
+ declare type ShouldRenderOptions = {
4905
+ instantSearchInstance: InstantSearch;
4906
+ };
4907
+
4872
4908
  declare function simpleStateMapping<TUiState extends UiState = UiState>(): StateMapping<TUiState, TUiState>;
4873
4909
 
4874
4910
  declare function singleIndexStateMapping<TUiState extends UiState = UiState>(indexName: keyof TUiState): StateMapping<TUiState, TUiState[typeof indexName]>;