algolia-experiences 1.8.12 → 1.8.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- /*! algolia-experiences 1.8.12 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
1
+ /*! algolia-experiences 1.8.14 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
2
2
  (function (factory) {
3
3
  typeof define === 'function' && define.amd ? define(factory) :
4
4
  factory();
@@ -4987,7 +4987,7 @@
4987
4987
  function requireVersion() {
4988
4988
  if (hasRequiredVersion) return version$1;
4989
4989
  hasRequiredVersion = 1;
4990
- version$1 = '3.29.1';
4990
+ version$1 = '3.29.2';
4991
4991
  return version$1;
4992
4992
  }
4993
4993
 
@@ -6886,6 +6886,8 @@
6886
6886
  });
6887
6887
  }
6888
6888
 
6889
+ var version = '4.105.0';
6890
+
6889
6891
  var ANONYMOUS_TOKEN_COOKIE_KEY = '_ALGOLIA';
6890
6892
  function getCookie(name) {
6891
6893
  if ((typeof document === "undefined" ? "undefined" : _type_of(document)) !== 'object' || typeof document.cookie !== 'string') {
@@ -6908,6 +6910,232 @@
6908
6910
  return getCookie(ANONYMOUS_TOKEN_COOKIE_KEY);
6909
6911
  }
6910
6912
 
6913
+ function serializePayload(payload) {
6914
+ return btoa(encodeURIComponent(JSON.stringify(payload)));
6915
+ }
6916
+ function deserializePayload(serialized) {
6917
+ return JSON.parse(decodeURIComponent(atob(serialized)));
6918
+ }
6919
+
6920
+ var USAGE_SESSION_KEY = 'ais.usage.sessionId';
6921
+ // Cache the id for the lifetime of the runtime so repeated calls don't hit
6922
+ // `sessionStorage` again, and so we always return the same id even when
6923
+ // storage is unavailable (SSR, privacy mode) and we fall back to a fresh UUID.
6924
+ var usageSessionId = null;
6925
+ function getUsageSessionId() {
6926
+ if (usageSessionId) {
6927
+ return usageSessionId;
6928
+ }
6929
+ try {
6930
+ var existing = sessionStorage.getItem(USAGE_SESSION_KEY);
6931
+ if (existing) {
6932
+ usageSessionId = existing;
6933
+ return usageSessionId;
6934
+ }
6935
+ usageSessionId = createUUID();
6936
+ sessionStorage.setItem(USAGE_SESSION_KEY, usageSessionId);
6937
+ return usageSessionId;
6938
+ } catch (unused) {
6939
+ // sessionStorage unavailable (SSR, privacy mode, etc.)
6940
+ usageSessionId = createUUID();
6941
+ return usageSessionId;
6942
+ }
6943
+ }
6944
+ /** @deprecated use bindEvent instead */ function readDataAttributes(domElement) {
6945
+ var method = domElement.getAttribute('data-insights-method');
6946
+ var serializedPayload = domElement.getAttribute('data-insights-payload');
6947
+ if (typeof serializedPayload !== 'string') {
6948
+ throw new Error('The insights helper expects `data-insights-payload` to be a base64-encoded JSON string.');
6949
+ }
6950
+ try {
6951
+ var payload = deserializePayload(serializedPayload);
6952
+ return {
6953
+ method: method,
6954
+ payload: payload
6955
+ };
6956
+ } catch (error) {
6957
+ throw new Error('The insights helper was unable to parse `data-insights-payload`.');
6958
+ }
6959
+ }
6960
+ /** @deprecated use bindEvent instead */ function writeDataAttributes(param) {
6961
+ var method = param.method, payload = param.payload;
6962
+ if ((typeof payload === "undefined" ? "undefined" : _type_of(payload)) !== 'object') {
6963
+ throw new Error("The insights helper expects the payload to be an object.");
6964
+ }
6965
+ var serializedPayload;
6966
+ try {
6967
+ serializedPayload = serializePayload(payload);
6968
+ } catch (error) {
6969
+ throw new Error("Could not JSON serialize the payload object.");
6970
+ }
6971
+ return 'data-insights-method="'.concat(method, '" data-insights-payload="').concat(serializedPayload, '"');
6972
+ }
6973
+ /**
6974
+ * @deprecated This function will be still supported in 4.x releases, but not further. It is replaced by the `insights` middleware. For more information, visit https://www.algolia.com/doc/guides/getting-insights-and-analytics/search-analytics/click-through-and-conversions/how-to/send-click-and-conversion-events-with-instantsearch/js/
6975
+ */ function insights(method, payload) {
6976
+ return writeDataAttributes({
6977
+ method: method,
6978
+ payload: payload
6979
+ });
6980
+ }
6981
+
6982
+ var now = typeof performance !== 'undefined' ? function() {
6983
+ return performance.now();
6984
+ } : function() {
6985
+ return Date.now();
6986
+ };
6987
+
6988
+ var indexWidgetTypes = [
6989
+ 'ais.index',
6990
+ 'ais.feedContainer'
6991
+ ];
6992
+
6993
+ function isIndexWidget(widget) {
6994
+ return indexWidgetTypes.includes(widget.$$type);
6995
+ }
6996
+
6997
+ function createInitArgs(instantSearchInstance, parent, uiState) {
6998
+ var helper = parent.getHelper();
6999
+ return {
7000
+ uiState: uiState,
7001
+ helper: helper,
7002
+ parent: parent,
7003
+ instantSearchInstance: instantSearchInstance,
7004
+ state: helper.state,
7005
+ renderState: instantSearchInstance.renderState,
7006
+ templatesConfig: instantSearchInstance.templatesConfig,
7007
+ createURL: parent.createURL,
7008
+ scopedResults: [],
7009
+ searchMetadata: {
7010
+ isSearchStalled: instantSearchInstance.status === 'stalled'
7011
+ },
7012
+ status: instantSearchInstance.status,
7013
+ error: instantSearchInstance.error
7014
+ };
7015
+ }
7016
+ function createRenderArgs(instantSearchInstance, parent, widget) {
7017
+ var results = parent.getResultsForWidget(widget);
7018
+ var helper = parent.getHelper();
7019
+ return {
7020
+ helper: helper,
7021
+ parent: parent,
7022
+ instantSearchInstance: instantSearchInstance,
7023
+ results: results,
7024
+ scopedResults: parent.getScopedResults(),
7025
+ state: results && '_state' in results ? results._state : helper.state,
7026
+ renderState: instantSearchInstance.renderState,
7027
+ templatesConfig: instantSearchInstance.templatesConfig,
7028
+ createURL: parent.createURL,
7029
+ searchMetadata: {
7030
+ isSearchStalled: instantSearchInstance.status === 'stalled'
7031
+ },
7032
+ status: instantSearchInstance.status,
7033
+ error: instantSearchInstance.error
7034
+ };
7035
+ }
7036
+ function storeRenderState(param) {
7037
+ var renderState = param.renderState, instantSearchInstance = param.instantSearchInstance, parent = param.parent;
7038
+ var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
7039
+ instantSearchInstance.renderState = _object_spread_props(_object_spread({}, instantSearchInstance.renderState), _define_property({}, parentIndexName, _object_spread({}, instantSearchInstance.renderState[parentIndexName], renderState)));
7040
+ }
7041
+
7042
+ function serializeParamValue(value) {
7043
+ if (value === undefined || value === null) {
7044
+ return null;
7045
+ }
7046
+ var t = typeof value === "undefined" ? "undefined" : _type_of(value);
7047
+ if (t === 'string' || t === 'number' || t === 'boolean') {
7048
+ return {
7049
+ value: String(value),
7050
+ type: t
7051
+ };
7052
+ }
7053
+ if (Array.isArray(value) || t === 'object') {
7054
+ var type = Array.isArray(value) ? 'array' : 'object';
7055
+ try {
7056
+ return {
7057
+ value: JSON.stringify(value),
7058
+ type: type
7059
+ };
7060
+ } catch (unused) {
7061
+ return {
7062
+ type: type
7063
+ };
7064
+ }
7065
+ }
7066
+ if (t === 'function') {
7067
+ return {
7068
+ value: value.name,
7069
+ type: 'function'
7070
+ };
7071
+ }
7072
+ // symbols, DOM elements: name only
7073
+ return null;
7074
+ }
7075
+ /**
7076
+ * Turns a `widgetParams`-style record into the serialized `WidgetTreeParam[]`
7077
+ * shape used throughout the usage events. Shared between the widget tree and
7078
+ * the root `ais.instantSearch` node so every node reports params identically.
7079
+ */ function serializeWidgetParams(widgetParams) {
7080
+ var params = [];
7081
+ Object.keys(widgetParams).forEach(function(key) {
7082
+ var raw = widgetParams[key];
7083
+ if (raw === undefined) {
7084
+ return;
7085
+ }
7086
+ var serialized = serializeParamValue(raw);
7087
+ if (serialized) {
7088
+ params.push(_object_spread({
7089
+ name: key
7090
+ }, serialized));
7091
+ } else {
7092
+ params.push({
7093
+ name: key
7094
+ });
7095
+ }
7096
+ });
7097
+ return params;
7098
+ }
7099
+ function buildWidgetTree(widgets, instantSearchInstance) {
7100
+ var parent = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : instantSearchInstance.mainIndex;
7101
+ var initOptions = createInitArgs(instantSearchInstance, parent, instantSearchInstance._initialUiState);
7102
+ return widgets.map(function(widget) {
7103
+ var widgetParams = {};
7104
+ if (widget.getWidgetRenderState) {
7105
+ var renderState = widget.getWidgetRenderState(initOptions);
7106
+ if (renderState && renderState.widgetParams) {
7107
+ widgetParams = renderState.widgetParams;
7108
+ }
7109
+ }
7110
+ var params = serializeWidgetParams(widgetParams);
7111
+ var children = isIndexWidget(widget) ? buildWidgetTree(widget.getWidgets(), instantSearchInstance, widget) : [];
7112
+ return {
7113
+ type: widget.$$widgetType || widget.$$type || 'unknown',
7114
+ params: params,
7115
+ children: children
7116
+ };
7117
+ });
7118
+ }
7119
+
7120
+ /**
7121
+ * Creates a new object with the same keys as the original object, but without the excluded keys.
7122
+ * @param source original object
7123
+ * @param excluded keys to remove from the original object
7124
+ * @returns the new object
7125
+ */ function omit(source, excluded) {
7126
+ if (source === null || source === undefined) {
7127
+ return source;
7128
+ }
7129
+ return Object.keys(source).reduce(function(target, key) {
7130
+ if (excluded.indexOf(key) >= 0) {
7131
+ return target;
7132
+ }
7133
+ var validKey = key;
7134
+ target[validKey] = source[validKey];
7135
+ return target;
7136
+ }, {});
7137
+ }
7138
+
6911
7139
  // eslint-disable-next-line no-restricted-globals
6912
7140
  /**
6913
7141
  * Runs code on browser environments safely.
@@ -6981,8 +7209,20 @@
6981
7209
  }
6982
7210
  }
6983
7211
 
7212
+ function getAlgoliaAgent(client) {
7213
+ var clientTyped = client;
7214
+ return clientTyped.transporter && clientTyped.transporter.userAgent ? clientTyped.transporter.userAgent.value : clientTyped._ua;
7215
+ }
7216
+
6984
7217
  var ALGOLIA_INSIGHTS_VERSION = '2.17.2';
6985
7218
  var ALGOLIA_INSIGHTS_SRC = "https://cdn.jsdelivr.net/npm/search-insights@".concat(ALGOLIA_INSIGHTS_VERSION, "/dist/search-insights.min.js");
7219
+ // InstantSearch options that must never be sent in usage events because
7220
+ // they carry credentials or end-user data. Everything else is reported as-is.
7221
+ var SENSITIVE_OPTIONS = [
7222
+ 'searchClient',
7223
+ 'insightsClient',
7224
+ 'initialUiState'
7225
+ ];
6986
7226
  function createInsightsMiddleware() {
6987
7227
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
6988
7228
  var _insightsClient = props.insightsClient, insightsInitParams = props.insightsInitParams, onEvent = props.onEvent, _props_$$internal = props.$$internal, $$internal = _props_$$internal === void 0 ? false : _props_$$internal, _props_$$automatic = props.$$automatic, $$automatic = _props_$$automatic === void 0 ? false : _props_$$automatic;
@@ -7072,6 +7312,7 @@
7072
7312
  }
7073
7313
  var initialParameters;
7074
7314
  var helper;
7315
+ var removeStartEventListener = null;
7075
7316
  return {
7076
7317
  $$type: 'ais.insights',
7077
7318
  $$internal: $$internal,
@@ -7246,8 +7487,65 @@
7246
7487
  insightsClientWithLocalCredentials(event.insightsMethod, event.payload);
7247
7488
  } else ;
7248
7489
  };
7490
+ // usage tracking (browser-only)
7491
+ safelyRunOnBrowser(function() {
7492
+ var usageSessionId = getUsageSessionId();
7493
+ function sendUsageEvent(event) {
7494
+ var _helper_state;
7495
+ var userToken = (_helper_state = helper.state) === null || _helper_state === void 0 ? void 0 : _helper_state.userToken;
7496
+ insightsClientWithLocalCredentials('sendEvents', [
7497
+ _object_spread({
7498
+ eventType: 'instantsearch',
7499
+ timestamp: Date.now(),
7500
+ sessionID: usageSessionId,
7501
+ userToken: userToken ? String(userToken) : undefined
7502
+ }, event)
7503
+ ]);
7504
+ }
7505
+ // Send the start event on the first `render`, by which point every
7506
+ // flavor has registered its widgets. `bootstrapMs` then measures the
7507
+ // time between the constructor running and that point, so for flavors
7508
+ // that register widgets right at start (e.g. React) it captures the
7509
+ // cost of adding them.
7510
+ var sendStartEvent = function sendStartEvent() {
7511
+ try {
7512
+ var bootstrapMs = Math.round(now() - instantSearchInstance._createdAt);
7513
+ sendUsageEvent({
7514
+ eventName: '__start__',
7515
+ algoliaAgent: getAlgoliaAgent(instantSearchInstance.client),
7516
+ version: version,
7517
+ applicationId: appId,
7518
+ performance: {
7519
+ bootstrapMs: bootstrapMs
7520
+ },
7521
+ widgets: [
7522
+ {
7523
+ type: 'ais.instantSearch',
7524
+ // The options the instance was created with, serialized the
7525
+ // same way every widget's params are. Derived dynamically from
7526
+ // `_initialOptions` so new options are reported automatically,
7527
+ // minus the keys that carry credentials or user data. Functions
7528
+ // (`onStateChange`, `searchFunction`) report their `fn.name`
7529
+ // when present, tagged `type: 'function'`.
7530
+ params: instantSearchInstance._initialOptions ? serializeWidgetParams(omit(instantSearchInstance._initialOptions, _to_consumable_array(SENSITIVE_OPTIONS))) : [],
7531
+ children: buildWidgetTree(instantSearchInstance.mainIndex.getWidgets(), instantSearchInstance)
7532
+ }
7533
+ ]
7534
+ });
7535
+ } catch (unused) {
7536
+ // usage tracking must never crash the host app
7537
+ }
7538
+ };
7539
+ instantSearchInstance.once('render', sendStartEvent);
7540
+ removeStartEventListener = function removeStartEventListener() {
7541
+ return instantSearchInstance.removeListener('render', sendStartEvent);
7542
+ };
7543
+ });
7249
7544
  },
7250
7545
  unsubscribe: function unsubscribe() {
7546
+ if (removeStartEventListener) {
7547
+ removeStartEventListener();
7548
+ }
7251
7549
  insightsClient('onUserTokenChange', undefined);
7252
7550
  instantSearchInstance.sendEventToInsights = noop;
7253
7551
  if (helper && initialParameters) {
@@ -7295,67 +7593,9 @@
7295
7593
  return typeof userToken === 'number' ? userToken.toString() : userToken;
7296
7594
  }
7297
7595
 
7298
- var indexWidgetTypes = [
7299
- 'ais.index',
7300
- 'ais.feedContainer'
7301
- ];
7302
-
7303
- function isIndexWidget(widget) {
7304
- return indexWidgetTypes.includes(widget.$$type);
7305
- }
7306
-
7307
- function getAlgoliaAgent(client) {
7308
- var clientTyped = client;
7309
- return clientTyped.transporter && clientTyped.transporter.userAgent ? clientTyped.transporter.userAgent.value : clientTyped._ua;
7310
- }
7311
-
7312
- function createInitArgs(instantSearchInstance, parent, uiState) {
7313
- var helper = parent.getHelper();
7314
- return {
7315
- uiState: uiState,
7316
- helper: helper,
7317
- parent: parent,
7318
- instantSearchInstance: instantSearchInstance,
7319
- state: helper.state,
7320
- renderState: instantSearchInstance.renderState,
7321
- templatesConfig: instantSearchInstance.templatesConfig,
7322
- createURL: parent.createURL,
7323
- scopedResults: [],
7324
- searchMetadata: {
7325
- isSearchStalled: instantSearchInstance.status === 'stalled'
7326
- },
7327
- status: instantSearchInstance.status,
7328
- error: instantSearchInstance.error
7329
- };
7330
- }
7331
- function createRenderArgs(instantSearchInstance, parent, widget) {
7332
- var results = parent.getResultsForWidget(widget);
7333
- var helper = parent.getHelper();
7334
- return {
7335
- helper: helper,
7336
- parent: parent,
7337
- instantSearchInstance: instantSearchInstance,
7338
- results: results,
7339
- scopedResults: parent.getScopedResults(),
7340
- state: results && '_state' in results ? results._state : helper.state,
7341
- renderState: instantSearchInstance.renderState,
7342
- templatesConfig: instantSearchInstance.templatesConfig,
7343
- createURL: parent.createURL,
7344
- searchMetadata: {
7345
- isSearchStalled: instantSearchInstance.status === 'stalled'
7346
- },
7347
- status: instantSearchInstance.status,
7348
- error: instantSearchInstance.error
7349
- };
7350
- }
7351
- function storeRenderState(param) {
7352
- var renderState = param.renderState, instantSearchInstance = param.instantSearchInstance, parent = param.parent;
7353
- var parentIndexName = parent ? parent.getIndexId() : instantSearchInstance.mainIndex.getIndexId();
7354
- instantSearchInstance.renderState = _object_spread_props(_object_spread({}, instantSearchInstance.renderState), _define_property({}, parentIndexName, _object_spread({}, instantSearchInstance.renderState[parentIndexName], renderState)));
7355
- }
7356
-
7357
7596
  function extractWidgetPayload(widgets, instantSearchInstance, payload) {
7358
- var initOptions = createInitArgs(instantSearchInstance, instantSearchInstance.mainIndex, instantSearchInstance._initialUiState);
7597
+ var parent = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : instantSearchInstance.mainIndex;
7598
+ var initOptions = createInitArgs(instantSearchInstance, parent, instantSearchInstance._initialUiState);
7359
7599
  widgets.forEach(function(widget) {
7360
7600
  var widgetParams = {};
7361
7601
  if (widget.getWidgetRenderState) {
@@ -7375,10 +7615,11 @@
7375
7615
  params: params
7376
7616
  });
7377
7617
  if (isIndexWidget(widget)) {
7378
- extractWidgetPayload(widget.getWidgets(), instantSearchInstance, payload);
7618
+ extractWidgetPayload(widget.getWidgets(), instantSearchInstance, payload, widget);
7379
7619
  }
7380
7620
  });
7381
7621
  }
7622
+
7382
7623
  function isMetadataEnabled() {
7383
7624
  return safelyRunOnBrowser(function(param) {
7384
7625
  var window = param.window;
@@ -9777,10 +10018,11 @@
9777
10018
 
9778
10019
  var hasAlphanumeric = new RegExp(/\w/i);
9779
10020
  function getHighlightFromSiblings(parts, i) {
10021
+ var _ref, _ref1;
9780
10022
  var _parts_, _parts_1;
9781
10023
  var current = parts[i];
9782
- var isNextHighlighted = ((_parts_ = parts[i + 1]) === null || _parts_ === void 0 ? void 0 : _parts_.isHighlighted) || true;
9783
- var isPreviousHighlighted = ((_parts_1 = parts[i - 1]) === null || _parts_1 === void 0 ? void 0 : _parts_1.isHighlighted) || true;
10024
+ var isNextHighlighted = (_ref = (_parts_ = parts[i + 1]) === null || _parts_ === void 0 ? void 0 : _parts_.isHighlighted) !== null && _ref !== void 0 ? _ref : true;
10025
+ var isPreviousHighlighted = (_ref1 = (_parts_1 = parts[i - 1]) === null || _parts_1 === void 0 ? void 0 : _parts_1.isHighlighted) !== null && _ref1 !== void 0 ? _ref1 : true;
9784
10026
  if (!hasAlphanumeric.test(unescape$1(current.value)) && isPreviousHighlighted === isNextHighlighted) {
9785
10027
  return isPreviousHighlighted;
9786
10028
  }
@@ -9875,51 +10117,6 @@
9875
10117
  return reverseHighlightedValue.replace(new RegExp(TAG_REPLACEMENT.highlightPreTag, 'g'), "<".concat(highlightedTagName, ' class="').concat(className, '">')).replace(new RegExp(TAG_REPLACEMENT.highlightPostTag, 'g'), "</".concat(highlightedTagName, ">"));
9876
10118
  }
9877
10119
 
9878
- function serializePayload(payload) {
9879
- return btoa(encodeURIComponent(JSON.stringify(payload)));
9880
- }
9881
- function deserializePayload(serialized) {
9882
- return JSON.parse(decodeURIComponent(atob(serialized)));
9883
- }
9884
-
9885
- /** @deprecated use bindEvent instead */ function readDataAttributes(domElement) {
9886
- var method = domElement.getAttribute('data-insights-method');
9887
- var serializedPayload = domElement.getAttribute('data-insights-payload');
9888
- if (typeof serializedPayload !== 'string') {
9889
- throw new Error('The insights helper expects `data-insights-payload` to be a base64-encoded JSON string.');
9890
- }
9891
- try {
9892
- var payload = deserializePayload(serializedPayload);
9893
- return {
9894
- method: method,
9895
- payload: payload
9896
- };
9897
- } catch (error) {
9898
- throw new Error('The insights helper was unable to parse `data-insights-payload`.');
9899
- }
9900
- }
9901
- /** @deprecated use bindEvent instead */ function writeDataAttributes(param) {
9902
- var method = param.method, payload = param.payload;
9903
- if ((typeof payload === "undefined" ? "undefined" : _type_of(payload)) !== 'object') {
9904
- throw new Error("The insights helper expects the payload to be an object.");
9905
- }
9906
- var serializedPayload;
9907
- try {
9908
- serializedPayload = serializePayload(payload);
9909
- } catch (error) {
9910
- throw new Error("Could not JSON serialize the payload object.");
9911
- }
9912
- return 'data-insights-method="'.concat(method, '" data-insights-payload="').concat(serializedPayload, '"');
9913
- }
9914
- /**
9915
- * @deprecated This function will be still supported in 4.x releases, but not further. It is replaced by the `insights` middleware. For more information, visit https://www.algolia.com/doc/guides/getting-insights-and-analytics/search-analytics/click-through-and-conversions/how-to/send-click-and-conversion-events-with-instantsearch/js/
9916
- */ function insights(method, payload) {
9917
- return writeDataAttributes({
9918
- method: method,
9919
- payload: payload
9920
- });
9921
- }
9922
-
9923
10120
  function hoganHelpers(param) {
9924
10121
  var numberLocale = param.numberLocale;
9925
10122
  return {
@@ -9981,8 +10178,6 @@
9981
10178
  };
9982
10179
  }
9983
10180
 
9984
- var version = '4.103.0';
9985
-
9986
10181
  function getServerResults(entry) {
9987
10182
  var _entry_compositionFeedsResults;
9988
10183
  return ((_entry_compositionFeedsResults = entry.compositionFeedsResults) === null || _entry_compositionFeedsResults === void 0 ? void 0 : _entry_compositionFeedsResults.length) ? entry.compositionFeedsResults : entry.results || [];
@@ -10141,7 +10336,14 @@
10141
10336
  function InstantSearch(options) {
10142
10337
  _class_call_check(this, InstantSearch);
10143
10338
  var _this;
10144
- _this = _call_super(this, InstantSearch), _define_property(_this, "client", void 0), _define_property(_this, "indexName", void 0), _define_property(_this, "compositionID", void 0), _define_property(_this, "insightsClient", void 0), _define_property(_this, "onStateChange", null), _define_property(_this, "future", void 0), _define_property(_this, "helper", void 0), _define_property(_this, "mainHelper", void 0), _define_property(_this, "mainIndex", void 0), _define_property(_this, "started", void 0), _define_property(_this, "templatesConfig", void 0), _define_property(_this, "renderState", {}), _define_property(_this, "_stalledSearchDelay", void 0), _define_property(_this, "_searchStalledTimer", void 0), _define_property(_this, "_initialUiState", void 0), _define_property(_this, "_initialResults", void 0), _define_property(_this, "_manuallyResetScheduleSearch", false), _define_property(_this, "_resetScheduleSearch", void 0), _define_property(_this, "_createURL", void 0), _define_property(_this, "_searchFunction", void 0), _define_property(_this, "_mainHelperSearch", void 0), _define_property(_this, "_hasSearchWidget", false), _define_property(_this, "_hasRecommendWidget", false), _define_property(_this, "_insights", void 0), _define_property(_this, "middleware", []), _define_property(_this, "sendEventToInsights", void 0), /**
10339
+ _this = _call_super(this, InstantSearch), _define_property(_this, "client", void 0), _define_property(_this, "indexName", void 0), _define_property(_this, "compositionID", void 0), _define_property(_this, "insightsClient", void 0), _define_property(_this, "onStateChange", null), _define_property(_this, "future", void 0), _define_property(_this, "helper", void 0), _define_property(_this, "mainHelper", void 0), _define_property(_this, "mainIndex", void 0), _define_property(_this, "started", void 0), _define_property(_this, "templatesConfig", void 0), _define_property(_this, "renderState", {}), _define_property(_this, "_stalledSearchDelay", void 0), _define_property(_this, "_searchStalledTimer", void 0), _define_property(_this, "_initialUiState", void 0), _define_property(_this, "_initialResults", void 0), _define_property(_this, "_manuallyResetScheduleSearch", false), _define_property(_this, "_resetScheduleSearch", void 0), _define_property(_this, "_createURL", void 0), _define_property(_this, "_searchFunction", void 0), _define_property(_this, "_mainHelperSearch", void 0), _define_property(_this, "_hasSearchWidget", false), _define_property(_this, "_hasRecommendWidget", false), _define_property(_this, "_insights", void 0), /**
10340
+ * The options the instance was created with, kept verbatim so consumers
10341
+ * (e.g. usage events) can introspect the configuration without the class
10342
+ * having to enumerate every option by hand. Typed without the class generics
10343
+ * on purpose: referencing `TUiState`/`TRouteState` here (they sit in
10344
+ * contravariant positions inside `InstantSearchOptions`) would break the
10345
+ * assignability of `InstantSearch<SpecificUiState>` to `InstantSearch`.
10346
+ */ _define_property(_this, "_initialOptions", void 0), _define_property(_this, "middleware", []), _define_property(_this, "sendEventToInsights", void 0), _define_property(_this, "_createdAt", now()), /**
10145
10347
  * The status of the search. Can be "idle", "loading", "stalled", or "error".
10146
10348
  */ _define_property(_this, "status", 'idle'), /**
10147
10349
  * The last returned error from the Search API.
@@ -10189,6 +10391,7 @@
10189
10391
  if (insightsClient && typeof insightsClient !== 'function') {
10190
10392
  throw new Error(withUsage$J('The `insightsClient` option should be a function.'));
10191
10393
  }
10394
+ _this._initialOptions = options;
10192
10395
  _this.client = searchClient;
10193
10396
  _this.future = future;
10194
10397
  _this.insightsClient = insightsClient;
@@ -10561,6 +10764,9 @@
10561
10764
  var instance = param.instance;
10562
10765
  instance.unsubscribe();
10563
10766
  });
10767
+ // Cleared after unsubscribe so in-flight readers (e.g. the insights
10768
+ // start-event listener) have detached before the reference goes away.
10769
+ this._initialOptions = null;
10564
10770
  }
10565
10771
  },
10566
10772
  {
@@ -11142,25 +11348,6 @@
11142
11348
  return widget.$$type === 'ais.dynamicWidgets' || widget.$$type === 'ais.feeds';
11143
11349
  }
11144
11350
 
11145
- /**
11146
- * Creates a new object with the same keys as the original object, but without the excluded keys.
11147
- * @param source original object
11148
- * @param excluded keys to remove from the original object
11149
- * @returns the new object
11150
- */ function omit(source, excluded) {
11151
- if (source === null || source === undefined) {
11152
- return source;
11153
- }
11154
- return Object.keys(source).reduce(function(target, key) {
11155
- if (excluded.indexOf(key) >= 0) {
11156
- return target;
11157
- }
11158
- var validKey = key;
11159
- target[validKey] = source[validKey];
11160
- return target;
11161
- }, {});
11162
- }
11163
-
11164
11351
  function range(param) {
11165
11352
  var _param_start = param.start, start = _param_start === void 0 ? 0 : _param_start, end = param.end, _param_step = param.step, step = _param_step === void 0 ? 1 : _param_step;
11166
11353
  // We can't divide by 0 so we re-assign the step to 1 if it happens.
@@ -13962,6 +14149,8 @@
13962
14149
  isSearchStalled: false,
13963
14150
  disabled: false,
13964
14151
  ariaLabel: 'Search',
14152
+ submitTitle: 'Submit the search query',
14153
+ resetTitle: 'Clear the search query',
13965
14154
  onChange: noop,
13966
14155
  onSubmit: noop,
13967
14156
  onReset: noop,
@@ -14101,7 +14290,8 @@
14101
14290
  rootProps: {
14102
14291
  className: cssClasses.submit,
14103
14292
  type: 'submit',
14104
- title: 'Submit the search query',
14293
+ title: this.props.submitTitle,
14294
+ 'aria-label': this.props.submitTitle,
14105
14295
  hidden: !showSubmit
14106
14296
  },
14107
14297
  templates: templates,
@@ -14114,7 +14304,8 @@
14114
14304
  rootProps: {
14115
14305
  className: cssClasses.reset,
14116
14306
  type: 'reset',
14117
- title: 'Clear the search query',
14307
+ title: this.props.resetTitle,
14308
+ 'aria-label': this.props.resetTitle,
14118
14309
  hidden: !(showReset && this.state.query.trim() && !isSearchStalled)
14119
14310
  },
14120
14311
  templates: templates,
@@ -14339,7 +14530,9 @@
14339
14530
  rootProps: {
14340
14531
  className: showMoreButtonClassName,
14341
14532
  disabled: !this.props.canToggleShowMore,
14342
- onClick: this.props.toggleShowMore
14533
+ onClick: this.props.toggleShowMore,
14534
+ 'aria-expanded': Boolean(this.props.isShowingMore),
14535
+ 'aria-label': this.props.showMoreButtonLabel
14343
14536
  },
14344
14537
  data: {
14345
14538
  isShowingMore: this.props.isShowingMore
@@ -16479,6 +16672,7 @@
16479
16672
  rootProps: {
16480
16673
  className: cssClasses.link,
16481
16674
  'aria-label': ariaLabel,
16675
+ 'aria-current': isSelected ? 'page' : undefined,
16482
16676
  href: createURL(pageNumber),
16483
16677
  onClick: createClickHandler(pageNumber)
16484
16678
  },
@@ -19049,7 +19243,7 @@
19049
19243
  var suit$4 = component('RefinementList');
19050
19244
  var searchBoxSuit = component('SearchBox');
19051
19245
  var renderer$6 = function renderer(param) {
19052
- var containerNode = param.containerNode, cssClasses = param.cssClasses, templates = param.templates, searchBoxTemplates = param.searchBoxTemplates, renderState = param.renderState, showMore = param.showMore, searchable = param.searchable, searchablePlaceholder = param.searchablePlaceholder, searchableIsAlwaysActive = param.searchableIsAlwaysActive, searchableSelectOnSubmit = param.searchableSelectOnSubmit;
19246
+ var containerNode = param.containerNode, cssClasses = param.cssClasses, templates = param.templates, searchBoxTemplates = param.searchBoxTemplates, renderState = param.renderState, showMore = param.showMore, showMoreButtonLabel = param.showMoreButtonLabel, searchable = param.searchable, searchablePlaceholder = param.searchablePlaceholder, searchableIsAlwaysActive = param.searchableIsAlwaysActive, searchableSelectOnSubmit = param.searchableSelectOnSubmit;
19053
19247
  return function(param, isFirstRendering) {
19054
19248
  var refine = param.refine, items = param.items, createURL = param.createURL, searchForItems = param.searchForItems, isFromSearch = param.isFromSearch, instantSearchInstance = param.instantSearchInstance, toggleShowMore = param.toggleShowMore, isShowingMore = param.isShowingMore, hasExhaustiveItems = param.hasExhaustiveItems, canToggleShowMore = param.canToggleShowMore;
19055
19249
  if (isFirstRendering) {
@@ -19077,6 +19271,7 @@
19077
19271
  searchIsAlwaysActive: searchableIsAlwaysActive,
19078
19272
  isFromSearch: isFromSearch,
19079
19273
  showMore: showMore && !isFromSearch && items.length > 0,
19274
+ showMoreButtonLabel: showMoreButtonLabel,
19080
19275
  toggleShowMore: toggleShowMore,
19081
19276
  isShowingMore: isShowingMore,
19082
19277
  hasExhaustiveItems: hasExhaustiveItems,
@@ -19104,7 +19299,7 @@
19104
19299
  *
19105
19300
  * If you also want to use search for facet values on this attribute, you need to make it searchable using the [dashboard](https://www.algolia.com/explorer/display/) or using the [API](https://www.algolia.com/doc/guides/searching/faceting/#search-for-facet-values).
19106
19301
  */ var refinementList = function refinementList(widgetParams) {
19107
- var _ref = widgetParams || {}, container = _ref.container, attribute = _ref.attribute, operator = _ref.operator, sortBy = _ref.sortBy, limit = _ref.limit, showMore = _ref.showMore, showMoreLimit = _ref.showMoreLimit, _ref_searchable = _ref.searchable, searchable = _ref_searchable === void 0 ? false : _ref_searchable, _ref_searchablePlaceholder = _ref.searchablePlaceholder, searchablePlaceholder = _ref_searchablePlaceholder === void 0 ? 'Search...' : _ref_searchablePlaceholder, _ref_searchableEscapeFacetValues = _ref.searchableEscapeFacetValues, searchableEscapeFacetValues = _ref_searchableEscapeFacetValues === void 0 ? true : _ref_searchableEscapeFacetValues, _ref_searchableIsAlwaysActive = _ref.searchableIsAlwaysActive, searchableIsAlwaysActive = _ref_searchableIsAlwaysActive === void 0 ? true : _ref_searchableIsAlwaysActive, _ref_searchableSelectOnSubmit = _ref.searchableSelectOnSubmit, searchableSelectOnSubmit = _ref_searchableSelectOnSubmit === void 0 ? true : _ref_searchableSelectOnSubmit, tmp = _ref.cssClasses, userCssClasses = tmp === void 0 ? {} : tmp, _ref_templates = _ref.templates, templates = _ref_templates === void 0 ? {} : _ref_templates, transformItems = _ref.transformItems;
19302
+ var _ref = widgetParams || {}, container = _ref.container, attribute = _ref.attribute, operator = _ref.operator, sortBy = _ref.sortBy, limit = _ref.limit, showMore = _ref.showMore, showMoreLimit = _ref.showMoreLimit, showMoreButtonLabel = _ref.showMoreButtonLabel, _ref_searchable = _ref.searchable, searchable = _ref_searchable === void 0 ? false : _ref_searchable, _ref_searchablePlaceholder = _ref.searchablePlaceholder, searchablePlaceholder = _ref_searchablePlaceholder === void 0 ? 'Search...' : _ref_searchablePlaceholder, _ref_searchableEscapeFacetValues = _ref.searchableEscapeFacetValues, searchableEscapeFacetValues = _ref_searchableEscapeFacetValues === void 0 ? true : _ref_searchableEscapeFacetValues, _ref_searchableIsAlwaysActive = _ref.searchableIsAlwaysActive, searchableIsAlwaysActive = _ref_searchableIsAlwaysActive === void 0 ? true : _ref_searchableIsAlwaysActive, _ref_searchableSelectOnSubmit = _ref.searchableSelectOnSubmit, searchableSelectOnSubmit = _ref_searchableSelectOnSubmit === void 0 ? true : _ref_searchableSelectOnSubmit, tmp = _ref.cssClasses, userCssClasses = tmp === void 0 ? {} : tmp, _ref_templates = _ref.templates, templates = _ref_templates === void 0 ? {} : _ref_templates, transformItems = _ref.transformItems;
19108
19303
  if (!container) {
19109
19304
  throw new Error(withUsage$d('The `container` option is required.'));
19110
19305
  }
@@ -19192,7 +19387,8 @@
19192
19387
  searchablePlaceholder: searchablePlaceholder,
19193
19388
  searchableIsAlwaysActive: searchableIsAlwaysActive,
19194
19389
  searchableSelectOnSubmit: searchableSelectOnSubmit,
19195
- showMore: showMore
19390
+ showMore: showMore,
19391
+ showMoreButtonLabel: showMoreButtonLabel
19196
19392
  });
19197
19393
  var makeWidget = connectRefinementList(specializedRenderer, function() {
19198
19394
  return P(null, containerNode);
@@ -19217,7 +19413,7 @@
19217
19413
  var suit$3 = component('SearchBox');
19218
19414
  var aiModeSuit = component('AiModeButton');
19219
19415
  var renderer$5 = function renderer(param) {
19220
- var containerNode = param.containerNode, cssClasses = param.cssClasses, placeholder = param.placeholder, templates = param.templates, autofocus = param.autofocus, searchAsYouType = param.searchAsYouType, ignoreCompositionEvents = param.ignoreCompositionEvents, showReset = param.showReset, showSubmit = param.showSubmit, showLoadingIndicator = param.showLoadingIndicator, aiMode = param.aiMode;
19416
+ var containerNode = param.containerNode, cssClasses = param.cssClasses, placeholder = param.placeholder, templates = param.templates, autofocus = param.autofocus, searchAsYouType = param.searchAsYouType, ignoreCompositionEvents = param.ignoreCompositionEvents, showReset = param.showReset, showSubmit = param.showSubmit, showLoadingIndicator = param.showLoadingIndicator, submitTitle = param.submitTitle, resetTitle = param.resetTitle, aiMode = param.aiMode;
19221
19417
  return function(param) {
19222
19418
  var refine = param.refine, query = param.query, isSearchStalled = param.isSearchStalled, instantSearchInstance = param.instantSearchInstance;
19223
19419
  var getChatRenderState = function getChatRenderState() {
@@ -19245,6 +19441,8 @@
19245
19441
  showSubmit: showSubmit,
19246
19442
  showReset: showReset,
19247
19443
  showLoadingIndicator: showLoadingIndicator,
19444
+ submitTitle: submitTitle,
19445
+ resetTitle: resetTitle,
19248
19446
  isSearchStalled: isSearchStalled,
19249
19447
  cssClasses: cssClasses,
19250
19448
  onAiModeClick: onAiModeClick,
@@ -19253,7 +19451,7 @@
19253
19451
  };
19254
19452
  };
19255
19453
  var searchBox = function searchBox(widgetParams) {
19256
- var _ref = widgetParams || {}, container = _ref.container, _ref_placeholder = _ref.placeholder, placeholder = _ref_placeholder === void 0 ? '' : _ref_placeholder, tmp = _ref.cssClasses, userCssClasses = tmp === void 0 ? {} : tmp, _ref_autofocus = _ref.autofocus, autofocus = _ref_autofocus === void 0 ? false : _ref_autofocus, _ref_searchAsYouType = _ref.searchAsYouType, searchAsYouType = _ref_searchAsYouType === void 0 ? true : _ref_searchAsYouType, _ref_ignoreCompositionEvents = _ref.ignoreCompositionEvents, ignoreCompositionEvents = _ref_ignoreCompositionEvents === void 0 ? false : _ref_ignoreCompositionEvents, _ref_showReset = _ref.showReset, showReset = _ref_showReset === void 0 ? true : _ref_showReset, _ref_showSubmit = _ref.showSubmit, showSubmit = _ref_showSubmit === void 0 ? true : _ref_showSubmit, _ref_showLoadingIndicator = _ref.showLoadingIndicator, showLoadingIndicator = _ref_showLoadingIndicator === void 0 ? true : _ref_showLoadingIndicator, queryHook = _ref.queryHook, tmp1 = _ref.templates, userTemplates = tmp1 === void 0 ? {} : tmp1, aiMode = _ref.aiMode;
19454
+ var _ref = widgetParams || {}, container = _ref.container, _ref_placeholder = _ref.placeholder, placeholder = _ref_placeholder === void 0 ? '' : _ref_placeholder, tmp = _ref.cssClasses, userCssClasses = tmp === void 0 ? {} : tmp, _ref_autofocus = _ref.autofocus, autofocus = _ref_autofocus === void 0 ? false : _ref_autofocus, _ref_searchAsYouType = _ref.searchAsYouType, searchAsYouType = _ref_searchAsYouType === void 0 ? true : _ref_searchAsYouType, _ref_ignoreCompositionEvents = _ref.ignoreCompositionEvents, ignoreCompositionEvents = _ref_ignoreCompositionEvents === void 0 ? false : _ref_ignoreCompositionEvents, _ref_showReset = _ref.showReset, showReset = _ref_showReset === void 0 ? true : _ref_showReset, _ref_showSubmit = _ref.showSubmit, showSubmit = _ref_showSubmit === void 0 ? true : _ref_showSubmit, _ref_showLoadingIndicator = _ref.showLoadingIndicator, showLoadingIndicator = _ref_showLoadingIndicator === void 0 ? true : _ref_showLoadingIndicator, _ref_submitTitle = _ref.submitTitle, submitTitle = _ref_submitTitle === void 0 ? 'Submit the search query' : _ref_submitTitle, _ref_resetTitle = _ref.resetTitle, resetTitle = _ref_resetTitle === void 0 ? 'Clear the search query' : _ref_resetTitle, queryHook = _ref.queryHook, tmp1 = _ref.templates, userTemplates = tmp1 === void 0 ? {} : tmp1, aiMode = _ref.aiMode;
19257
19455
  if (!container) {
19258
19456
  throw new Error(withUsage$c('The `container` option is required.'));
19259
19457
  }
@@ -19304,6 +19502,8 @@
19304
19502
  showReset: showReset,
19305
19503
  showSubmit: showSubmit,
19306
19504
  showLoadingIndicator: showLoadingIndicator,
19505
+ submitTitle: submitTitle,
19506
+ resetTitle: resetTitle,
19307
19507
  aiMode: aiMode
19308
19508
  });
19309
19509
  var widgetFactory = connectSearchBox(specializedRenderer, function() {
@@ -19537,13 +19737,70 @@
19537
19737
  });
19538
19738
  };
19539
19739
 
19740
+ // Delay before announcing an update, so that rapid changes (e.g. typing in the
19741
+ // search box) settle into a single announcement instead of piling up. Mirrors
19742
+ // the debounce used by GOV.UK's accessible-autocomplete.
19743
+ var ANNOUNCEMENT_DELAY = 1400;
19744
+ var visuallyHiddenStyle = {
19745
+ position: 'absolute',
19746
+ width: '1px',
19747
+ height: '1px',
19748
+ padding: 0,
19749
+ margin: '-1px',
19750
+ overflow: 'hidden',
19751
+ clip: 'rect(0, 0, 0, 0)',
19752
+ whiteSpace: 'nowrap',
19753
+ border: 0
19754
+ };
19755
+ // Result count without the volatile details (such as the processing time) that
19756
+ // are part of the visible text, so that only the meaningful count is announced.
19757
+ function getAnnouncement(nbHits, nbSortedHits, areHitsSorted) {
19758
+ if (areHitsSorted) {
19759
+ var suffix = "sorted out of ".concat(formatNumber(nbHits));
19760
+ if (nbSortedHits === 0) {
19761
+ return "No relevant results ".concat(suffix);
19762
+ }
19763
+ if (nbSortedHits === 1) {
19764
+ return "1 relevant result ".concat(suffix);
19765
+ }
19766
+ return "".concat(formatNumber(nbSortedHits || 0), " relevant results ").concat(suffix);
19767
+ }
19768
+ if (nbHits === 0) {
19769
+ return 'No results';
19770
+ }
19771
+ if (nbHits === 1) {
19772
+ return '1 result';
19773
+ }
19774
+ return "".concat(formatNumber(nbHits), " results");
19775
+ }
19540
19776
  var Stats = function Stats(_0) {
19541
- var nbHits = _0.nbHits, nbSortedHits = _0.nbSortedHits, cssClasses = _0.cssClasses, templateProps = _0.templateProps, rest = _object_without_properties(_0, [
19777
+ var nbHits = _0.nbHits, nbSortedHits = _0.nbSortedHits, areHitsSorted = _0.areHitsSorted, cssClasses = _0.cssClasses, templateProps = _0.templateProps, rest = _object_without_properties(_0, [
19542
19778
  "nbHits",
19543
19779
  "nbSortedHits",
19780
+ "areHitsSorted",
19544
19781
  "cssClasses",
19545
19782
  "templateProps"
19546
19783
  ]);
19784
+ var nextAnnouncement = getAnnouncement(nbHits, nbSortedHits, areHitsSorted);
19785
+ var _useState = _sliced_to_array(y(''), 2), announcement = _useState[0], setAnnouncement = _useState[1];
19786
+ var timerRef = A();
19787
+ var isInitialRef = A(true);
19788
+ s(function() {
19789
+ // Don't announce the initial results, only subsequent changes.
19790
+ if (isInitialRef.current) {
19791
+ isInitialRef.current = false;
19792
+ return undefined;
19793
+ }
19794
+ clearTimeout(timerRef.current);
19795
+ timerRef.current = setTimeout(function() {
19796
+ setAnnouncement(nextAnnouncement);
19797
+ }, ANNOUNCEMENT_DELAY);
19798
+ return function() {
19799
+ return clearTimeout(timerRef.current);
19800
+ };
19801
+ }, [
19802
+ nextAnnouncement
19803
+ ]);
19547
19804
  return /*#__PURE__*/ h$1("div", {
19548
19805
  className: cx(cssClasses.root)
19549
19806
  }, /*#__PURE__*/ h$1(Template, _object_spread_props(_object_spread({}, templateProps), {
@@ -19561,9 +19818,16 @@
19561
19818
  hasOneResult: nbHits === 1,
19562
19819
  nbHits: nbHits,
19563
19820
  nbSortedHits: nbSortedHits,
19821
+ areHitsSorted: areHitsSorted,
19564
19822
  cssClasses: cssClasses
19565
19823
  }, rest)
19566
- })));
19824
+ })), /*#__PURE__*/ h$1("span", {
19825
+ className: "ais-Stats-announcement",
19826
+ role: "status",
19827
+ "aria-live": "polite",
19828
+ "aria-atomic": "true",
19829
+ style: visuallyHiddenStyle
19830
+ }, announcement));
19567
19831
  };
19568
19832
 
19569
19833
  var withUsage$9 = createDocumentationMessageGenerator({