react-instantsearch 7.38.0 → 7.39.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.
@@ -1,4 +1,4 @@
1
- /*! React InstantSearch 7.38.0 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
1
+ /*! React InstantSearch 7.39.0 | © Algolia, Inc. and contributors; MIT License | https://github.com/algolia/instantsearch */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
4
4
  typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
@@ -24,7 +24,7 @@
24
24
 
25
25
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
26
26
 
27
- var version$2 = '7.38.0';
27
+ var version$2 = '7.39.0';
28
28
 
29
29
  function _define_property(obj, key, value) {
30
30
  if (key in obj) {
@@ -571,10 +571,10 @@
571
571
  return objectHasKeys_1;
572
572
  }
573
573
 
574
- var omit;
574
+ var omit$1;
575
575
  var hasRequiredOmit;
576
576
  function requireOmit() {
577
- if (hasRequiredOmit) return omit;
577
+ if (hasRequiredOmit) return omit$1;
578
578
  hasRequiredOmit = 1;
579
579
  // https://github.com/babel/babel/blob/3aaafae053fa75febb3aa45d45b6f00646e30ba4/packages/babel-helpers/src/helpers.js#L604-L620
580
580
  function _objectWithoutPropertiesLoose(source, excluded) {
@@ -591,8 +591,8 @@
591
591
  }
592
592
  return target;
593
593
  }
594
- omit = _objectWithoutPropertiesLoose;
595
- return omit;
594
+ omit$1 = _objectWithoutPropertiesLoose;
595
+ return omit$1;
596
596
  }
597
597
 
598
598
  var RecommendParameters_1;
@@ -3919,7 +3919,7 @@
3919
3919
  function requireVersion() {
3920
3920
  if (hasRequiredVersion) return version$1;
3921
3921
  hasRequiredVersion = 1;
3922
- version$1 = '3.29.1';
3922
+ version$1 = '3.29.2';
3923
3923
  return version$1;
3924
3924
  }
3925
3925
 
@@ -7259,19 +7259,23 @@
7259
7259
  * This is used to log issues in development environment only.
7260
7260
  */ var warn = noop;
7261
7261
 
7262
- function range(param) {
7263
- 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;
7264
- // We can't divide by 0 so we re-assign the step to 1 if it happens.
7265
- var limitStep = step === 0 ? 1 : step;
7266
- // In some cases the array to create has a decimal length.
7267
- // We therefore need to round the value.
7268
- // Example:
7269
- // { start: 1, end: 5000, step: 500 }
7270
- // => Array length = (5000 - 1) / 500 = 9.998
7271
- var arrayLength = Math.round((end - start) / limitStep);
7272
- return _to_consumable_array(Array(arrayLength)).map(function(_, current) {
7273
- return start + current * limitStep;
7274
- });
7262
+ /**
7263
+ * Creates a new object with the same keys as the original object, but without the excluded keys.
7264
+ * @param source original object
7265
+ * @param excluded keys to remove from the original object
7266
+ * @returns the new object
7267
+ */ function omit(source, excluded) {
7268
+ if (source === null || source === undefined) {
7269
+ return source;
7270
+ }
7271
+ return Object.keys(source).reduce(function(target, key) {
7272
+ if (excluded.indexOf(key) >= 0) {
7273
+ return target;
7274
+ }
7275
+ var validKey = key;
7276
+ target[validKey] = source[validKey];
7277
+ return target;
7278
+ }, {});
7275
7279
  }
7276
7280
 
7277
7281
  function createInitArgs(instantSearchInstance, parent, uiState) {
@@ -7319,6 +7323,132 @@
7319
7323
  instantSearchInstance.renderState = _object_spread_props(_object_spread({}, instantSearchInstance.renderState), _define_property({}, parentIndexName, _object_spread({}, instantSearchInstance.renderState[parentIndexName], renderState)));
7320
7324
  }
7321
7325
 
7326
+ function serializeParamValue(value) {
7327
+ if (value === undefined || value === null) {
7328
+ return null;
7329
+ }
7330
+ var t = typeof value === "undefined" ? "undefined" : _type_of(value);
7331
+ if (t === 'string' || t === 'number' || t === 'boolean') {
7332
+ return {
7333
+ value: String(value),
7334
+ type: t
7335
+ };
7336
+ }
7337
+ if (Array.isArray(value) || t === 'object') {
7338
+ var type = Array.isArray(value) ? 'array' : 'object';
7339
+ try {
7340
+ return {
7341
+ value: JSON.stringify(value),
7342
+ type: type
7343
+ };
7344
+ } catch (unused) {
7345
+ return {
7346
+ type: type
7347
+ };
7348
+ }
7349
+ }
7350
+ if (t === 'function') {
7351
+ return {
7352
+ value: value.name,
7353
+ type: 'function'
7354
+ };
7355
+ }
7356
+ // symbols, DOM elements: name only
7357
+ return null;
7358
+ }
7359
+ /**
7360
+ * Turns a `widgetParams`-style record into the serialized `WidgetTreeParam[]`
7361
+ * shape used throughout the usage events. Shared between the widget tree and
7362
+ * the root `ais.instantSearch` node so every node reports params identically.
7363
+ */ function serializeWidgetParams(widgetParams) {
7364
+ var params = [];
7365
+ Object.keys(widgetParams).forEach(function(key) {
7366
+ var raw = widgetParams[key];
7367
+ if (raw === undefined) {
7368
+ return;
7369
+ }
7370
+ var serialized = serializeParamValue(raw);
7371
+ if (serialized) {
7372
+ params.push(_object_spread({
7373
+ name: key
7374
+ }, serialized));
7375
+ } else {
7376
+ params.push({
7377
+ name: key
7378
+ });
7379
+ }
7380
+ });
7381
+ return params;
7382
+ }
7383
+ function buildWidgetTree(widgets, instantSearchInstance) {
7384
+ var parent = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : instantSearchInstance.mainIndex;
7385
+ var initOptions = createInitArgs(instantSearchInstance, parent, instantSearchInstance._initialUiState);
7386
+ return widgets.map(function(widget) {
7387
+ var widgetParams = {};
7388
+ if (widget.getWidgetRenderState) {
7389
+ var renderState = widget.getWidgetRenderState(initOptions);
7390
+ if (renderState && renderState.widgetParams) {
7391
+ widgetParams = renderState.widgetParams;
7392
+ }
7393
+ }
7394
+ var params = serializeWidgetParams(widgetParams);
7395
+ var children = isIndexWidget(widget) ? buildWidgetTree(widget.getWidgets(), instantSearchInstance, widget) : [];
7396
+ return {
7397
+ type: widget.$$widgetType || widget.$$type || 'unknown',
7398
+ params: params,
7399
+ children: children
7400
+ };
7401
+ });
7402
+ }
7403
+
7404
+ function extractWidgetPayload(widgets, instantSearchInstance, payload) {
7405
+ var parent = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : instantSearchInstance.mainIndex;
7406
+ var initOptions = createInitArgs(instantSearchInstance, parent, instantSearchInstance._initialUiState);
7407
+ widgets.forEach(function(widget) {
7408
+ var widgetParams = {};
7409
+ if (widget.getWidgetRenderState) {
7410
+ var renderState = widget.getWidgetRenderState(initOptions);
7411
+ if (renderState && renderState.widgetParams) {
7412
+ // casting, as we just earlier checked widgetParams exists, and thus an object
7413
+ widgetParams = renderState.widgetParams;
7414
+ }
7415
+ }
7416
+ // since we destructure in all widgets, the parameters with defaults are set to "undefined"
7417
+ var params = Object.keys(widgetParams).filter(function(key) {
7418
+ return widgetParams[key] !== undefined;
7419
+ });
7420
+ payload.widgets.push({
7421
+ type: widget.$$type,
7422
+ widgetType: widget.$$widgetType,
7423
+ params: params
7424
+ });
7425
+ if (isIndexWidget(widget)) {
7426
+ extractWidgetPayload(widget.getWidgets(), instantSearchInstance, payload, widget);
7427
+ }
7428
+ });
7429
+ }
7430
+
7431
+ var now = typeof performance !== 'undefined' ? function() {
7432
+ return performance.now();
7433
+ } : function() {
7434
+ return Date.now();
7435
+ };
7436
+
7437
+ function range(param) {
7438
+ 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;
7439
+ // We can't divide by 0 so we re-assign the step to 1 if it happens.
7440
+ var limitStep = step === 0 ? 1 : step;
7441
+ // In some cases the array to create has a decimal length.
7442
+ // We therefore need to round the value.
7443
+ // Example:
7444
+ // { start: 1, end: 5000, step: 500 }
7445
+ // => Array length = (5000 - 1) / 500 = 9.998
7446
+ var arrayLength = Math.round((end - start) / limitStep);
7447
+ return _to_consumable_array(Array(arrayLength)).map(function(_, current) {
7448
+ return start + current * limitStep;
7449
+ });
7450
+ }
7451
+
7322
7452
  function resolveSearchParameters(current) {
7323
7453
  var parent = current.getParent();
7324
7454
  var states = [
@@ -9030,6 +9160,8 @@
9030
9160
  });
9031
9161
  }
9032
9162
 
9163
+ var version = '4.105.0';
9164
+
9033
9165
  var ANONYMOUS_TOKEN_COOKIE_KEY = '_ALGOLIA';
9034
9166
  function getCookie(name) {
9035
9167
  if ((typeof document === "undefined" ? "undefined" : _type_of(document)) !== 'object' || typeof document.cookie !== 'string') {
@@ -9052,8 +9184,61 @@
9052
9184
  return getCookie(ANONYMOUS_TOKEN_COOKIE_KEY);
9053
9185
  }
9054
9186
 
9187
+ var USAGE_SESSION_KEY = 'ais.usage.sessionId';
9188
+ // Cache the id for the lifetime of the runtime so repeated calls don't hit
9189
+ // `sessionStorage` again, and so we always return the same id even when
9190
+ // storage is unavailable (SSR, privacy mode) and we fall back to a fresh UUID.
9191
+ var usageSessionId = null;
9192
+ function getUsageSessionId() {
9193
+ if (usageSessionId) {
9194
+ return usageSessionId;
9195
+ }
9196
+ try {
9197
+ var existing = sessionStorage.getItem(USAGE_SESSION_KEY);
9198
+ if (existing) {
9199
+ usageSessionId = existing;
9200
+ return usageSessionId;
9201
+ }
9202
+ usageSessionId = createUUID();
9203
+ sessionStorage.setItem(USAGE_SESSION_KEY, usageSessionId);
9204
+ return usageSessionId;
9205
+ } catch (unused) {
9206
+ // sessionStorage unavailable (SSR, privacy mode, etc.)
9207
+ usageSessionId = createUUID();
9208
+ return usageSessionId;
9209
+ }
9210
+ }
9211
+ /** @deprecated use bindEvent instead */ function writeDataAttributes(param) {
9212
+ var method = param.method, payload = param.payload;
9213
+ if ((typeof payload === "undefined" ? "undefined" : _type_of(payload)) !== 'object') {
9214
+ throw new Error("The insights helper expects the payload to be an object.");
9215
+ }
9216
+ var serializedPayload;
9217
+ try {
9218
+ serializedPayload = serializePayload(payload);
9219
+ } catch (error) {
9220
+ throw new Error("Could not JSON serialize the payload object.");
9221
+ }
9222
+ return 'data-insights-method="'.concat(method, '" data-insights-payload="').concat(serializedPayload, '"');
9223
+ }
9224
+ /**
9225
+ * @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/
9226
+ */ function insights(method, payload) {
9227
+ return writeDataAttributes({
9228
+ method: method,
9229
+ payload: payload
9230
+ });
9231
+ }
9232
+
9055
9233
  var ALGOLIA_INSIGHTS_VERSION = '2.17.2';
9056
9234
  var ALGOLIA_INSIGHTS_SRC = "https://cdn.jsdelivr.net/npm/search-insights@".concat(ALGOLIA_INSIGHTS_VERSION, "/dist/search-insights.min.js");
9235
+ // InstantSearch options that must never be sent in usage events because
9236
+ // they carry credentials or end-user data. Everything else is reported as-is.
9237
+ var SENSITIVE_OPTIONS = [
9238
+ 'searchClient',
9239
+ 'insightsClient',
9240
+ 'initialUiState'
9241
+ ];
9057
9242
  function createInsightsMiddleware() {
9058
9243
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
9059
9244
  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;
@@ -9143,6 +9328,7 @@
9143
9328
  }
9144
9329
  var initialParameters;
9145
9330
  var helper;
9331
+ var removeStartEventListener = null;
9146
9332
  return {
9147
9333
  $$type: 'ais.insights',
9148
9334
  $$internal: $$internal,
@@ -9317,8 +9503,65 @@
9317
9503
  insightsClientWithLocalCredentials(event.insightsMethod, event.payload);
9318
9504
  } else ;
9319
9505
  };
9506
+ // usage tracking (browser-only)
9507
+ safelyRunOnBrowser(function() {
9508
+ var usageSessionId = getUsageSessionId();
9509
+ function sendUsageEvent(event) {
9510
+ var _helper_state;
9511
+ var userToken = (_helper_state = helper.state) === null || _helper_state === void 0 ? void 0 : _helper_state.userToken;
9512
+ insightsClientWithLocalCredentials('sendEvents', [
9513
+ _object_spread({
9514
+ eventType: 'instantsearch',
9515
+ timestamp: Date.now(),
9516
+ sessionID: usageSessionId,
9517
+ userToken: userToken ? String(userToken) : undefined
9518
+ }, event)
9519
+ ]);
9520
+ }
9521
+ // Send the start event on the first `render`, by which point every
9522
+ // flavor has registered its widgets. `bootstrapMs` then measures the
9523
+ // time between the constructor running and that point, so for flavors
9524
+ // that register widgets right at start (e.g. React) it captures the
9525
+ // cost of adding them.
9526
+ var sendStartEvent = function sendStartEvent() {
9527
+ try {
9528
+ var bootstrapMs = Math.round(now() - instantSearchInstance._createdAt);
9529
+ sendUsageEvent({
9530
+ eventName: '__start__',
9531
+ algoliaAgent: getAlgoliaAgent(instantSearchInstance.client),
9532
+ version: version,
9533
+ applicationId: appId,
9534
+ performance: {
9535
+ bootstrapMs: bootstrapMs
9536
+ },
9537
+ widgets: [
9538
+ {
9539
+ type: 'ais.instantSearch',
9540
+ // The options the instance was created with, serialized the
9541
+ // same way every widget's params are. Derived dynamically from
9542
+ // `_initialOptions` so new options are reported automatically,
9543
+ // minus the keys that carry credentials or user data. Functions
9544
+ // (`onStateChange`, `searchFunction`) report their `fn.name`
9545
+ // when present, tagged `type: 'function'`.
9546
+ params: instantSearchInstance._initialOptions ? serializeWidgetParams(omit(instantSearchInstance._initialOptions, _to_consumable_array(SENSITIVE_OPTIONS))) : [],
9547
+ children: buildWidgetTree(instantSearchInstance.mainIndex.getWidgets(), instantSearchInstance)
9548
+ }
9549
+ ]
9550
+ });
9551
+ } catch (unused) {
9552
+ // usage tracking must never crash the host app
9553
+ }
9554
+ };
9555
+ instantSearchInstance.once('render', sendStartEvent);
9556
+ removeStartEventListener = function removeStartEventListener() {
9557
+ return instantSearchInstance.removeListener('render', sendStartEvent);
9558
+ };
9559
+ });
9320
9560
  },
9321
9561
  unsubscribe: function unsubscribe() {
9562
+ if (removeStartEventListener) {
9563
+ removeStartEventListener();
9564
+ }
9322
9565
  insightsClient('onUserTokenChange', undefined);
9323
9566
  instantSearchInstance.sendEventToInsights = noop;
9324
9567
  if (helper && initialParameters) {
@@ -9366,31 +9609,6 @@
9366
9609
  return typeof userToken === 'number' ? userToken.toString() : userToken;
9367
9610
  }
9368
9611
 
9369
- function extractWidgetPayload(widgets, instantSearchInstance, payload) {
9370
- var initOptions = createInitArgs(instantSearchInstance, instantSearchInstance.mainIndex, instantSearchInstance._initialUiState);
9371
- widgets.forEach(function(widget) {
9372
- var widgetParams = {};
9373
- if (widget.getWidgetRenderState) {
9374
- var renderState = widget.getWidgetRenderState(initOptions);
9375
- if (renderState && renderState.widgetParams) {
9376
- // casting, as we just earlier checked widgetParams exists, and thus an object
9377
- widgetParams = renderState.widgetParams;
9378
- }
9379
- }
9380
- // since we destructure in all widgets, the parameters with defaults are set to "undefined"
9381
- var params = Object.keys(widgetParams).filter(function(key) {
9382
- return widgetParams[key] !== undefined;
9383
- });
9384
- payload.widgets.push({
9385
- type: widget.$$type,
9386
- widgetType: widget.$$widgetType,
9387
- params: params
9388
- });
9389
- if (isIndexWidget(widget)) {
9390
- extractWidgetPayload(widget.getWidgets(), instantSearchInstance, payload);
9391
- }
9392
- });
9393
- }
9394
9612
  function isMetadataEnabled() {
9395
9613
  return safelyRunOnBrowser(function(param) {
9396
9614
  var window = param.window;
@@ -10739,28 +10957,6 @@
10739
10957
  return reverseHighlightedValue.replace(new RegExp(TAG_REPLACEMENT.highlightPreTag, 'g'), "<".concat(highlightedTagName, ' class="').concat(className, '">')).replace(new RegExp(TAG_REPLACEMENT.highlightPostTag, 'g'), "</".concat(highlightedTagName, ">"));
10740
10958
  }
10741
10959
 
10742
- /** @deprecated use bindEvent instead */ function writeDataAttributes(param) {
10743
- var method = param.method, payload = param.payload;
10744
- if ((typeof payload === "undefined" ? "undefined" : _type_of(payload)) !== 'object') {
10745
- throw new Error("The insights helper expects the payload to be an object.");
10746
- }
10747
- var serializedPayload;
10748
- try {
10749
- serializedPayload = serializePayload(payload);
10750
- } catch (error) {
10751
- throw new Error("Could not JSON serialize the payload object.");
10752
- }
10753
- return 'data-insights-method="'.concat(method, '" data-insights-payload="').concat(serializedPayload, '"');
10754
- }
10755
- /**
10756
- * @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/
10757
- */ function insights(method, payload) {
10758
- return writeDataAttributes({
10759
- method: method,
10760
- payload: payload
10761
- });
10762
- }
10763
-
10764
10960
  function hoganHelpers(param) {
10765
10961
  var numberLocale = param.numberLocale;
10766
10962
  return {
@@ -10822,8 +11018,6 @@
10822
11018
  };
10823
11019
  }
10824
11020
 
10825
- var version = '4.104.0';
10826
-
10827
11021
  var withUsage$r = createDocumentationMessageGenerator({
10828
11022
  name: 'instantsearch'
10829
11023
  });
@@ -10843,7 +11037,14 @@
10843
11037
  function InstantSearch(options) {
10844
11038
  _class_call_check(this, InstantSearch);
10845
11039
  var _this;
10846
- _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), /**
11040
+ _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), /**
11041
+ * The options the instance was created with, kept verbatim so consumers
11042
+ * (e.g. usage events) can introspect the configuration without the class
11043
+ * having to enumerate every option by hand. Typed without the class generics
11044
+ * on purpose: referencing `TUiState`/`TRouteState` here (they sit in
11045
+ * contravariant positions inside `InstantSearchOptions`) would break the
11046
+ * assignability of `InstantSearch<SpecificUiState>` to `InstantSearch`.
11047
+ */ _define_property(_this, "_initialOptions", void 0), _define_property(_this, "middleware", []), _define_property(_this, "sendEventToInsights", void 0), _define_property(_this, "_createdAt", now()), /**
10847
11048
  * The status of the search. Can be "idle", "loading", "stalled", or "error".
10848
11049
  */ _define_property(_this, "status", 'idle'), /**
10849
11050
  * The last returned error from the Search API.
@@ -10891,6 +11092,7 @@
10891
11092
  if (insightsClient && typeof insightsClient !== 'function') {
10892
11093
  throw new Error(withUsage$r('The `insightsClient` option should be a function.'));
10893
11094
  }
11095
+ _this._initialOptions = options;
10894
11096
  _this.client = searchClient;
10895
11097
  _this.future = future;
10896
11098
  _this.insightsClient = insightsClient;
@@ -11263,6 +11465,9 @@
11263
11465
  var instance = param.instance;
11264
11466
  instance.unsubscribe();
11265
11467
  });
11468
+ // Cleared after unsubscribe so in-flight readers (e.g. the insights
11469
+ // start-event listener) have detached before the reference goes away.
11470
+ this._initialOptions = null;
11266
11471
  }
11267
11472
  },
11268
11473
  {
@@ -23838,7 +24043,10 @@
23838
24043
  "isShowingMore",
23839
24044
  "translations"
23840
24045
  ]);
23841
- return /*#__PURE__*/ React.createElement("button", props, translations.showMoreButtonText({
24046
+ return /*#__PURE__*/ React.createElement("button", _object_spread_props(_object_spread({}, props), {
24047
+ "aria-expanded": isShowingMore,
24048
+ "aria-label": translations.showMoreButtonLabel
24049
+ }), translations.showMoreButtonText({
23842
24050
  isShowingMore: isShowingMore
23843
24051
  }));
23844
24052
  }
@@ -24368,6 +24576,7 @@
24368
24576
  currentPage: page + 1,
24369
24577
  nbPages: nbPages
24370
24578
  }),
24579
+ "aria-current": page === currentPage ? 'page' : undefined,
24371
24580
  href: createURL(page),
24372
24581
  onClick: function onClick() {
24373
24582
  return onNavigate(page);
@@ -24836,13 +25045,15 @@
24836
25045
  })), /*#__PURE__*/ React.createElement("button", {
24837
25046
  className: cx('ais-SearchBox-submit', classNames.submit),
24838
25047
  type: "submit",
24839
- title: translations.submitButtonTitle
25048
+ title: translations.submitButtonTitle,
25049
+ "aria-label": translations.submitButtonTitle
24840
25050
  }, /*#__PURE__*/ React.createElement(SubmitIcon, {
24841
25051
  classNames: classNames
24842
25052
  })), /*#__PURE__*/ React.createElement("button", {
24843
25053
  className: cx('ais-SearchBox-reset', classNames.reset),
24844
25054
  type: "reset",
24845
25055
  title: translations.resetButtonTitle,
25056
+ "aria-label": translations.resetButtonTitle,
24846
25057
  hidden: value.length === 0 || isSearchStalled
24847
25058
  }, /*#__PURE__*/ React.createElement(ResetIcon, {
24848
25059
  classNames: classNames
@@ -24954,7 +25165,8 @@
24954
25165
  onToggleShowMore: toggleShowMore,
24955
25166
  isShowingMore: isShowingMore,
24956
25167
  translations: {
24957
- showMoreButtonText: mergedTranslations.showMoreButtonText
25168
+ showMoreButtonText: mergedTranslations.showMoreButtonText,
25169
+ showMoreButtonLabel: translations === null || translations === void 0 ? void 0 : translations.showMoreButtonLabel
24958
25170
  }
24959
25171
  };
24960
25172
  return /*#__PURE__*/ React.createElement(RefinementList$1, _object_spread_props(_object_spread({}, props, uiProps), {
@@ -25178,6 +25390,21 @@
25178
25390
  return /*#__PURE__*/ React.createElement(SortBy$1, _object_spread({}, props, uiProps));
25179
25391
  }
25180
25392
 
25393
+ // Delay before announcing an update, so that rapid changes (e.g. typing in the
25394
+ // search box) settle into a single announcement instead of piling up. Mirrors
25395
+ // the debounce used by GOV.UK's accessible-autocomplete.
25396
+ var ANNOUNCEMENT_DELAY = 1400;
25397
+ var visuallyHiddenStyle = {
25398
+ position: 'absolute',
25399
+ width: 1,
25400
+ height: 1,
25401
+ padding: 0,
25402
+ margin: -1,
25403
+ overflow: 'hidden',
25404
+ clip: 'rect(0, 0, 0, 0)',
25405
+ whiteSpace: 'nowrap',
25406
+ border: 0
25407
+ };
25181
25408
  function Stats$1(_0) {
25182
25409
  var _0_classNames = _0.classNames, classNames = _0_classNames === void 0 ? {} : _0_classNames, nbHits = _0.nbHits, processingTimeMS = _0.processingTimeMS, nbSortedHits = _0.nbSortedHits, areHitsSorted = _0.areHitsSorted, translations = _0.translations, props = _object_without_properties(_0, [
25183
25410
  "classNames",
@@ -25193,11 +25420,37 @@
25193
25420
  nbSortedHits: nbSortedHits,
25194
25421
  areHitsSorted: areHitsSorted
25195
25422
  };
25423
+ var nextAnnouncement = translations.announcementText ? translations.announcementText(translationOptions) : '';
25424
+ var _useState = _sliced_to_array(React.useState(''), 2), announcement = _useState[0], setAnnouncement = _useState[1];
25425
+ var timerRef = React.useRef(undefined);
25426
+ var isInitialRef = React.useRef(true);
25427
+ React.useEffect(function() {
25428
+ // Don't announce the initial results, only subsequent changes.
25429
+ if (isInitialRef.current) {
25430
+ isInitialRef.current = false;
25431
+ return undefined;
25432
+ }
25433
+ clearTimeout(timerRef.current);
25434
+ timerRef.current = setTimeout(function() {
25435
+ setAnnouncement(nextAnnouncement);
25436
+ }, ANNOUNCEMENT_DELAY);
25437
+ return function() {
25438
+ return clearTimeout(timerRef.current);
25439
+ };
25440
+ }, [
25441
+ nextAnnouncement
25442
+ ]);
25196
25443
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props), {
25197
25444
  className: cx('ais-Stats', classNames.root, props.className)
25198
25445
  }), /*#__PURE__*/ React.createElement("span", {
25199
25446
  className: "ais-Stats-text"
25200
- }, translations.rootElementText(translationOptions)));
25447
+ }, translations.rootElementText(translationOptions)), /*#__PURE__*/ React.createElement("span", {
25448
+ className: "ais-Stats-announcement",
25449
+ role: "status",
25450
+ "aria-live": "polite",
25451
+ "aria-atomic": "true",
25452
+ style: visuallyHiddenStyle
25453
+ }, announcement));
25201
25454
  }
25202
25455
 
25203
25456
  function Stats(_0) {
@@ -25215,6 +25468,9 @@
25215
25468
  translations: _object_spread({
25216
25469
  rootElementText: function rootElementText(options) {
25217
25470
  return "".concat(options.areHitsSorted ? getSortedResultsSentence(options) : getResultsSentence(options), " found in ").concat(options.processingTimeMS.toLocaleString(), "ms");
25471
+ },
25472
+ announcementText: function announcementText(options) {
25473
+ return options.areHitsSorted ? getSortedResultsSentence(options) : getResultsSentence(options);
25218
25474
  }
25219
25475
  }, translations)
25220
25476
  };