react-instantsearch 7.35.1 → 7.37.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,14 +1,14 @@
1
- import { _ as _$1 } from '@swc/helpers/esm/_object_spread.js';
1
+ import { _ as _$2 } from '@swc/helpers/esm/_object_spread.js';
2
2
  import { _ as _$4 } from '@swc/helpers/esm/_object_spread_props.js';
3
3
  import { _ } from '@swc/helpers/esm/_object_without_properties.js';
4
- import { _ as _$5 } from '@swc/helpers/esm/_sliced_to_array.js';
5
- import { _ as _$2 } from '@swc/helpers/esm/_to_consumable_array.js';
6
- import { _ as _$3 } from '@swc/helpers/esm/_type_of.js';
4
+ import { _ as _$1 } from '@swc/helpers/esm/_sliced_to_array.js';
5
+ import { _ as _$3 } from '@swc/helpers/esm/_to_consumable_array.js';
6
+ import { _ as _$5 } from '@swc/helpers/esm/_type_of.js';
7
7
  import { createAutocompleteComponent, createAutocompletePanelComponent, createAutocompleteIndexComponent, createAutocompleteSuggestionComponent, createAutocompletePromptSuggestionComponent, createAutocompleteRecentSearchComponent, createAutocompleteDetachedContainerComponent, createAutocompleteDetachedOverlayComponent, createAutocompleteDetachedFormContainerComponent, createAutocompleteDetachedSearchButtonComponent, createAutocompletePropGetters, createAutocompleteStorage, cx, getPromptSuggestionHits, isPromptSuggestion } from 'instantsearch-ui-components';
8
8
  import { openChat, isChatBusy } from 'instantsearch.js/es/lib/chat/index.js';
9
9
  import 'instantsearch.js/es/lib/utils/index.js';
10
- import React, { createElement, Fragment, useEffect, useMemo, useRef, useState } from 'react';
11
- import { useInstantSearch, useSearchBox, Index, Configure, useAutocomplete } from 'react-instantsearch-core';
10
+ import React, { createElement, Fragment, useEffect, useMemo, useRef, useState, useLayoutEffect } from 'react';
11
+ import { useInstantSearch, useInstantSearchContext, useSearchBox, Index, Configure, Feeds, useAutocomplete } from 'react-instantsearch-core';
12
12
  import { AutocompleteSearch } from '../components/AutocompleteSearch.js';
13
13
  import { Highlight } from './Highlight.js';
14
14
  import { ReverseHighlight } from './ReverseHighlight.js';
@@ -54,6 +54,16 @@ var AutocompleteDetachedSearchButton = createAutocompleteDetachedSearchButtonCom
54
54
  Fragment: Fragment
55
55
  });
56
56
  var id = 0;
57
+ // Colons (`:r0:`) preserved so concatenations like `autocomplete:r0:input`
58
+ // have a recognisable boundary; callers that need a colon-free variant for
59
+ // InstantSearch's `indexId` strip them at the use site.
60
+ var useAutocompleteId = React.useId ? function() {
61
+ return React.useId();
62
+ } : function() {
63
+ return React.useState(function() {
64
+ return ":a".concat(id++, ":");
65
+ })[0];
66
+ };
57
67
  var usePropGetters = createAutocompletePropGetters({
58
68
  useEffect: useEffect,
59
69
  useId: React.useId || function() {
@@ -108,12 +118,12 @@ function getMediaQueryList(mediaQuery) {
108
118
  }, [
109
119
  mediaQuery
110
120
  ]);
111
- var _useState = _$5(useState(function() {
121
+ var _useState = _$1(useState(function() {
112
122
  var _getMediaQueryList;
113
123
  return resolvedMediaQuery ? Boolean((_getMediaQueryList = getMediaQueryList(resolvedMediaQuery)) === null || _getMediaQueryList === void 0 ? void 0 : _getMediaQueryList.matches) : false;
114
124
  }), 2), isDetached = _useState[0], setIsDetached = _useState[1];
115
- var _useState1 = _$5(useState(false), 2), isModalOpen = _useState1[0], setIsModalOpen = _useState1[1];
116
- var _useState2 = _$5(useState(false), 2), isModalDetached = _useState2[0], setIsModalDetached = _useState2[1];
125
+ var _useState1 = _$1(useState(false), 2), isModalOpen = _useState1[0], setIsModalOpen = _useState1[1];
126
+ var _useState2 = _$1(useState(false), 2), isModalDetached = _useState2[0], setIsModalDetached = _useState2[1];
117
127
  useEffect(function() {
118
128
  if (!resolvedMediaQuery) {
119
129
  setIsDetached(false);
@@ -189,99 +199,193 @@ function getMediaQueryList(mediaQuery) {
189
199
  setIsModalOpen: setIsModalOpen
190
200
  };
191
201
  }
192
- function EXPERIMENTAL_Autocomplete(_0) {
193
- var _0_indices = _0.indices, indices = _0_indices === void 0 ? [] : _0_indices, showQuerySuggestions = _0.showQuerySuggestions, showPromptSuggestions = _0.showPromptSuggestions, showRecent = _0.showRecent, userSearchParameters = _0.searchParameters, detachedMediaQuery = _0.detachedMediaQuery, tmp = _0.translations, userTranslations = tmp === void 0 ? {} : tmp, aiMode = _0.aiMode, props = _(_0, [
194
- "indices",
202
+ function EXPERIMENTAL_Autocomplete(props) {
203
+ var _showRecent_classNames, _showRecent_classNames1, _showRecent_classNames2, _showRecent_classNames3;
204
+ var indices = 'indices' in props ? props.indices : undefined;
205
+ var feeds = 'feeds' in props ? props.feeds : undefined;
206
+ var isFeedsMode = feeds !== undefined;
207
+ var showQuerySuggestions = props.showQuerySuggestions, showPromptSuggestions = props.showPromptSuggestions, showRecent = props.showRecent, userSearchParameters = props.searchParameters, detachedMediaQuery = props.detachedMediaQuery, tmp = props.translations, userTranslations = tmp === void 0 ? {} : tmp, transformItems = props.transformItems, restProps = _(props, [
195
208
  "showQuerySuggestions",
196
209
  "showPromptSuggestions",
197
210
  "showRecent",
198
211
  "searchParameters",
199
212
  "detachedMediaQuery",
200
213
  "translations",
201
- "aiMode"
214
+ "transformItems"
202
215
  ]);
203
- var _showRecent_classNames, _showRecent_classNames1, _showRecent_classNames2, _showRecent_classNames3;
204
- var translations = _$1({}, DEFAULT_TRANSLATIONS, userTranslations);
216
+ var autoFocus = restProps.autoFocus, placeholder = restProps.placeholder, classNames = restProps.classNames;
217
+ // Eager-mount only when `autoFocus` is set — otherwise wait for first focus
218
+ // before registering the autocomplete subtree in the search graph.
219
+ var _useState = _$1(useState(autoFocus === true), 2), activated = _useState[0], setActivated = _useState[1];
220
+ var translations = _$2({}, DEFAULT_TRANSLATIONS, userTranslations);
205
221
  var _useInstantSearch = useInstantSearch(), indexUiState = _useInstantSearch.indexUiState, indexRenderState = _useInstantSearch.indexRenderState, status = _useInstantSearch.status;
206
- var refine = useSearchBox({}, _$1({
222
+ var compositionID = useInstantSearchContext().compositionID;
223
+ var refine = useSearchBox({}, _$2({
207
224
  $$type: 'ais.autocomplete',
208
225
  $$widgetType: 'ais.autocomplete'
209
- }, aiMode ? {
226
+ }, props.aiMode ? {
210
227
  opensChat: true
211
228
  } : {})).refine;
229
+ var domId = useAutocompleteId();
230
+ var instanceKey = domId.replace(/:/g, '');
231
+ if (isFeedsMode && indices !== undefined) {
232
+ throw new Error('EXPERIMENTAL_Autocomplete: `feeds` and `indices` are mutually exclusive.');
233
+ }
234
+ if (isFeedsMode && !compositionID) {
235
+ throw new Error('EXPERIMENTAL_Autocomplete in feeds-mode requires a composition-based <InstantSearch> (compositionID must be set).');
236
+ }
212
237
  var isSearchStalled = status === 'stalled';
213
- var searchParameters = _$1({
238
+ var searchParameters = _$2({
214
239
  hitsPerPage: 5
215
240
  }, userSearchParameters);
216
- var indicesConfig = _$2(indices);
217
- if (showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.indexName) {
218
- var _showQuerySuggestions_classNames, _showQuerySuggestions_classNames1, _showQuerySuggestions_classNames2, _showQuerySuggestions_classNames3;
219
- indicesConfig.unshift({
220
- indexName: showQuerySuggestions.indexName,
221
- headerComponent: showQuerySuggestions.headerComponent,
222
- itemComponent: showQuerySuggestions.itemComponent || function(param) {
223
- var item = param.item, onSelect = param.onSelect, onApply = param.onApply;
224
- return /*#__PURE__*/ React.createElement(AutocompleteSuggestion, {
225
- item: item,
226
- onSelect: onSelect,
227
- onApply: onApply
228
- }, /*#__PURE__*/ React.createElement(ConditionalReverseHighlight, {
229
- item: item
230
- }));
231
- },
232
- classNames: {
233
- root: cx('ais-AutocompleteSuggestions', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames === void 0 ? void 0 : _showQuerySuggestions_classNames.root),
234
- list: cx('ais-AutocompleteSuggestionsList', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames1 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames1 === void 0 ? void 0 : _showQuerySuggestions_classNames1.list),
235
- header: cx('ais-AutocompleteSuggestionsHeader', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames2 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames2 === void 0 ? void 0 : _showQuerySuggestions_classNames2.header),
236
- item: cx('ais-AutocompleteSuggestionsItem', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames3 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames3 === void 0 ? void 0 : _showQuerySuggestions_classNames3.item)
237
- },
238
- searchParameters: _$1({
241
+ // In feeds-mode `indexName` carries the feedID so downstream matching
242
+ // (section building, dedupe in createAutocompleteStorage) treats feeds
243
+ // like indices without any changes to InnerAutocomplete.
244
+ var querySuggestionsKey = isFeedsMode ? showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.feedID : showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.indexName;
245
+ var promptSuggestionsKey = isFeedsMode ? showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.feedID : showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.indexName;
246
+ var indicesConfig = useMemo(function() {
247
+ var config = isFeedsMode ? feeds.map(function(feed) {
248
+ return {
249
+ indexName: feed.feedID,
250
+ headerComponent: feed.headerComponent,
251
+ itemComponent: feed.itemComponent,
252
+ noResultsComponent: feed.noResultsComponent,
253
+ getURL: feed.getURL,
254
+ getQuery: feed.getQuery,
255
+ classNames: feed.classNames
256
+ };
257
+ }) : _$3(indices !== null && indices !== void 0 ? indices : []);
258
+ if (querySuggestionsKey) {
259
+ var _showQuerySuggestions_classNames, _showQuerySuggestions_classNames1, _showQuerySuggestions_classNames2, _showQuerySuggestions_classNames3;
260
+ var querySuggestionsSearchParameters = isFeedsMode ? undefined : _$2({
239
261
  hitsPerPage: 3
240
- }, showQuerySuggestions.searchParameters),
241
- getQuery: function getQuery(item) {
242
- return item.query;
243
- },
244
- getURL: showQuerySuggestions.getURL
245
- });
246
- }
247
- if (showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.indexName) {
248
- var _showPromptSuggestions_classNames, _showPromptSuggestions_classNames1, _showPromptSuggestions_classNames2, _showPromptSuggestions_classNames3;
249
- indicesConfig.push({
250
- indexName: showPromptSuggestions.indexName,
251
- headerComponent: showPromptSuggestions.headerComponent,
252
- itemComponent: showPromptSuggestions.itemComponent || function(param) {
253
- var item = param.item, onSelect = param.onSelect;
254
- return /*#__PURE__*/ React.createElement(AutocompletePromptSuggestion, {
255
- item: item,
256
- onSelect: onSelect
257
- }, /*#__PURE__*/ React.createElement(ConditionalHighlight, {
258
- item: item,
259
- attribute: "prompt"
260
- }));
261
- },
262
- classNames: {
263
- root: cx('ais-AutocompletePromptSuggestions', (_showPromptSuggestions_classNames = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames === void 0 ? void 0 : _showPromptSuggestions_classNames.root),
264
- list: cx('ais-AutocompletePromptSuggestionsList', (_showPromptSuggestions_classNames1 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames1 === void 0 ? void 0 : _showPromptSuggestions_classNames1.list),
265
- header: cx('ais-AutocompletePromptSuggestionsHeader', (_showPromptSuggestions_classNames2 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames2 === void 0 ? void 0 : _showPromptSuggestions_classNames2.header),
266
- item: cx('ais-AutocompletePromptSuggestionsItem', (_showPromptSuggestions_classNames3 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames3 === void 0 ? void 0 : _showPromptSuggestions_classNames3.item)
267
- },
268
- searchParameters: _$1({
262
+ }, showQuerySuggestions.searchParameters);
263
+ config.unshift({
264
+ indexName: querySuggestionsKey,
265
+ headerComponent: showQuerySuggestions.headerComponent,
266
+ itemComponent: showQuerySuggestions.itemComponent || function(param) {
267
+ var item = param.item, onSelect = param.onSelect, onApply = param.onApply;
268
+ return /*#__PURE__*/ React.createElement(AutocompleteSuggestion, {
269
+ item: item,
270
+ onSelect: onSelect,
271
+ onApply: onApply
272
+ }, /*#__PURE__*/ React.createElement(ConditionalReverseHighlight, {
273
+ item: item
274
+ }));
275
+ },
276
+ classNames: {
277
+ root: cx('ais-AutocompleteSuggestions', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames === void 0 ? void 0 : _showQuerySuggestions_classNames.root),
278
+ list: cx('ais-AutocompleteSuggestionsList', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames1 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames1 === void 0 ? void 0 : _showQuerySuggestions_classNames1.list),
279
+ header: cx('ais-AutocompleteSuggestionsHeader', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames2 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames2 === void 0 ? void 0 : _showQuerySuggestions_classNames2.header),
280
+ item: cx('ais-AutocompleteSuggestionsItem', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames3 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames3 === void 0 ? void 0 : _showQuerySuggestions_classNames3.item)
281
+ },
282
+ searchParameters: querySuggestionsSearchParameters,
283
+ getQuery: function getQuery(item) {
284
+ return item.query;
285
+ },
286
+ getURL: showQuerySuggestions.getURL
287
+ });
288
+ }
289
+ if (promptSuggestionsKey) {
290
+ var _showPromptSuggestions_classNames, _showPromptSuggestions_classNames1, _showPromptSuggestions_classNames2, _showPromptSuggestions_classNames3;
291
+ var promptSuggestionsSearchParameters = isFeedsMode ? undefined : _$2({
269
292
  hitsPerPage: 3
270
- }, showPromptSuggestions.searchParameters),
271
- getQuery: function getQuery(item) {
272
- return item.prompt;
273
- },
274
- getURL: showPromptSuggestions.getURL
275
- });
276
- }
293
+ }, showPromptSuggestions.searchParameters);
294
+ config.push({
295
+ indexName: promptSuggestionsKey,
296
+ headerComponent: showPromptSuggestions.headerComponent,
297
+ itemComponent: showPromptSuggestions.itemComponent || function(param) {
298
+ var item = param.item, onSelect = param.onSelect;
299
+ return /*#__PURE__*/ React.createElement(AutocompletePromptSuggestion, {
300
+ item: item,
301
+ onSelect: onSelect
302
+ }, /*#__PURE__*/ React.createElement(ConditionalHighlight, {
303
+ item: item,
304
+ attribute: "prompt"
305
+ }));
306
+ },
307
+ classNames: {
308
+ root: cx('ais-AutocompletePromptSuggestions', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames === void 0 ? void 0 : _showPromptSuggestions_classNames.root),
309
+ list: cx('ais-AutocompletePromptSuggestionsList', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames1 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames1 === void 0 ? void 0 : _showPromptSuggestions_classNames1.list),
310
+ header: cx('ais-AutocompletePromptSuggestionsHeader', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames2 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames2 === void 0 ? void 0 : _showPromptSuggestions_classNames2.header),
311
+ item: cx('ais-AutocompletePromptSuggestionsItem', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames3 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames3 === void 0 ? void 0 : _showPromptSuggestions_classNames3.item)
312
+ },
313
+ searchParameters: promptSuggestionsSearchParameters,
314
+ getQuery: function getQuery(item) {
315
+ return item.prompt;
316
+ },
317
+ getURL: showPromptSuggestions.getURL
318
+ });
319
+ }
320
+ return config;
321
+ }, [
322
+ feeds,
323
+ indices,
324
+ isFeedsMode,
325
+ promptSuggestionsKey,
326
+ querySuggestionsKey,
327
+ showPromptSuggestions,
328
+ showQuerySuggestions
329
+ ]);
330
+ // Normalize `show*` for InnerAutocomplete: always surface `indexName`
331
+ // (in feeds-mode it carries the feedID). Keeps downstream dedupe in
332
+ // createAutocompleteStorage (suggestionsIndexName === index.indexName) working.
333
+ var normalizedShowQuerySuggestions = useMemo(function() {
334
+ if (!showQuerySuggestions) {
335
+ return undefined;
336
+ }
337
+ if (isFeedsMode) {
338
+ return _$4(_$2({}, showQuerySuggestions), {
339
+ indexName: querySuggestionsKey
340
+ });
341
+ }
342
+ return showQuerySuggestions;
343
+ }, [
344
+ isFeedsMode,
345
+ querySuggestionsKey,
346
+ showQuerySuggestions
347
+ ]);
348
+ var normalizedShowPromptSuggestions = useMemo(function() {
349
+ if (!showPromptSuggestions) {
350
+ return undefined;
351
+ }
352
+ if (isFeedsMode) {
353
+ return _$4(_$2({}, showPromptSuggestions), {
354
+ indexName: promptSuggestionsKey
355
+ });
356
+ }
357
+ return showPromptSuggestions;
358
+ }, [
359
+ isFeedsMode,
360
+ promptSuggestionsKey,
361
+ showPromptSuggestions
362
+ ]);
363
+ // In feeds-mode, remap `indexName := indexId` so downstream storage (which
364
+ // matches on indexName) sees feedIDs instead of the composition index name
365
+ // that connectAutocomplete sets from the helper results.
366
+ // Must be memoized: useConnector's useStableValue runs dequal on each render
367
+ // and treats a new function identity as a change, re-registering the widget.
368
+ var effectiveTransformItems = useMemo(function() {
369
+ return isFeedsMode ? function(items) {
370
+ var remapped = items.map(function(item) {
371
+ return _$4(_$2({}, item), {
372
+ indexName: item.indexId
373
+ });
374
+ });
375
+ return transformItems ? transformItems(remapped) : remapped;
376
+ } : transformItems;
377
+ }, [
378
+ isFeedsMode,
379
+ transformItems
380
+ ]);
277
381
  var recentSearchConfig = showRecent ? {
278
- headerComponent: (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' ? showRecent.headerComponent : undefined,
279
- itemComponent: (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' && showRecent.itemComponent ? showRecent.itemComponent : AutocompleteRecentSearch,
382
+ headerComponent: (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' ? showRecent.headerComponent : undefined,
383
+ itemComponent: (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' && showRecent.itemComponent ? showRecent.itemComponent : AutocompleteRecentSearch,
280
384
  classNames: {
281
- root: cx('ais-AutocompleteRecentSearches', (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' ? (_showRecent_classNames = showRecent.classNames) === null || _showRecent_classNames === void 0 ? void 0 : _showRecent_classNames.root : undefined),
282
- list: cx('ais-AutocompleteRecentSearchesList', (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' ? (_showRecent_classNames1 = showRecent.classNames) === null || _showRecent_classNames1 === void 0 ? void 0 : _showRecent_classNames1.list : undefined),
283
- header: cx('ais-AutocompleteRecentSearchesHeader', (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' ? (_showRecent_classNames2 = showRecent.classNames) === null || _showRecent_classNames2 === void 0 ? void 0 : _showRecent_classNames2.header : undefined),
284
- item: cx('ais-AutocompleteRecentSearchesItem', (typeof showRecent === "undefined" ? "undefined" : _$3(showRecent)) === 'object' ? (_showRecent_classNames3 = showRecent.classNames) === null || _showRecent_classNames3 === void 0 ? void 0 : _showRecent_classNames3.item : undefined)
385
+ root: cx('ais-AutocompleteRecentSearches', (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' ? (_showRecent_classNames = showRecent.classNames) === null || _showRecent_classNames === void 0 ? void 0 : _showRecent_classNames.root : undefined),
386
+ list: cx('ais-AutocompleteRecentSearchesList', (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' ? (_showRecent_classNames1 = showRecent.classNames) === null || _showRecent_classNames1 === void 0 ? void 0 : _showRecent_classNames1.list : undefined),
387
+ header: cx('ais-AutocompleteRecentSearchesHeader', (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' ? (_showRecent_classNames2 = showRecent.classNames) === null || _showRecent_classNames2 === void 0 ? void 0 : _showRecent_classNames2.header : undefined),
388
+ item: cx('ais-AutocompleteRecentSearchesItem', (typeof showRecent === "undefined" ? "undefined" : _$5(showRecent)) === 'object' ? (_showRecent_classNames3 = showRecent.classNames) === null || _showRecent_classNames3 === void 0 ? void 0 : _showRecent_classNames3.item : undefined)
285
389
  }
286
390
  } : undefined;
287
391
  var isSearchPage = useMemo(function() {
@@ -289,15 +393,88 @@ function EXPERIMENTAL_Autocomplete(_0) {
289
393
  }, [
290
394
  indexRenderState
291
395
  ]);
292
- return /*#__PURE__*/ React.createElement(Fragment, null, /*#__PURE__*/ React.createElement(Index, {
293
- EXPERIMENTAL_isolated: true
294
- }, /*#__PURE__*/ React.createElement(Configure, searchParameters), indicesConfig.map(function(index) {
295
- return /*#__PURE__*/ React.createElement(Index, {
296
- key: index.indexName,
297
- indexName: index.indexName
298
- }, /*#__PURE__*/ React.createElement(Configure, index.searchParameters));
299
- }), /*#__PURE__*/ React.createElement(InnerAutocomplete, _$4(_$1({}, props), {
300
- aiMode: aiMode,
396
+ restProps.indices; restProps.feeds; var forwardedProps = _(restProps, [
397
+ "indices",
398
+ "feeds"
399
+ ]);
400
+ var instance = useInstantSearchContext();
401
+ var detached = useDetachedMode(detachedMediaQuery);
402
+ var isDetached = detached.isDetached, setIsModalOpen = detached.setIsModalOpen;
403
+ // Lazy activation only: when `activated` flips from false to true, the
404
+ // newly-mounted isolated `<Index>` schedules the parent's search even
405
+ // though the parent's state hasn't changed. Cancel it so only the
406
+ // autocomplete's own search fires on activation. Skip when `autoFocus`
407
+ // mounts the inner eagerly — the parent's legitimate initial search
408
+ // shares the same defer slot and must not be cancelled.
409
+ var initialActivatedRef = useRef(activated);
410
+ useLayoutEffect(function() {
411
+ if (activated && !initialActivatedRef.current) {
412
+ initialActivatedRef.current = true;
413
+ instance.scheduleSearch.cancel();
414
+ }
415
+ }, [
416
+ activated,
417
+ instance
418
+ ]);
419
+ if (!activated) {
420
+ var _indexUiState_query, _indexUiState_query1;
421
+ restProps.indices; restProps.feeds; restProps.autoFocus; restProps.placeholder; restProps.classNames; restProps.aiMode; restProps.panelComponent; restProps.getSearchPageURL; restProps.onSelect; var shellRootProps = _(restProps, [
422
+ "indices",
423
+ "feeds",
424
+ "autoFocus",
425
+ "placeholder",
426
+ "classNames",
427
+ "aiMode",
428
+ "panelComponent",
429
+ "getSearchPageURL",
430
+ "onSelect"
431
+ ]);
432
+ var activateWithQueryMirror = function activateWithQueryMirror() {
433
+ // Routing only fills the parent index's UI state, not the
434
+ // autocomplete's isolated one, so without this, the autocomplete
435
+ // would activate with an empty query and fire a useless search.
436
+ // We copy the parent's query into the autocomplete's slot of
437
+ // `_initialUiState` right before flipping `activated`: that's the
438
+ // moment the isolated `<Index>` is about to mount and read it.
439
+ // Doing this later would mean firing a second search to correct
440
+ // the first.
441
+ if (indexUiState.query) {
442
+ var isoIndexId = "ais-autocomplete-".concat(instanceKey);
443
+ var initial = instance._initialUiState;
444
+ initial[isoIndexId] = _$4(_$2({}, initial[isoIndexId]), {
445
+ query: indexUiState.query
446
+ });
447
+ }
448
+ setActivated(true);
449
+ };
450
+ return /*#__PURE__*/ React.createElement(Autocomplete, _$4(_$2({}, shellRootProps), {
451
+ classNames: classNames
452
+ }), isDetached ? /*#__PURE__*/ React.createElement(AutocompleteDetachedSearchButton, {
453
+ query: (_indexUiState_query = indexUiState.query) !== null && _indexUiState_query !== void 0 ? _indexUiState_query : '',
454
+ placeholder: placeholder,
455
+ classNames: classNames,
456
+ translations: translations,
457
+ onClick: function onClick() {
458
+ setIsModalOpen(true);
459
+ activateWithQueryMirror();
460
+ }
461
+ }) : /*#__PURE__*/ React.createElement(AutocompleteSearch, {
462
+ inputProps: {
463
+ id: "autocomplete".concat(domId, "input"),
464
+ role: 'combobox',
465
+ placeholder: placeholder,
466
+ onFocus: activateWithQueryMirror
467
+ },
468
+ clearQuery: function clearQuery() {},
469
+ query: (_indexUiState_query1 = indexUiState.query) !== null && _indexUiState_query1 !== void 0 ? _indexUiState_query1 : '',
470
+ isSearchStalled: false,
471
+ classNames: classNames
472
+ }));
473
+ }
474
+ var innerAutocomplete = /*#__PURE__*/ React.createElement(InnerAutocomplete, _$4(_$2({}, forwardedProps), {
475
+ autoFocus: true,
476
+ domId: domId,
477
+ detached: detached,
301
478
  indicesConfig: indicesConfig,
302
479
  refineSearchBox: refine,
303
480
  isSearchStalled: isSearchStalled,
@@ -305,15 +482,37 @@ function EXPERIMENTAL_Autocomplete(_0) {
305
482
  isSearchPage: isSearchPage,
306
483
  showRecent: showRecent,
307
484
  recentSearchConfig: recentSearchConfig,
308
- showQuerySuggestions: showQuerySuggestions,
309
- detachedMediaQuery: detachedMediaQuery,
485
+ showQuerySuggestions: normalizedShowQuerySuggestions,
310
486
  translations: translations,
311
- showPromptSuggestions: showPromptSuggestions,
487
+ showPromptSuggestions: normalizedShowPromptSuggestions,
488
+ transformItems: effectiveTransformItems,
312
489
  chatRenderState: indexRenderState.chat
313
- }))));
490
+ }));
491
+ if (isFeedsMode) {
492
+ return /*#__PURE__*/ React.createElement(Index, {
493
+ EXPERIMENTAL_isolated: true,
494
+ indexName: compositionID,
495
+ indexId: "ais-autocomplete-".concat(instanceKey)
496
+ }, /*#__PURE__*/ React.createElement(Configure, searchParameters), /*#__PURE__*/ React.createElement(Feeds, {
497
+ isolated: false,
498
+ renderFeed: function renderFeed() {
499
+ return null;
500
+ }
501
+ }), innerAutocomplete);
502
+ }
503
+ return /*#__PURE__*/ React.createElement(Index, {
504
+ EXPERIMENTAL_isolated: true,
505
+ indexId: "ais-autocomplete-".concat(instanceKey)
506
+ }, /*#__PURE__*/ React.createElement(Configure, searchParameters), indicesConfig.map(function(index) {
507
+ return /*#__PURE__*/ React.createElement(Index, {
508
+ key: index.indexName,
509
+ indexName: index.indexName,
510
+ indexId: "ais-autocomplete-".concat(instanceKey, "-").concat(index.indexName)
511
+ }, /*#__PURE__*/ React.createElement(Configure, index.searchParameters));
512
+ }), innerAutocomplete);
314
513
  }
315
514
  function InnerAutocomplete(_0) {
316
- var indicesConfig = _0.indicesConfig, refineSearchBox = _0.refineSearchBox, isSearchStalled = _0.isSearchStalled, getSearchPageURL = _0.getSearchPageURL, userOnSelect = _0.onSelect, indexUiState = _0.indexUiState, isSearchPage = _0.isSearchPage, PanelComponent = _0.panelComponent, showRecent = _0.showRecent, recentSearchConfig = _0.recentSearchConfig, showQuerySuggestions = _0.showQuerySuggestions, showPromptSuggestions = _0.showPromptSuggestions, chatRenderState = _0.chatRenderState, transformItems = _0.transformItems, placeholder = _0.placeholder, autoFocus = _0.autoFocus, _0_detachedMediaQuery = _0.detachedMediaQuery, detachedMediaQuery = _0_detachedMediaQuery === void 0 ? DEFAULT_DETACHED_MEDIA_QUERY : _0_detachedMediaQuery, translations = _0.translations, classNames = _0.classNames, aiMode = _0.aiMode, props = _(_0, [
515
+ var indicesConfig = _0.indicesConfig, refineSearchBox = _0.refineSearchBox, isSearchStalled = _0.isSearchStalled, getSearchPageURL = _0.getSearchPageURL, userOnSelect = _0.onSelect, indexUiState = _0.indexUiState, isSearchPage = _0.isSearchPage, PanelComponent = _0.panelComponent, showRecent = _0.showRecent, recentSearchConfig = _0.recentSearchConfig, showQuerySuggestions = _0.showQuerySuggestions, showPromptSuggestions = _0.showPromptSuggestions, chatRenderState = _0.chatRenderState, transformItems = _0.transformItems, placeholder = _0.placeholder, autoFocus = _0.autoFocus, translations = _0.translations, classNames = _0.classNames, aiMode = _0.aiMode, domId = _0.domId, detached = _0.detached, props = _(_0, [
317
516
  "indicesConfig",
318
517
  "refineSearchBox",
319
518
  "isSearchStalled",
@@ -330,10 +529,11 @@ function InnerAutocomplete(_0) {
330
529
  "transformItems",
331
530
  "placeholder",
332
531
  "autoFocus",
333
- "detachedMediaQuery",
334
532
  "translations",
335
533
  "classNames",
336
- "aiMode"
534
+ "aiMode",
535
+ "domId",
536
+ "detached"
337
537
  ]);
338
538
  var _indexUiState_query, _ref;
339
539
  var _showPromptSuggestions_searchParameters;
@@ -344,7 +544,7 @@ function InnerAutocomplete(_0) {
344
544
  }
345
545
  }), indices = _useAutocomplete.indices, refineAutocomplete = _useAutocomplete.refine, currentRefinement = _useAutocomplete.currentRefinement;
346
546
  var resolvedQuery = currentRefinement !== undefined ? currentRefinement : (_indexUiState_query = indexUiState.query) !== null && _indexUiState_query !== void 0 ? _indexUiState_query : '';
347
- var _useDetachedMode = useDetachedMode(detachedMediaQuery), isDetached = _useDetachedMode.isDetached, isModalDetached = _useDetachedMode.isModalDetached, isModalOpen = _useDetachedMode.isModalOpen, setIsModalOpen = _useDetachedMode.setIsModalOpen;
547
+ var isDetached = detached.isDetached, isModalDetached = detached.isModalDetached, isModalOpen = detached.isModalOpen, setIsModalOpen = detached.setIsModalOpen;
348
548
  var previousIsDetachedRef = useRef(isDetached);
349
549
  var _useStorage = useStorage({
350
550
  showRecent: showRecent,
@@ -363,11 +563,11 @@ function InnerAutocomplete(_0) {
363
563
  });
364
564
  }) : index.hits;
365
565
  if (index.indexName !== promptSuggestionsIndexName) {
366
- return _$4(_$1({}, index), {
566
+ return _$4(_$2({}, index), {
367
567
  hits: dedupedHits
368
568
  });
369
569
  }
370
- return _$4(_$1({}, index), {
570
+ return _$4(_$2({}, index), {
371
571
  hits: getPromptSuggestionHits({
372
572
  hits: dedupedHits,
373
573
  limit: promptSuggestionsLimit
@@ -387,7 +587,7 @@ function InnerAutocomplete(_0) {
387
587
  if (index.indexName !== promptSuggestionsIndexName) {
388
588
  return index;
389
589
  }
390
- return _$4(_$1({}, index), {
590
+ return _$4(_$2({}, index), {
391
591
  hits: getPromptSuggestionHits({
392
592
  hits: index.hits,
393
593
  limit: promptSuggestionsLimit
@@ -410,6 +610,7 @@ function InnerAutocomplete(_0) {
410
610
  });
411
611
  var shouldHideEmptyPanel = allIndicesEmpty && recentEmpty && !hasNoResultsTemplate && !PanelComponent;
412
612
  var _usePropGetters = usePropGetters({
613
+ id: domId,
413
614
  indices: indicesForPropGettersWithPromptSuggestions,
414
615
  indicesConfig: indicesConfigForPropGetters,
415
616
  onRefine: function onRefine(query) {
@@ -438,7 +639,7 @@ function InnerAutocomplete(_0) {
438
639
  return;
439
640
  }
440
641
  if (!isSearchPage && typeof getSearchPageURL !== 'undefined') {
441
- window.location.href = getSearchPageURL(_$4(_$1({}, indexUiState), {
642
+ window.location.href = getSearchPageURL(_$4(_$2({}, indexUiState), {
442
643
  query: query
443
644
  }));
444
645
  return;
@@ -529,8 +730,8 @@ function InnerAutocomplete(_0) {
529
730
  ItemComponent: currentIndexConfig.itemComponent,
530
731
  NoResultsComponent: currentIndexConfig.noResultsComponent,
531
732
  items: hits.map(function(item) {
532
- return _$4(_$1({}, item), {
533
- __indexName: indexId
733
+ return _$4(_$2({}, item), {
734
+ __indexName: indexName
534
735
  });
535
736
  }),
536
737
  getItemProps: getItemProps,
@@ -576,7 +777,7 @@ function InnerAutocomplete(_0) {
576
777
  aiModeButtonDisabled: aiMode ? isChatBusy(chatRenderState) : undefined,
577
778
  classNames: classNames
578
779
  });
579
- var panelContent = /*#__PURE__*/ React.createElement(AutocompletePanel, _$4(_$1({}, getPanelProps()), {
780
+ var panelContent = /*#__PURE__*/ React.createElement(AutocompletePanel, _$4(_$2({}, getPanelProps()), {
580
781
  classNames: {
581
782
  root: classNames === null || classNames === void 0 ? void 0 : classNames.panel,
582
783
  open: classNames === null || classNames === void 0 ? void 0 : classNames.panelOpen,
@@ -588,14 +789,14 @@ function InnerAutocomplete(_0) {
588
789
  }) : Object.keys(elements).map(function(elementId) {
589
790
  return elements[elementId];
590
791
  }));
591
- var detachedContainerClassNames = isModalDetached ? _$4(_$1({}, classNames), {
792
+ var detachedContainerClassNames = isModalDetached ? _$4(_$2({}, classNames), {
592
793
  detachedContainer: cx('ais-AutocompleteDetachedContainer--modal', classNames === null || classNames === void 0 ? void 0 : classNames.detachedContainer)
593
794
  }) : classNames;
594
795
  var _getRootProps = getRootProps(), rootRef = _getRootProps.ref, rootProps = _(_getRootProps, [
595
796
  "ref"
596
797
  ]);
597
798
  if (isDetached) {
598
- return /*#__PURE__*/ React.createElement(Autocomplete, _$4(_$1({}, props, rootProps), {
799
+ return /*#__PURE__*/ React.createElement(Autocomplete, _$4(_$2({}, props, rootProps), {
599
800
  rootRef: rootRef,
600
801
  classNames: classNames
601
802
  }), /*#__PURE__*/ React.createElement(AutocompleteDetachedSearchButton, {
@@ -621,7 +822,7 @@ function InnerAutocomplete(_0) {
621
822
  }, searchBoxContent), panelContent)));
622
823
  }
623
824
  // Normal (non-detached) rendering
624
- return /*#__PURE__*/ React.createElement(Autocomplete, _$4(_$1({}, props, rootProps), {
825
+ return /*#__PURE__*/ React.createElement(Autocomplete, _$4(_$2({}, props, rootProps), {
625
826
  rootRef: rootRef,
626
827
  classNames: classNames
627
828
  }), searchBoxContent, panelContent);
@@ -7,7 +7,7 @@ import { _ as _$1 } from '@swc/helpers/esm/_to_array.js';
7
7
  import { createChatComponent } from 'instantsearch-ui-components';
8
8
  import { SearchIndexToolType, RecommendToolType, DisplayResultsToolType, MemorizeToolType, MemorySearchToolType, PonderToolType } from 'instantsearch.js/es/lib/chat/index.js';
9
9
  export { DisplayResultsToolType, MemorizeToolType, MemorySearchToolType, PonderToolType, RecommendToolType, SearchIndexToolType } from 'instantsearch.js/es/lib/chat/index.js';
10
- import React, { createElement, Fragment, useState, useRef, useMemo, useImperativeHandle, useEffect } from 'react';
10
+ import React, { createElement, Fragment, memo, useState, useRef, useMemo, useImperativeHandle, useEffect } from 'react';
11
11
  import { useInstantSearch, useChat } from 'react-instantsearch-core';
12
12
  import { useStickToBottom } from '../lib/useStickToBottom.js';
13
13
  import { createDisplayResultsTool } from './chat/tools/DisplayResultsTool.js';
@@ -15,7 +15,8 @@ import { createCarouselTool } from './chat/tools/SearchIndexTool.js';
15
15
 
16
16
  var ChatUiComponent = createChatComponent({
17
17
  createElement: createElement,
18
- Fragment: Fragment
18
+ Fragment: Fragment,
19
+ memo: memo
19
20
  });
20
21
  function createDefaultTools(itemComponent, getSearchPageURL) {
21
22
  var _obj;
@@ -103,6 +104,23 @@ function ChatInner(_0, _1) {
103
104
  }, [
104
105
  open
105
106
  ]);
107
+ // Keep the conversation pinned to the bottom while streaming. The stick-to-
108
+ // bottom ResizeObserver only reacts to content *height* changes, but tool
109
+ // results such as a horizontally-growing carousel stream in without changing
110
+ // height — so we also re-pin on every message/status update. Passing
111
+ // `preserveScrollPosition` reuses the existing "only if already at the
112
+ // bottom" gate, so this never fights a user who has scrolled up to read.
113
+ useEffect(function() {
114
+ if (status === 'streaming' || status === 'submitted') {
115
+ scrollToBottom({
116
+ preserveScrollPosition: true
117
+ });
118
+ }
119
+ }, [
120
+ messages,
121
+ status,
122
+ scrollToBottom
123
+ ]);
106
124
  return /*#__PURE__*/ React.createElement(ChatUiComponent, {
107
125
  title: title,
108
126
  open: open,