instantsearch.js 4.58.0 → 4.60.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.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/cjs/components/Pagination/Pagination.js +4 -4
  3. package/cjs/components/RefinementList/RefinementList.js +2 -1
  4. package/cjs/components/SearchBox/SearchBox.js +5 -2
  5. package/cjs/components/Selector/Selector.js +4 -2
  6. package/cjs/components/Slider/Slider.js +3 -1
  7. package/cjs/lib/InstantSearch.js +27 -5
  8. package/cjs/lib/utils/createSendEventForFacet.js +12 -5
  9. package/cjs/lib/utils/createSendEventForHits.js +12 -6
  10. package/cjs/lib/utils/hydrateSearchClient.js +116 -0
  11. package/cjs/lib/utils/index.js +11 -0
  12. package/cjs/lib/version.js +1 -1
  13. package/cjs/middlewares/createInsightsMiddleware.js +15 -4
  14. package/cjs/widgets/sort-by/sort-by.js +2 -1
  15. package/dist/instantsearch.development.d.ts +4 -3
  16. package/dist/instantsearch.development.js +184 -34
  17. package/dist/instantsearch.development.js.map +1 -1
  18. package/dist/instantsearch.production.d.ts +4 -3
  19. package/dist/instantsearch.production.min.d.ts +4 -3
  20. package/dist/instantsearch.production.min.js +2 -2
  21. package/dist/instantsearch.production.min.js.map +1 -1
  22. package/es/components/Pagination/Pagination.js +4 -4
  23. package/es/components/RefinementList/RefinementList.js +2 -1
  24. package/es/components/SearchBox/SearchBox.d.ts +3 -0
  25. package/es/components/SearchBox/SearchBox.js +5 -2
  26. package/es/components/Selector/Selector.d.ts +2 -1
  27. package/es/components/Selector/Selector.js +4 -2
  28. package/es/components/Slider/Slider.js +3 -1
  29. package/es/lib/InstantSearch.d.ts +1 -0
  30. package/es/lib/InstantSearch.js +28 -6
  31. package/es/lib/utils/createSendEventForFacet.d.ts +1 -1
  32. package/es/lib/utils/createSendEventForFacet.js +12 -5
  33. package/es/lib/utils/createSendEventForHits.d.ts +2 -2
  34. package/es/lib/utils/createSendEventForHits.js +12 -6
  35. package/es/lib/utils/hydrateSearchClient.d.ts +2 -0
  36. package/es/lib/utils/hydrateSearchClient.js +110 -0
  37. package/es/lib/utils/index.d.ts +1 -0
  38. package/es/lib/utils/index.js +1 -0
  39. package/es/lib/version.d.ts +1 -1
  40. package/es/lib/version.js +1 -1
  41. package/es/middlewares/createInsightsMiddleware.js +15 -4
  42. package/es/widgets/sort-by/sort-by.js +2 -1
  43. package/package.json +6 -6
@@ -19,7 +19,7 @@ function Pagination(props) {
19
19
  }, h("ul", {
20
20
  className: props.cssClasses.list
21
21
  }, props.showFirst && h(PaginationLink, {
22
- ariaLabel: "First",
22
+ ariaLabel: "First Page",
23
23
  className: props.cssClasses.firstPageItem,
24
24
  isDisabled: props.isFirstPage,
25
25
  templates: props.templates,
@@ -29,7 +29,7 @@ function Pagination(props) {
29
29
  cssClasses: props.cssClasses,
30
30
  createClickHandler: createClickHandler
31
31
  }), props.showPrevious && h(PaginationLink, {
32
- ariaLabel: "Previous",
32
+ ariaLabel: "Previous Page",
33
33
  className: props.cssClasses.previousPageItem,
34
34
  isDisabled: props.isFirstPage,
35
35
  templates: props.templates,
@@ -52,7 +52,7 @@ function Pagination(props) {
52
52
  createClickHandler: createClickHandler
53
53
  });
54
54
  }), props.showNext && h(PaginationLink, {
55
- ariaLabel: "Next",
55
+ ariaLabel: "Next Page",
56
56
  className: props.cssClasses.nextPageItem,
57
57
  isDisabled: props.isLastPage,
58
58
  templates: props.templates,
@@ -62,7 +62,7 @@ function Pagination(props) {
62
62
  cssClasses: props.cssClasses,
63
63
  createClickHandler: createClickHandler
64
64
  }), props.showLast && h(PaginationLink, {
65
- ariaLabel: "Last",
65
+ ariaLabel: "Last Page, Page ".concat(props.nbPages),
66
66
  className: props.cssClasses.lastPageItem,
67
67
  isDisabled: props.isLastPage,
68
68
  templates: props.templates,
@@ -203,7 +203,8 @@ var RefinementList = /*#__PURE__*/function (_Component) {
203
203
  // This sets the search box to a controlled state because
204
204
  // we don't rely on the `refine` prop but on `onChange`.
205
205
  ,
206
- searchAsYouType: false
206
+ searchAsYouType: false,
207
+ ariaLabel: "Search for filters"
207
208
  }));
208
209
  var facetValues = this.props.facetValues && this.props.facetValues.length > 0 && h("ul", {
209
210
  className: this.props.cssClasses.list
@@ -18,6 +18,7 @@ type SearchBoxProps = {
18
18
  searchAsYouType?: boolean;
19
19
  isSearchStalled?: boolean;
20
20
  disabled?: boolean;
21
+ ariaLabel?: string;
21
22
  onChange?: (event: Event) => void;
22
23
  onSubmit?: (event: Event) => void;
23
24
  onReset?: (event: Event) => void;
@@ -31,6 +32,7 @@ declare const defaultProps: {
31
32
  searchAsYouType: boolean;
32
33
  isSearchStalled: boolean;
33
34
  disabled: boolean;
35
+ ariaLabel: string;
34
36
  onChange: typeof noop;
35
37
  onSubmit: typeof noop;
36
38
  onReset: typeof noop;
@@ -51,6 +53,7 @@ declare class SearchBox extends Component<SearchBoxPropsWithDefaultProps, Search
51
53
  searchAsYouType: boolean;
52
54
  isSearchStalled: boolean;
53
55
  disabled: boolean;
56
+ ariaLabel: string;
54
57
  onChange: typeof noop;
55
58
  onSubmit: typeof noop;
56
59
  onReset: typeof noop;
@@ -24,6 +24,7 @@ var defaultProps = {
24
24
  searchAsYouType: true,
25
25
  isSearchStalled: false,
26
26
  disabled: false,
27
+ ariaLabel: 'Search',
27
28
  onChange: noop,
28
29
  onSubmit: noop,
29
30
  onReset: noop,
@@ -140,7 +141,8 @@ var SearchBox = /*#__PURE__*/function (_Component) {
140
141
  showReset = _this$props4.showReset,
141
142
  showLoadingIndicator = _this$props4.showLoadingIndicator,
142
143
  templates = _this$props4.templates,
143
- isSearchStalled = _this$props4.isSearchStalled;
144
+ isSearchStalled = _this$props4.isSearchStalled,
145
+ ariaLabel = _this$props4.ariaLabel;
144
146
  return h("div", {
145
147
  className: cssClasses.root
146
148
  }, h("form", {
@@ -167,7 +169,8 @@ var SearchBox = /*#__PURE__*/function (_Component) {
167
169
  maxLength: 512,
168
170
  onInput: this.onInput,
169
171
  onBlur: this.onBlur,
170
- onFocus: this.onFocus
172
+ onFocus: this.onFocus,
173
+ "aria-label": ariaLabel
171
174
  }), h(Template, {
172
175
  templateKey: "submit",
173
176
  rootTagName: "button",
@@ -14,6 +14,7 @@ export type SelectorProps = {
14
14
  currentValue?: string | number;
15
15
  options: SelectorOption[];
16
16
  setValue: (value: string) => void;
17
+ ariaLabel?: string;
17
18
  };
18
- declare function Selector({ currentValue, options, cssClasses, setValue, }: SelectorProps): h.JSX.Element;
19
+ declare function Selector({ currentValue, options, cssClasses, setValue, ariaLabel, }: SelectorProps): h.JSX.Element;
19
20
  export default Selector;
@@ -4,13 +4,15 @@ function Selector(_ref) {
4
4
  var currentValue = _ref.currentValue,
5
5
  options = _ref.options,
6
6
  cssClasses = _ref.cssClasses,
7
- setValue = _ref.setValue;
7
+ setValue = _ref.setValue,
8
+ ariaLabel = _ref.ariaLabel;
8
9
  return h("select", {
9
10
  className: cx(cssClasses.select),
10
11
  onChange: function onChange(event) {
11
12
  return setValue(event.target.value);
12
13
  },
13
- value: "".concat(currentValue)
14
+ value: "".concat(currentValue),
15
+ "aria-label": ariaLabel
14
16
  }, options.map(function (option) {
15
17
  return h("option", {
16
18
  className: cx(cssClasses.option),
@@ -49,8 +49,10 @@ var Slider = /*#__PURE__*/function (_Component) {
49
49
  parseFloat(props['aria-valuenow']) * 100) / 100;
50
50
  var value = _typeof(tooltips) === 'object' && tooltips.format ? tooltips.format(roundedValue) : roundedValue;
51
51
  var className = cx(props.className, props['data-handle-key'] === 0 && 'rheostat-handle-lower', props['data-handle-key'] === 1 && 'rheostat-handle-upper');
52
+ var ariaLabel = props['data-handle-key'] === 0 ? 'Minimum Filter Handle' : 'Maximum Filter Handle';
52
53
  return h("div", _extends({}, props, {
53
- className: className
54
+ className: className,
55
+ "aria-label": ariaLabel
54
56
  }), tooltips && h("div", {
55
57
  className: "rheostat-tooltip"
56
58
  }, value));
@@ -135,6 +135,7 @@ declare class InstantSearch<TUiState extends UiState = UiState, TRouteState = TU
135
135
  _createURL: CreateURL<TUiState>;
136
136
  _searchFunction?: InstantSearchOptions['searchFunction'];
137
137
  _mainHelperSearch?: AlgoliaSearchHelper['search'];
138
+ _insights: InstantSearchOptions['insights'];
138
139
  middleware: Array<{
139
140
  creator: Middleware<TUiState>;
140
141
  instance: MiddlewareDefinition<TUiState>;
@@ -21,7 +21,7 @@ import { createMetadataMiddleware, isMetadataEnabled } from "../middlewares/crea
21
21
  import { createRouterMiddleware } from "../middlewares/createRouterMiddleware.js";
22
22
  import index from "../widgets/index/index.js";
23
23
  import createHelpers from "./createHelpers.js";
24
- import { createDocumentationMessageGenerator, createDocumentationLink, defer, noop, warning, setIndexHelperState, isIndexWidget } from "./utils/index.js";
24
+ import { createDocumentationMessageGenerator, createDocumentationLink, defer, hydrateSearchClient, noop, warning, setIndexHelperState, isIndexWidget } from "./utils/index.js";
25
25
  import version from "./version.js";
26
26
  var withUsage = createDocumentationMessageGenerator({
27
27
  name: 'instantsearch'
@@ -73,6 +73,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
73
73
  _defineProperty(_assertThisInitialized(_this), "_createURL", void 0);
74
74
  _defineProperty(_assertThisInitialized(_this), "_searchFunction", void 0);
75
75
  _defineProperty(_assertThisInitialized(_this), "_mainHelperSearch", void 0);
76
+ _defineProperty(_assertThisInitialized(_this), "_insights", void 0);
76
77
  _defineProperty(_assertThisInitialized(_this), "middleware", []);
77
78
  _defineProperty(_assertThisInitialized(_this), "sendEventToInsights", void 0);
78
79
  /**
@@ -123,7 +124,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
123
124
  _options$routing = options.routing,
124
125
  routing = _options$routing === void 0 ? null : _options$routing,
125
126
  _options$insights = options.insights,
126
- insights = _options$insights === void 0 ? false : _options$insights,
127
+ insights = _options$insights === void 0 ? undefined : _options$insights,
127
128
  searchFunction = options.searchFunction,
128
129
  _options$stalledSearc = options.stalledSearchDelay,
129
130
  stalledSearchDelay = _options$stalledSearc === void 0 ? 200 : _options$stalledSearc,
@@ -179,6 +180,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
179
180
  _this._createURL = defaultCreateURL;
180
181
  _this._initialUiState = initialUiState;
181
182
  _this._initialResults = null;
183
+ _this._insights = insights;
182
184
  if (searchFunction) {
183
185
  process.env.NODE_ENV === 'development' ? warning(false, "The `searchFunction` option is deprecated. Use `onStateChange` instead.") : void 0;
184
186
  _this._searchFunction = searchFunction;
@@ -190,8 +192,9 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
190
192
  _this.use(createRouterMiddleware(routerOptions));
191
193
  }
192
194
 
193
- // This is the default middleware,
194
- // any user-provided middleware will be added later and override this one.
195
+ // This is the default Insights middleware,
196
+ // added when `insights` is set to true by the user.
197
+ // Any user-provided middleware will be added later and override this one.
195
198
  if (insights) {
196
199
  var insightsOptions = typeof insights === 'boolean' ? {} : insights;
197
200
  insightsOptions.$$internal = true;
@@ -446,6 +449,7 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
446
449
  uiState: this._initialUiState
447
450
  });
448
451
  if (this._initialResults) {
452
+ hydrateSearchClient(this.client, this._initialResults);
449
453
  var originalScheduleSearch = this.scheduleSearch;
450
454
  // We don't schedule a first search when initial results are provided
451
455
  // because we already have the results to render. This skips the initial
@@ -483,6 +487,24 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
483
487
  var instance = _ref6.instance;
484
488
  instance.started();
485
489
  });
490
+
491
+ // This is the automatic Insights middleware,
492
+ // added when `insights` is unset and the initial results possess `queryID`.
493
+ // Any user-provided middleware will be added later and override this one.
494
+ if (typeof this._insights === 'undefined') {
495
+ mainHelper.derivedHelpers[0].once('result', function () {
496
+ var hasAutomaticInsights = _this3.mainIndex.getScopedResults().some(function (_ref7) {
497
+ var results = _ref7.results;
498
+ return results === null || results === void 0 ? void 0 : results._automaticInsights;
499
+ });
500
+ if (hasAutomaticInsights) {
501
+ _this3.use(createInsightsMiddleware({
502
+ $$internal: true,
503
+ $$automatic: true
504
+ }));
505
+ }
506
+ });
507
+ }
486
508
  }
487
509
 
488
510
  /**
@@ -512,8 +534,8 @@ var InstantSearch = /*#__PURE__*/function (_EventEmitter) {
512
534
  (_this$mainHelper2 = this.mainHelper) === null || _this$mainHelper2 === void 0 ? void 0 : _this$mainHelper2.removeAllListeners();
513
535
  this.mainHelper = null;
514
536
  this.helper = null;
515
- this.middleware.forEach(function (_ref7) {
516
- var instance = _ref7.instance;
537
+ this.middleware.forEach(function (_ref8) {
538
+ var instance = _ref8.instance;
517
539
  instance.unsubscribe();
518
540
  });
519
541
  }
@@ -1,6 +1,6 @@
1
1
  import type { InstantSearch } from '../../types';
2
2
  import type { AlgoliaSearchHelper } from 'algoliasearch-helper';
3
- type BuiltInSendEventForFacet = (eventType: string, facetValue: string, eventName?: string) => void;
3
+ type BuiltInSendEventForFacet = (eventType: string, facetValue: string, eventName?: string, additionalData?: Record<string, any>) => void;
4
4
  type CustomSendEventForFacet = (customPayload: any) => void;
5
5
  export type SendEventForFacet = BuiltInSendEventForFacet & CustomSendEventForFacet;
6
6
  type CreateSendEventForFacetOptions = {
@@ -1,3 +1,8 @@
1
+ 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; }
2
+ 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; }
3
+ 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; }
4
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
5
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
1
6
  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
7
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
3
8
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -17,7 +22,9 @@ export function createSendEventForFacet(_ref) {
17
22
  }
18
23
  var facetValue = args[1],
19
24
  _args$ = args[2],
20
- eventName = _args$ === void 0 ? 'Filter Applied' : _args$;
25
+ eventName = _args$ === void 0 ? 'Filter Applied' : _args$,
26
+ _args$2 = args[3],
27
+ additionalData = _args$2 === void 0 ? {} : _args$2;
21
28
  var _args$0$split = args[0].split(':'),
22
29
  _args$0$split2 = _slicedToArray(_args$0$split, 2),
23
30
  eventType = _args$0$split2[0],
@@ -25,7 +32,7 @@ export function createSendEventForFacet(_ref) {
25
32
  var attribute = typeof attr === 'string' ? attr : attr(facetValue);
26
33
  if (args.length === 1 && _typeof(args[0]) === 'object') {
27
34
  instantSearchInstance.sendEventToInsights(args[0]);
28
- } else if (eventType === 'click' && (args.length === 2 || args.length === 3)) {
35
+ } else if (eventType === 'click' && args.length >= 2 && args.length <= 4) {
29
36
  if (!isFacetRefined(helper, attribute, facetValue)) {
30
37
  // send event only when the facet is being checked "ON"
31
38
  instantSearchInstance.sendEventToInsights({
@@ -33,16 +40,16 @@ export function createSendEventForFacet(_ref) {
33
40
  widgetType: widgetType,
34
41
  eventType: eventType,
35
42
  eventModifier: eventModifier,
36
- payload: {
43
+ payload: _objectSpread({
37
44
  eventName: eventName,
38
45
  index: helper.getIndex(),
39
46
  filters: ["".concat(attribute, ":").concat(facetValue)]
40
- },
47
+ }, additionalData),
41
48
  attribute: attribute
42
49
  });
43
50
  }
44
51
  } else if (process.env.NODE_ENV === 'development') {
45
- throw new Error("You need to pass two arguments like:\n sendEvent('click', facetValue);\n\nIf you want to send a custom payload, you can pass one object: sendEvent(customPayload);\n");
52
+ throw new Error("You need to pass between two and four arguments like:\n sendEvent('click', facetValue, eventName?, additionalData?);\n\nIf you want to send a custom payload, you can pass one object: sendEvent(customPayload);\n");
46
53
  }
47
54
  };
48
55
  return sendEventForFacet;
@@ -1,9 +1,9 @@
1
1
  import type { InsightsEvent } from '../../middlewares/createInsightsMiddleware';
2
2
  import type { InstantSearch, Hit } from '../../types';
3
- type BuiltInSendEventForHits = (eventType: string, hits: Hit | Hit[], eventName?: string) => void;
3
+ type BuiltInSendEventForHits = (eventType: string, hits: Hit | Hit[], eventName?: string, additionalData?: Record<string, any>) => void;
4
4
  type CustomSendEventForHits = (customPayload: any) => void;
5
5
  export type SendEventForHits = BuiltInSendEventForHits & CustomSendEventForHits;
6
- export type BuiltInBindEventForHits = (eventType: string, hits: Hit | Hit[], eventName?: string) => string;
6
+ export type BuiltInBindEventForHits = (eventType: string, hits: Hit | Hit[], eventName?: string, additionalData?: Record<string, any>) => string;
7
7
  export type CustomBindEventForHits = (customPayload: any) => string;
8
8
  export type BindEventForHits = BuiltInBindEventForHits & CustomBindEventForHits;
9
9
  export declare function _buildEventPayloadsForHits({ index, widgetType, methodName, args, instantSearchInstance, }: {
@@ -1,3 +1,8 @@
1
+ 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; }
2
+ 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; }
3
+ 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; }
4
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
5
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
1
6
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
7
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
8
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -30,6 +35,7 @@ export function _buildEventPayloadsForHits(_ref) {
30
35
  eventModifier = _args$0$split2[1];
31
36
  var hits = args[1];
32
37
  var eventName = args[2];
38
+ var additionalData = args[3] || {};
33
39
  if (!hits) {
34
40
  if (process.env.NODE_ENV === 'development') {
35
41
  throw new Error("You need to pass hit or hits as the second argument like:\n ".concat(methodName, "(eventType, hit);\n "));
@@ -69,11 +75,11 @@ export function _buildEventPayloadsForHits(_ref) {
69
75
  insightsMethod: 'viewedObjectIDs',
70
76
  widgetType: widgetType,
71
77
  eventType: eventType,
72
- payload: {
78
+ payload: _objectSpread({
73
79
  eventName: eventName || 'Hits Viewed',
74
80
  index: index,
75
81
  objectIDs: objectIDsByChunk[i]
76
- },
82
+ }, additionalData),
77
83
  hits: batch,
78
84
  eventModifier: eventModifier
79
85
  };
@@ -84,13 +90,13 @@ export function _buildEventPayloadsForHits(_ref) {
84
90
  insightsMethod: 'clickedObjectIDsAfterSearch',
85
91
  widgetType: widgetType,
86
92
  eventType: eventType,
87
- payload: {
93
+ payload: _objectSpread({
88
94
  eventName: eventName || 'Hit Clicked',
89
95
  index: index,
90
96
  queryID: queryID,
91
97
  objectIDs: objectIDsByChunk[i],
92
98
  positions: positionsByChunk[i]
93
- },
99
+ }, additionalData),
94
100
  hits: batch,
95
101
  eventModifier: eventModifier
96
102
  };
@@ -101,12 +107,12 @@ export function _buildEventPayloadsForHits(_ref) {
101
107
  insightsMethod: 'convertedObjectIDsAfterSearch',
102
108
  widgetType: widgetType,
103
109
  eventType: eventType,
104
- payload: {
110
+ payload: _objectSpread({
105
111
  eventName: eventName || 'Hit Converted',
106
112
  index: index,
107
113
  queryID: queryID,
108
114
  objectIDs: objectIDsByChunk[i]
109
- },
115
+ }, additionalData),
110
116
  hits: batch,
111
117
  eventModifier: eventModifier
112
118
  };
@@ -0,0 +1,2 @@
1
+ import type { InitialResults, SearchClient } from '../../types';
2
+ export declare function hydrateSearchClient(client: SearchClient, results?: InitialResults): void;
@@ -0,0 +1,110 @@
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
+ 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; }
3
+ 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; }
4
+ 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; }
5
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
6
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
7
+ // @ts-nocheck (types to be fixed during actual implementation)
8
+
9
+ export function hydrateSearchClient(client, results) {
10
+ if (!results) {
11
+ return;
12
+ }
13
+
14
+ // Disable cache hydration on:
15
+ // - Algoliasearch API Client < v4 with cache disabled
16
+ // - Third party clients (detected by the `addAlgoliaAgent` function missing)
17
+
18
+ if ((!client.transporter || client._cacheHydrated) && (!client._useCache || typeof client.addAlgoliaAgent !== 'function')) {
19
+ return;
20
+ }
21
+
22
+ // Algoliasearch API Client >= v4
23
+ // To hydrate the client we need to populate the cache with the data from
24
+ // the server (done in `hydrateSearchClientWithMultiIndexRequest` or
25
+ // `hydrateSearchClientWithSingleIndexRequest`). But since there is no way
26
+ // for us to compute the key the same way as `algoliasearch-client` we need
27
+ // to populate it on a custom key and override the `search` method to
28
+ // search on it first.
29
+ if (client.transporter && !client._cacheHydrated) {
30
+ client._cacheHydrated = true;
31
+ var baseMethod = client.search;
32
+ client.search = function (requests) {
33
+ for (var _len = arguments.length, methodArgs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
34
+ methodArgs[_key - 1] = arguments[_key];
35
+ }
36
+ var requestsWithSerializedParams = requests.map(function (request) {
37
+ return _objectSpread(_objectSpread({}, request), {}, {
38
+ params: serializeQueryParameters(request.params)
39
+ });
40
+ });
41
+ return client.transporter.responsesCache.get({
42
+ method: 'search',
43
+ args: [requestsWithSerializedParams].concat(methodArgs)
44
+ }, function () {
45
+ return baseMethod.apply(void 0, [requests].concat(methodArgs));
46
+ });
47
+ };
48
+
49
+ // Populate the cache with the data from the server
50
+ client.transporter.responsesCache.set({
51
+ method: 'search',
52
+ args: [Object.keys(results).reduce(function (acc, key) {
53
+ return acc.concat(results[key].results.map(function (request) {
54
+ return {
55
+ indexName: request.index,
56
+ params: request.params
57
+ };
58
+ }));
59
+ }, [])]
60
+ }, {
61
+ results: Object.keys(results).reduce(function (acc, key) {
62
+ return acc.concat(results[key].results);
63
+ }, [])
64
+ });
65
+ }
66
+
67
+ // Algoliasearch API Client < v4
68
+ // Prior to client v4 we didn't have a proper API to hydrate the client
69
+ // cache from the outside. The following code populates the cache with
70
+ // a single-index result. You can find more information about the
71
+ // computation of the key inside the client (see link below).
72
+ // https://github.com/algolia/algoliasearch-client-javascript/blob/c27e89ff92b2a854ae6f40dc524bffe0f0cbc169/src/AlgoliaSearchCore.js#L232-L240
73
+ if (!client.transporter) {
74
+ var cacheKey = "/1/indexes/*/queries_body_".concat(JSON.stringify({
75
+ requests: Object.keys(results).reduce(function (acc, key) {
76
+ return acc.concat(results[key].rawResults.map(function (request) {
77
+ return {
78
+ indexName: request.index,
79
+ params: request.params
80
+ };
81
+ }));
82
+ }, [])
83
+ }));
84
+ client.cache = _objectSpread(_objectSpread({}, client.cache), {}, _defineProperty({}, cacheKey, JSON.stringify({
85
+ results: Object.keys(results).reduce(function (acc, key) {
86
+ return acc.concat(results[key].rawResults);
87
+ }, [])
88
+ })));
89
+ }
90
+ }
91
+
92
+ // This function is copied from the algoliasearch v4 API Client. If modified,
93
+ // consider updating it also in `serializeQueryParameters` from `@algolia/transporter`.
94
+ function serializeQueryParameters(parameters) {
95
+ var isObjectOrArray = function isObjectOrArray(value) {
96
+ return Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === '[object Array]';
97
+ };
98
+ var encode = function encode(format) {
99
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
100
+ args[_key2 - 1] = arguments[_key2];
101
+ }
102
+ var i = 0;
103
+ return format.replace(/%s/g, function () {
104
+ return encodeURIComponent(args[i++]);
105
+ });
106
+ };
107
+ return Object.keys(parameters).map(function (key) {
108
+ return encode('%s=%s', key, isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key]);
109
+ }).join('&');
110
+ }
@@ -27,6 +27,7 @@ export * from './getRefinements';
27
27
  export * from './getWidgetAttribute';
28
28
  export * from './hits-absolute-position';
29
29
  export * from './hits-query-id';
30
+ export * from './hydrateSearchClient';
30
31
  export * from './isDomElement';
31
32
  export * from './isEqual';
32
33
  export * from './isFacetRefined';
@@ -27,6 +27,7 @@ export * from "./getRefinements.js";
27
27
  export * from "./getWidgetAttribute.js";
28
28
  export * from "./hits-absolute-position.js";
29
29
  export * from "./hits-query-id.js";
30
+ export * from "./hydrateSearchClient.js";
30
31
  export * from "./isDomElement.js";
31
32
  export * from "./isEqual.js";
32
33
  export * from "./isFacetRefined.js";
@@ -1,2 +1,2 @@
1
- declare const _default: "4.58.0";
1
+ declare const _default: "4.60.0";
2
2
  export default _default;
package/es/lib/version.js CHANGED
@@ -1 +1 @@
1
- export default '4.58.0';
1
+ export default '4.60.0';
@@ -24,7 +24,9 @@ export function createInsightsMiddleware() {
24
24
  insightsInitParams = props.insightsInitParams,
25
25
  onEvent = props.onEvent,
26
26
  _props$$$internal = props.$$internal,
27
- $$internal = _props$$$internal === void 0 ? false : _props$$$internal;
27
+ $$internal = _props$$$internal === void 0 ? false : _props$$$internal,
28
+ _props$$$automatic = props.$$automatic,
29
+ $$automatic = _props$$$automatic === void 0 ? false : _props$$$automatic;
28
30
  var potentialInsightsClient = _insightsClient;
29
31
  if (!_insightsClient && _insightsClient !== null) {
30
32
  safelyRunOnBrowser(function (_ref) {
@@ -115,6 +117,7 @@ export function createInsightsMiddleware() {
115
117
  return {
116
118
  $$type: 'ais.insights',
117
119
  $$internal: $$internal,
120
+ $$automatic: $$automatic,
118
121
  onStateChange: function onStateChange() {},
119
122
  subscribe: function subscribe() {
120
123
  if (!insightsClient.shouldAddScript) return;
@@ -140,9 +143,14 @@ export function createInsightsMiddleware() {
140
143
  userToken: helper.state.userToken,
141
144
  clickAnalytics: helper.state.clickAnalytics
142
145
  };
143
- helper.overrideStateWithoutTriggeringChangeEvent(_objectSpread(_objectSpread({}, helper.state), {}, {
144
- clickAnalytics: true
145
- }));
146
+
147
+ // We don't want to force clickAnalytics when the insights is enabled from the search response.
148
+ // This means we don't enable insights for indices that don't opt in
149
+ if (!$$automatic) {
150
+ helper.overrideStateWithoutTriggeringChangeEvent(_objectSpread(_objectSpread({}, helper.state), {}, {
151
+ clickAnalytics: true
152
+ }));
153
+ }
146
154
  if (!$$internal) {
147
155
  instantSearchInstance.scheduleSearch();
148
156
  }
@@ -209,6 +217,9 @@ export function createInsightsMiddleware() {
209
217
  } else if (event.insightsMethod) {
210
218
  // Source is used to differentiate events sent by instantsearch from those sent manually.
211
219
  event.payload.algoliaSource = ['instantsearch'];
220
+ if ($$automatic) {
221
+ event.payload.algoliaSource.push('instantsearch-automatic');
222
+ }
212
223
  if (event.eventModifier === 'internal') {
213
224
  event.payload.algoliaSource.push('instantsearch-internal');
214
225
  }
@@ -30,7 +30,8 @@ var renderer = function renderer(_ref) {
30
30
  cssClasses: cssClasses,
31
31
  currentValue: currentRefinement,
32
32
  options: options,
33
- setValue: refine
33
+ setValue: refine,
34
+ ariaLabel: "Sort results by"
34
35
  })), containerNode);
35
36
  };
36
37
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instantsearch.js",
3
- "version": "4.58.0",
3
+ "version": "4.60.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",
@@ -33,7 +33,7 @@
33
33
  "@types/google.maps": "^3.45.3",
34
34
  "@types/hogan.js": "^3.0.0",
35
35
  "@types/qs": "^6.5.3",
36
- "algoliasearch-helper": "3.14.2",
36
+ "algoliasearch-helper": "3.15.0",
37
37
  "hogan.js": "^3.0.2",
38
38
  "htm": "^3.0.0",
39
39
  "preact": "^10.10.0",
@@ -55,9 +55,9 @@
55
55
  "version": "./scripts/version/update-version.js"
56
56
  },
57
57
  "devDependencies": {
58
- "@instantsearch/mocks": "1.27.0",
59
- "@instantsearch/tests": "1.27.0",
60
- "@instantsearch/testutils": "1.16.0",
58
+ "@instantsearch/mocks": "1.29.0",
59
+ "@instantsearch/tests": "1.29.0",
60
+ "@instantsearch/testutils": "1.18.0",
61
61
  "@storybook/html": "5.3.9",
62
62
  "@types/scriptjs": "0.0.2",
63
63
  "algoliasearch": "4.14.3",
@@ -65,5 +65,5 @@
65
65
  "scriptjs": "2.5.9",
66
66
  "webpack": "4.41.5"
67
67
  },
68
- "gitHead": "d21e0ed006139e5635df70d7a4caf0c99ab85f5a"
68
+ "gitHead": "cacb63f88ce9f215e8f65af2b497e615a58b296e"
69
69
  }