instantsearch.js 4.66.0 → 4.67.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.
@@ -102,6 +102,8 @@ var connectHits = function connectHits(renderFn) {
102
102
  if (!escapeHTML) {
103
103
  return state;
104
104
  }
105
+
106
+ // @MAJOR: set this globally, not in the Hits widget to allow Hits to be conditionally used
105
107
  return state.setQueryParameters(TAG_PLACEHOLDER);
106
108
  }
107
109
  };
@@ -250,6 +250,7 @@ var connectInfiniteHits = function connectInfiniteHits(renderFn) {
250
250
  var uiState = _ref10.uiState;
251
251
  var widgetSearchParameters = searchParameters;
252
252
  if (escapeHTML) {
253
+ // @MAJOR: set this globally, not in the InfiniteHits widget to allow InfiniteHits to be conditionally used
253
254
  widgetSearchParameters = searchParameters.setQueryParameters(TAG_PLACEHOLDER);
254
255
  }
255
256
 
@@ -94,6 +94,8 @@ export type RefinementListRenderState = {
94
94
  isFromSearch: boolean;
95
95
  /**
96
96
  * `true` if a refinement can be applied.
97
+ * @MAJOR: reconsider how `canRefine` is computed so it both accounts for the
98
+ * items returned in the main search and in SFFV.
97
99
  */
98
100
  canRefine: boolean;
99
101
  /**
@@ -384,7 +384,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
384
384
  // under the hood, we have a different implementation. It should be
385
385
  // completely transparent for the rest of the codebase. Only this module
386
386
  // is impacted.
387
- return mainHelper.searchOnlyWithDerivedHelpers();
387
+ return mainHelper.searchOnlyWithDerivedHelpers() && mainHelper.recommend();
388
388
  };
389
389
  if (this._searchFunction) {
390
390
  // this client isn't used to actually search, but required for the helper
@@ -1,2 +1,2 @@
1
- declare const _default: "4.66.0";
1
+ declare const _default: "4.67.0";
2
2
  export default _default;
package/es/lib/version.js CHANGED
@@ -1 +1 @@
1
- export default '4.66.0';
1
+ export default '4.67.0';
@@ -3,7 +3,7 @@ import type { InstantSearch } from './instantsearch';
3
3
  import type { IndexRenderState, WidgetRenderState } from './render-state';
4
4
  import type { IndexUiState, UiState } from './ui-state';
5
5
  import type { Expand, RequiredKeys } from './utils';
6
- import type { AlgoliaSearchHelper as Helper, SearchParameters, SearchResults } from 'algoliasearch-helper';
6
+ import type { AlgoliaSearchHelper as Helper, SearchParameters, SearchResults, RecommendParameters } from 'algoliasearch-helper';
7
7
  export type ScopedResult = {
8
8
  indexId: string;
9
9
  results: SearchResults;
@@ -30,6 +30,9 @@ export type InitOptions = SharedRenderOptions & {
30
30
  uiState: UiState;
31
31
  results?: undefined;
32
32
  };
33
+ export type ShouldRenderOptions = {
34
+ instantSearchInstance: InstantSearch;
35
+ };
33
36
  export type RenderOptions = SharedRenderOptions & {
34
37
  results: SearchResults;
35
38
  };
@@ -51,6 +54,18 @@ export type WidgetDescription = {
51
54
  indexRenderState?: Record<string, unknown>;
52
55
  indexUiState?: Record<string, unknown>;
53
56
  };
57
+ type SearchWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
58
+ dependsOn?: 'search';
59
+ getWidgetParameters?: (state: SearchParameters, widgetParametersOptions: {
60
+ uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
61
+ }) => SearchParameters;
62
+ };
63
+ type RecommendWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
64
+ dependsOn?: 'recommend';
65
+ getWidgetParameters: (state: RecommendParameters, widgetParametersOptions: {
66
+ uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
67
+ }) => RecommendParameters;
68
+ };
54
69
  type RequiredWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
55
70
  /**
56
71
  * Identifier for connectors and widgets.
@@ -60,6 +75,10 @@ type RequiredWidgetLifeCycle<TWidgetDescription extends WidgetDescription> = {
60
75
  * Called once before the first search.
61
76
  */
62
77
  init?: (options: InitOptions) => void;
78
+ /**
79
+ * Whether `render` should be called
80
+ */
81
+ shouldRender?: (options: ShouldRenderOptions) => boolean;
63
82
  /**
64
83
  * Called after each search response has been received.
65
84
  */
@@ -116,7 +135,7 @@ type RequiredUiStateLifeCycle<TWidgetDescription extends WidgetDescription> = {
116
135
  getWidgetSearchParameters: (state: SearchParameters, widgetSearchParametersOptions: {
117
136
  uiState: Expand<Partial<TWidgetDescription['indexUiState'] & IndexUiState>>;
118
137
  }) => SearchParameters;
119
- };
138
+ } & (SearchWidgetLifeCycle<TWidgetDescription> | RecommendWidgetLifeCycle<TWidgetDescription>);
120
139
  type UiStateLifeCycle<TWidgetDescription extends WidgetDescription> = TWidgetDescription extends RequiredKeys<WidgetDescription, 'indexUiState'> ? RequiredUiStateLifeCycle<TWidgetDescription> : Partial<RequiredUiStateLifeCycle<TWidgetDescription>>;
121
140
  type RequiredRenderStateLifeCycle<TWidgetDescription extends WidgetDescription & WidgetParams> = {
122
141
  /**
@@ -1,5 +1,6 @@
1
1
  function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
2
- var _excluded = ["initialSearchParameters"];
2
+ var _excluded = ["initialSearchParameters"],
3
+ _excluded2 = ["initialRecommendParameters"];
3
4
  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; }
4
5
  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; }
5
6
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -25,6 +26,7 @@ var withUsage = createDocumentationMessageGenerator({
25
26
  */
26
27
  function privateHelperSetState(helper, _ref) {
27
28
  var state = _ref.state,
29
+ recommendState = _ref.recommendState,
28
30
  isPageReset = _ref.isPageReset,
29
31
  _uiState = _ref._uiState;
30
32
  if (state !== helper.state) {
@@ -36,7 +38,14 @@ function privateHelperSetState(helper, _ref) {
36
38
  _uiState: _uiState
37
39
  });
38
40
  }
41
+ if (recommendState !== helper.recommendState) {
42
+ helper.recommendState = recommendState;
43
+
44
+ // eslint-disable-next-line no-warning-comments
45
+ // TODO: emit "change" event when events for Recommend are implemented
46
+ }
39
47
  }
48
+
40
49
  function getLocalWidgetsUiState(widgets, widgetStateOptions) {
41
50
  var initialUiState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
42
51
  return widgets.reduce(function (uiState, widget) {
@@ -55,15 +64,26 @@ function getLocalWidgetsUiState(widgets, widgetStateOptions) {
55
64
  function getLocalWidgetsSearchParameters(widgets, widgetSearchParametersOptions) {
56
65
  var initialSearchParameters = widgetSearchParametersOptions.initialSearchParameters,
57
66
  rest = _objectWithoutProperties(widgetSearchParametersOptions, _excluded);
58
- return widgets.filter(function (widget) {
59
- return !isIndexWidget(widget);
60
- }).reduce(function (state, widget) {
61
- if (!widget.getWidgetSearchParameters) {
67
+ return widgets.reduce(function (state, widget) {
68
+ if (!widget.getWidgetSearchParameters || isIndexWidget(widget)) {
62
69
  return state;
63
70
  }
71
+ if (widget.dependsOn === 'search' && widget.getWidgetParameters) {
72
+ return widget.getWidgetParameters(state, rest);
73
+ }
64
74
  return widget.getWidgetSearchParameters(state, rest);
65
75
  }, initialSearchParameters);
66
76
  }
77
+ function getLocalWidgetsRecommendParameters(widgets, widgetRecommendParametersOptions) {
78
+ var initialRecommendParameters = widgetRecommendParametersOptions.initialRecommendParameters,
79
+ rest = _objectWithoutProperties(widgetRecommendParametersOptions, _excluded2);
80
+ return widgets.reduce(function (state, widget) {
81
+ if (!isIndexWidget(widget) && widget.dependsOn === 'recommend' && widget.getWidgetParameters) {
82
+ return widget.getWidgetParameters(state, rest);
83
+ }
84
+ return state;
85
+ }, initialRecommendParameters);
86
+ }
67
87
  function resetPageFromWidgets(widgets) {
68
88
  var indexWidgets = widgets.filter(isIndexWidget);
69
89
  if (indexWidgets.length === 0) {
@@ -73,6 +93,7 @@ function resetPageFromWidgets(widgets) {
73
93
  var widgetHelper = widget.getHelper();
74
94
  privateHelperSetState(widgetHelper, {
75
95
  state: widgetHelper.state.resetPage(),
96
+ recommendState: widgetHelper.recommendState,
76
97
  isPageReset: true
77
98
  });
78
99
  resetPageFromWidgets(widget.getWidgets());
@@ -168,6 +189,10 @@ var index = function index(widgetParams) {
168
189
  uiState: localUiState,
169
190
  initialSearchParameters: helper.state
170
191
  }),
192
+ recommendState: getLocalWidgetsRecommendParameters(localWidgets, {
193
+ uiState: localUiState,
194
+ initialRecommendParameters: helper.recommendState
195
+ }),
171
196
  _uiState: localUiState
172
197
  });
173
198
 
@@ -264,11 +289,16 @@ var index = function index(widgetParams) {
264
289
  index: indexName
265
290
  })
266
291
  });
292
+ var recommendParameters = getLocalWidgetsRecommendParameters(localWidgets, {
293
+ uiState: localUiState,
294
+ initialRecommendParameters: new algoliasearchHelper.RecommendParameters()
295
+ });
267
296
 
268
297
  // This Helper is only used for state management we do not care about the
269
298
  // `searchClient`. Only the "main" Helper created at the `InstantSearch`
270
299
  // level is aware of the client.
271
300
  helper = algoliasearchHelper({}, parameters.index, parameters);
301
+ helper.recommendState = recommendParameters;
272
302
 
273
303
  // We forward the call to `search` to the "main" instance of the Helper
274
304
  // which is responsible for managing the queries (it's the only one that is
@@ -299,6 +329,8 @@ var index = function index(widgetParams) {
299
329
  };
300
330
  derivedHelper = mainHelper.derive(function () {
301
331
  return mergeSearchParameters.apply(void 0, [mainHelper.state].concat(_toConsumableArray(resolveSearchParameters(_this3))));
332
+ }, function () {
333
+ return _this3.getHelper().recommendState;
302
334
  });
303
335
  var indexInitialResults = (_instantSearchInstanc = instantSearchInstance._initialResults) === null || _instantSearchInstanc === void 0 ? void 0 : _instantSearchInstanc[this.getIndexId()];
304
336
  if (indexInitialResults) {
@@ -347,6 +379,21 @@ var index = function index(widgetParams) {
347
379
  lastValidSearchParameters = results === null || results === void 0 ? void 0 : results._state;
348
380
  });
349
381
 
382
+ // eslint-disable-next-line no-warning-comments
383
+ // TODO: listen to "result" event when events for Recommend are implemented
384
+ derivedHelper.on('recommend:result', function (_ref5) {
385
+ var recommend = _ref5.recommend;
386
+ // The index does not render the results it schedules a new render
387
+ // to let all the other indices emit their own results. It allows us to
388
+ // run the render process in one pass.
389
+ instantSearchInstance.scheduleRender();
390
+
391
+ // the derived helper is the one which actually searches, but the helper
392
+ // which is exposed e.g. via instance.helper, doesn't search, and thus
393
+ // does not have access to lastRecommendResults.
394
+ helper.lastRecommendResults = recommend.results;
395
+ });
396
+
350
397
  // We compute the render state before calling `init` in a separate loop
351
398
  // to construct the whole render state object that is then passed to
352
399
  // `init`.
@@ -397,9 +444,9 @@ var index = function index(widgetParams) {
397
444
  instantSearchInstance.scheduleRender();
398
445
  }
399
446
  },
400
- render: function render(_ref5) {
447
+ render: function render(_ref6) {
401
448
  var _this4 = this;
402
- var instantSearchInstance = _ref5.instantSearchInstance;
449
+ var instantSearchInstance = _ref6.instantSearchInstance;
403
450
  // we can't attach a listener to the error event of search, as the error
404
451
  // then would no longer be thrown for global handlers.
405
452
  if (instantSearchInstance.status === 'error' && !instantSearchInstance.mainHelper.hasPendingRequests() && lastValidSearchParameters) {
@@ -409,6 +456,14 @@ var index = function index(widgetParams) {
409
456
  // We only render index widgets if there are no results.
410
457
  // This makes sure `render` is never called with `results` being `null`.
411
458
  var widgetsToRender = this.getResults() ? localWidgets : localWidgets.filter(isIndexWidget);
459
+ widgetsToRender = widgetsToRender.filter(function (widget) {
460
+ if (!widget.shouldRender) {
461
+ return true;
462
+ }
463
+ return widget.shouldRender({
464
+ instantSearchInstance: instantSearchInstance
465
+ });
466
+ });
412
467
  widgetsToRender.forEach(function (widget) {
413
468
  if (widget.getRenderState) {
414
469
  var renderState = widget.getRenderState(instantSearchInstance.renderState[_this4.getIndexId()] || {}, createRenderArgs(instantSearchInstance, _this4));
@@ -467,8 +522,8 @@ var index = function index(widgetParams) {
467
522
  process.env.NODE_ENV === 'development' ? 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;
468
523
  return this.getWidgetUiState(uiState);
469
524
  },
470
- getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref6) {
471
- var uiState = _ref6.uiState;
525
+ getWidgetSearchParameters: function getWidgetSearchParameters(searchParameters, _ref7) {
526
+ var uiState = _ref7.uiState;
472
527
  return getLocalWidgetsSearchParameters(localWidgets, {
473
528
  uiState: uiState,
474
529
  initialSearchParameters: searchParameters
@@ -489,10 +544,10 @@ var index = function index(widgetParams) {
489
544
  };
490
545
  };
491
546
  export default index;
492
- function storeRenderState(_ref7) {
493
- var renderState = _ref7.renderState,
494
- instantSearchInstance = _ref7.instantSearchInstance,
495
- parent = _ref7.parent;
547
+ function storeRenderState(_ref8) {
548
+ var renderState = _ref8.renderState,
549
+ instantSearchInstance = _ref8.instantSearchInstance,
550
+ parent = _ref8.parent;
496
551
  var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
497
552
  instantSearchInstance.renderState = _objectSpread(_objectSpread({}, instantSearchInstance.renderState), {}, _defineProperty({}, parentIndexName, _objectSpread(_objectSpread({}, instantSearchInstance.renderState[parentIndexName]), renderState)));
498
553
  }
@@ -80,7 +80,7 @@ export type PanelWidgetParams<TWidgetFactory extends AnyWidgetFactory> = {
80
80
  */
81
81
  cssClasses?: PanelCSSClasses;
82
82
  };
83
- type AugmentedWidget<TWidgetFactory extends AnyWidgetFactory, TOverriddenKeys extends keyof Widget = 'init' | 'render' | 'dispose'> = Omit<ReturnType<TWidgetFactory>, TOverriddenKeys> & Pick<Required<Widget>, TOverriddenKeys>;
83
+ type AugmentedWidget<TWidgetFactory extends AnyWidgetFactory, TOverriddenKeys extends keyof Widget = 'init' | 'render' | 'dispose'> = Omit<ReturnType<TWidgetFactory>, TOverriddenKeys | 'dependsOn' | 'getWidgetParameters'> & Pick<Required<Widget>, TOverriddenKeys>;
84
84
  export type PanelWidget = <TWidgetFactory extends AnyWidgetFactory>(panelWidgetParams?: PanelWidgetParams<TWidgetFactory>) => (widgetFactory: TWidgetFactory) => (widgetParams: Parameters<TWidgetFactory>[0]) => AugmentedWidget<TWidgetFactory>;
85
85
  /**
86
86
  * The panel widget wraps other widgets in a consistent panel design.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instantsearch.js",
3
- "version": "4.66.0",
3
+ "version": "4.67.0",
4
4
  "description": "InstantSearch.js is a JavaScript library for building performant and instant search experiences with Algolia.",
5
5
  "homepage": "https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/",
6
6
  "types": "es/index.d.ts",
@@ -31,7 +31,7 @@
31
31
  "@types/google.maps": "^3.45.3",
32
32
  "@types/hogan.js": "^3.0.0",
33
33
  "@types/qs": "^6.5.3",
34
- "algoliasearch-helper": "3.16.3",
34
+ "algoliasearch-helper": "3.18.0",
35
35
  "hogan.js": "^3.0.2",
36
36
  "htm": "^3.0.0",
37
37
  "instantsearch-ui-components": "0.4.0",
@@ -56,15 +56,15 @@
56
56
  "watch:es": "yarn --silent build:es:base --watch"
57
57
  },
58
58
  "devDependencies": {
59
- "@instantsearch/mocks": "1.39.0",
60
- "@instantsearch/tests": "1.39.0",
61
- "@instantsearch/testutils": "1.28.0",
59
+ "@instantsearch/mocks": "1.41.0",
60
+ "@instantsearch/tests": "1.41.0",
61
+ "@instantsearch/testutils": "1.30.0",
62
62
  "@storybook/html": "5.3.9",
63
63
  "@types/scriptjs": "0.0.2",
64
- "algoliasearch": "4.22.1",
64
+ "algoliasearch": "4.23.2",
65
65
  "places.js": "1.17.1",
66
66
  "scriptjs": "2.5.9",
67
67
  "webpack": "4.47.0"
68
68
  },
69
- "gitHead": "358f849cba15cbbb415da05feb582b47358aa239"
69
+ "gitHead": "17da3c2268354325cc22103260d944d3e4feff90"
70
70
  }