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.
@@ -65,6 +65,16 @@ var AutocompleteDetachedSearchButton = (0, _instantsearchuicomponents.createAuto
65
65
  Fragment: _react.Fragment
66
66
  });
67
67
  var id = 0;
68
+ // Colons (`:r0:`) preserved so concatenations like `autocomplete:r0:input`
69
+ // have a recognisable boundary; callers that need a colon-free variant for
70
+ // InstantSearch's `indexId` strip them at the use site.
71
+ var useAutocompleteId = _react.default.useId ? function() {
72
+ return _react.default.useId();
73
+ } : function() {
74
+ return _react.default.useState(function() {
75
+ return ":a".concat(id++, ":");
76
+ })[0];
77
+ };
68
78
  var usePropGetters = (0, _instantsearchuicomponents.createAutocompletePropGetters)({
69
79
  useEffect: _react.useEffect,
70
80
  useId: _react.default.useId || function() {
@@ -200,91 +210,185 @@ function getMediaQueryList(mediaQuery) {
200
210
  setIsModalOpen: setIsModalOpen
201
211
  };
202
212
  }
203
- function EXPERIMENTAL_Autocomplete(_0) {
204
- 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 = _object_without_properties._(_0, [
205
- "indices",
213
+ function EXPERIMENTAL_Autocomplete(props) {
214
+ var _showRecent_classNames, _showRecent_classNames1, _showRecent_classNames2, _showRecent_classNames3;
215
+ var indices = 'indices' in props ? props.indices : undefined;
216
+ var feeds = 'feeds' in props ? props.feeds : undefined;
217
+ var isFeedsMode = feeds !== undefined;
218
+ 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 = _object_without_properties._(props, [
206
219
  "showQuerySuggestions",
207
220
  "showPromptSuggestions",
208
221
  "showRecent",
209
222
  "searchParameters",
210
223
  "detachedMediaQuery",
211
224
  "translations",
212
- "aiMode"
225
+ "transformItems"
213
226
  ]);
214
- var _showRecent_classNames, _showRecent_classNames1, _showRecent_classNames2, _showRecent_classNames3;
227
+ var autoFocus = restProps.autoFocus, placeholder = restProps.placeholder, classNames = restProps.classNames;
228
+ // Eager-mount only when `autoFocus` is set — otherwise wait for first focus
229
+ // before registering the autocomplete subtree in the search graph.
230
+ var _useState = _sliced_to_array._((0, _react.useState)(autoFocus === true), 2), activated = _useState[0], setActivated = _useState[1];
215
231
  var translations = _object_spread._({}, DEFAULT_TRANSLATIONS, userTranslations);
216
232
  var _useInstantSearch = (0, _reactinstantsearchcore.useInstantSearch)(), indexUiState = _useInstantSearch.indexUiState, indexRenderState = _useInstantSearch.indexRenderState, status = _useInstantSearch.status;
233
+ var compositionID = (0, _reactinstantsearchcore.useInstantSearchContext)().compositionID;
217
234
  var refine = (0, _reactinstantsearchcore.useSearchBox)({}, _object_spread._({
218
235
  $$type: 'ais.autocomplete',
219
236
  $$widgetType: 'ais.autocomplete'
220
- }, aiMode ? {
237
+ }, props.aiMode ? {
221
238
  opensChat: true
222
239
  } : {})).refine;
240
+ var domId = useAutocompleteId();
241
+ var instanceKey = domId.replace(/:/g, '');
242
+ if (isFeedsMode && indices !== undefined) {
243
+ throw new Error('EXPERIMENTAL_Autocomplete: `feeds` and `indices` are mutually exclusive.');
244
+ }
245
+ if (isFeedsMode && !compositionID) {
246
+ throw new Error('EXPERIMENTAL_Autocomplete in feeds-mode requires a composition-based <InstantSearch> (compositionID must be set).');
247
+ }
223
248
  var isSearchStalled = status === 'stalled';
224
249
  var searchParameters = _object_spread._({
225
250
  hitsPerPage: 5
226
251
  }, userSearchParameters);
227
- var indicesConfig = _to_consumable_array._(indices);
228
- if (showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.indexName) {
229
- var _showQuerySuggestions_classNames, _showQuerySuggestions_classNames1, _showQuerySuggestions_classNames2, _showQuerySuggestions_classNames3;
230
- indicesConfig.unshift({
231
- indexName: showQuerySuggestions.indexName,
232
- headerComponent: showQuerySuggestions.headerComponent,
233
- itemComponent: showQuerySuggestions.itemComponent || function(param) {
234
- var item = param.item, onSelect = param.onSelect, onApply = param.onApply;
235
- return /*#__PURE__*/ _react.default.createElement(AutocompleteSuggestion, {
236
- item: item,
237
- onSelect: onSelect,
238
- onApply: onApply
239
- }, /*#__PURE__*/ _react.default.createElement(ConditionalReverseHighlight, {
240
- item: item
241
- }));
242
- },
243
- classNames: {
244
- root: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestions', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames === void 0 ? void 0 : _showQuerySuggestions_classNames.root),
245
- list: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsList', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames1 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames1 === void 0 ? void 0 : _showQuerySuggestions_classNames1.list),
246
- header: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsHeader', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames2 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames2 === void 0 ? void 0 : _showQuerySuggestions_classNames2.header),
247
- item: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsItem', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames3 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames3 === void 0 ? void 0 : _showQuerySuggestions_classNames3.item)
248
- },
249
- searchParameters: _object_spread._({
252
+ // In feeds-mode `indexName` carries the feedID so downstream matching
253
+ // (section building, dedupe in createAutocompleteStorage) treats feeds
254
+ // like indices without any changes to InnerAutocomplete.
255
+ var querySuggestionsKey = isFeedsMode ? showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.feedID : showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : showQuerySuggestions.indexName;
256
+ var promptSuggestionsKey = isFeedsMode ? showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.feedID : showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.indexName;
257
+ var indicesConfig = (0, _react.useMemo)(function() {
258
+ var config = isFeedsMode ? feeds.map(function(feed) {
259
+ return {
260
+ indexName: feed.feedID,
261
+ headerComponent: feed.headerComponent,
262
+ itemComponent: feed.itemComponent,
263
+ noResultsComponent: feed.noResultsComponent,
264
+ getURL: feed.getURL,
265
+ getQuery: feed.getQuery,
266
+ classNames: feed.classNames
267
+ };
268
+ }) : _to_consumable_array._(indices !== null && indices !== void 0 ? indices : []);
269
+ if (querySuggestionsKey) {
270
+ var _showQuerySuggestions_classNames, _showQuerySuggestions_classNames1, _showQuerySuggestions_classNames2, _showQuerySuggestions_classNames3;
271
+ var querySuggestionsSearchParameters = isFeedsMode ? undefined : _object_spread._({
250
272
  hitsPerPage: 3
251
- }, showQuerySuggestions.searchParameters),
252
- getQuery: function getQuery(item) {
253
- return item.query;
254
- },
255
- getURL: showQuerySuggestions.getURL
256
- });
257
- }
258
- if (showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : showPromptSuggestions.indexName) {
259
- var _showPromptSuggestions_classNames, _showPromptSuggestions_classNames1, _showPromptSuggestions_classNames2, _showPromptSuggestions_classNames3;
260
- indicesConfig.push({
261
- indexName: showPromptSuggestions.indexName,
262
- headerComponent: showPromptSuggestions.headerComponent,
263
- itemComponent: showPromptSuggestions.itemComponent || function(param) {
264
- var item = param.item, onSelect = param.onSelect;
265
- return /*#__PURE__*/ _react.default.createElement(AutocompletePromptSuggestion, {
266
- item: item,
267
- onSelect: onSelect
268
- }, /*#__PURE__*/ _react.default.createElement(ConditionalHighlight, {
269
- item: item,
270
- attribute: "prompt"
271
- }));
272
- },
273
- classNames: {
274
- root: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestions', (_showPromptSuggestions_classNames = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames === void 0 ? void 0 : _showPromptSuggestions_classNames.root),
275
- list: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsList', (_showPromptSuggestions_classNames1 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames1 === void 0 ? void 0 : _showPromptSuggestions_classNames1.list),
276
- header: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsHeader', (_showPromptSuggestions_classNames2 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames2 === void 0 ? void 0 : _showPromptSuggestions_classNames2.header),
277
- item: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsItem', (_showPromptSuggestions_classNames3 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames3 === void 0 ? void 0 : _showPromptSuggestions_classNames3.item)
278
- },
279
- searchParameters: _object_spread._({
273
+ }, showQuerySuggestions.searchParameters);
274
+ config.unshift({
275
+ indexName: querySuggestionsKey,
276
+ headerComponent: showQuerySuggestions.headerComponent,
277
+ itemComponent: showQuerySuggestions.itemComponent || function(param) {
278
+ var item = param.item, onSelect = param.onSelect, onApply = param.onApply;
279
+ return /*#__PURE__*/ _react.default.createElement(AutocompleteSuggestion, {
280
+ item: item,
281
+ onSelect: onSelect,
282
+ onApply: onApply
283
+ }, /*#__PURE__*/ _react.default.createElement(ConditionalReverseHighlight, {
284
+ item: item
285
+ }));
286
+ },
287
+ classNames: {
288
+ root: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestions', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames === void 0 ? void 0 : _showQuerySuggestions_classNames.root),
289
+ list: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsList', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames1 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames1 === void 0 ? void 0 : _showQuerySuggestions_classNames1.list),
290
+ header: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsHeader', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames2 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames2 === void 0 ? void 0 : _showQuerySuggestions_classNames2.header),
291
+ item: (0, _instantsearchuicomponents.cx)('ais-AutocompleteSuggestionsItem', showQuerySuggestions === null || showQuerySuggestions === void 0 ? void 0 : (_showQuerySuggestions_classNames3 = showQuerySuggestions.classNames) === null || _showQuerySuggestions_classNames3 === void 0 ? void 0 : _showQuerySuggestions_classNames3.item)
292
+ },
293
+ searchParameters: querySuggestionsSearchParameters,
294
+ getQuery: function getQuery(item) {
295
+ return item.query;
296
+ },
297
+ getURL: showQuerySuggestions.getURL
298
+ });
299
+ }
300
+ if (promptSuggestionsKey) {
301
+ var _showPromptSuggestions_classNames, _showPromptSuggestions_classNames1, _showPromptSuggestions_classNames2, _showPromptSuggestions_classNames3;
302
+ var promptSuggestionsSearchParameters = isFeedsMode ? undefined : _object_spread._({
280
303
  hitsPerPage: 3
281
- }, showPromptSuggestions.searchParameters),
282
- getQuery: function getQuery(item) {
283
- return item.prompt;
284
- },
285
- getURL: showPromptSuggestions.getURL
286
- });
287
- }
304
+ }, showPromptSuggestions.searchParameters);
305
+ config.push({
306
+ indexName: promptSuggestionsKey,
307
+ headerComponent: showPromptSuggestions.headerComponent,
308
+ itemComponent: showPromptSuggestions.itemComponent || function(param) {
309
+ var item = param.item, onSelect = param.onSelect;
310
+ return /*#__PURE__*/ _react.default.createElement(AutocompletePromptSuggestion, {
311
+ item: item,
312
+ onSelect: onSelect
313
+ }, /*#__PURE__*/ _react.default.createElement(ConditionalHighlight, {
314
+ item: item,
315
+ attribute: "prompt"
316
+ }));
317
+ },
318
+ classNames: {
319
+ root: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestions', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames === void 0 ? void 0 : _showPromptSuggestions_classNames.root),
320
+ list: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsList', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames1 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames1 === void 0 ? void 0 : _showPromptSuggestions_classNames1.list),
321
+ header: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsHeader', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames2 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames2 === void 0 ? void 0 : _showPromptSuggestions_classNames2.header),
322
+ item: (0, _instantsearchuicomponents.cx)('ais-AutocompletePromptSuggestionsItem', showPromptSuggestions === null || showPromptSuggestions === void 0 ? void 0 : (_showPromptSuggestions_classNames3 = showPromptSuggestions.classNames) === null || _showPromptSuggestions_classNames3 === void 0 ? void 0 : _showPromptSuggestions_classNames3.item)
323
+ },
324
+ searchParameters: promptSuggestionsSearchParameters,
325
+ getQuery: function getQuery(item) {
326
+ return item.prompt;
327
+ },
328
+ getURL: showPromptSuggestions.getURL
329
+ });
330
+ }
331
+ return config;
332
+ }, [
333
+ feeds,
334
+ indices,
335
+ isFeedsMode,
336
+ promptSuggestionsKey,
337
+ querySuggestionsKey,
338
+ showPromptSuggestions,
339
+ showQuerySuggestions
340
+ ]);
341
+ // Normalize `show*` for InnerAutocomplete: always surface `indexName`
342
+ // (in feeds-mode it carries the feedID). Keeps downstream dedupe in
343
+ // createAutocompleteStorage (suggestionsIndexName === index.indexName) working.
344
+ var normalizedShowQuerySuggestions = (0, _react.useMemo)(function() {
345
+ if (!showQuerySuggestions) {
346
+ return undefined;
347
+ }
348
+ if (isFeedsMode) {
349
+ return _object_spread_props._(_object_spread._({}, showQuerySuggestions), {
350
+ indexName: querySuggestionsKey
351
+ });
352
+ }
353
+ return showQuerySuggestions;
354
+ }, [
355
+ isFeedsMode,
356
+ querySuggestionsKey,
357
+ showQuerySuggestions
358
+ ]);
359
+ var normalizedShowPromptSuggestions = (0, _react.useMemo)(function() {
360
+ if (!showPromptSuggestions) {
361
+ return undefined;
362
+ }
363
+ if (isFeedsMode) {
364
+ return _object_spread_props._(_object_spread._({}, showPromptSuggestions), {
365
+ indexName: promptSuggestionsKey
366
+ });
367
+ }
368
+ return showPromptSuggestions;
369
+ }, [
370
+ isFeedsMode,
371
+ promptSuggestionsKey,
372
+ showPromptSuggestions
373
+ ]);
374
+ // In feeds-mode, remap `indexName := indexId` so downstream storage (which
375
+ // matches on indexName) sees feedIDs instead of the composition index name
376
+ // that connectAutocomplete sets from the helper results.
377
+ // Must be memoized: useConnector's useStableValue runs dequal on each render
378
+ // and treats a new function identity as a change, re-registering the widget.
379
+ var effectiveTransformItems = (0, _react.useMemo)(function() {
380
+ return isFeedsMode ? function(items) {
381
+ var remapped = items.map(function(item) {
382
+ return _object_spread_props._(_object_spread._({}, item), {
383
+ indexName: item.indexId
384
+ });
385
+ });
386
+ return transformItems ? transformItems(remapped) : remapped;
387
+ } : transformItems;
388
+ }, [
389
+ isFeedsMode,
390
+ transformItems
391
+ ]);
288
392
  var recentSearchConfig = showRecent ? {
289
393
  headerComponent: (typeof showRecent === "undefined" ? "undefined" : _type_of._(showRecent)) === 'object' ? showRecent.headerComponent : undefined,
290
394
  itemComponent: (typeof showRecent === "undefined" ? "undefined" : _type_of._(showRecent)) === 'object' && showRecent.itemComponent ? showRecent.itemComponent : AutocompleteRecentSearch,
@@ -300,15 +404,88 @@ function EXPERIMENTAL_Autocomplete(_0) {
300
404
  }, [
301
405
  indexRenderState
302
406
  ]);
303
- return /*#__PURE__*/ _react.default.createElement(_react.Fragment, null, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Index, {
304
- EXPERIMENTAL_isolated: true
305
- }, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Configure, searchParameters), indicesConfig.map(function(index) {
306
- return /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Index, {
307
- key: index.indexName,
308
- indexName: index.indexName
309
- }, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Configure, index.searchParameters));
310
- }), /*#__PURE__*/ _react.default.createElement(InnerAutocomplete, _object_spread_props._(_object_spread._({}, props), {
311
- aiMode: aiMode,
407
+ restProps.indices; restProps.feeds; var forwardedProps = _object_without_properties._(restProps, [
408
+ "indices",
409
+ "feeds"
410
+ ]);
411
+ var instance = (0, _reactinstantsearchcore.useInstantSearchContext)();
412
+ var detached = useDetachedMode(detachedMediaQuery);
413
+ var isDetached = detached.isDetached, setIsModalOpen = detached.setIsModalOpen;
414
+ // Lazy activation only: when `activated` flips from false to true, the
415
+ // newly-mounted isolated `<Index>` schedules the parent's search even
416
+ // though the parent's state hasn't changed. Cancel it so only the
417
+ // autocomplete's own search fires on activation. Skip when `autoFocus`
418
+ // mounts the inner eagerly — the parent's legitimate initial search
419
+ // shares the same defer slot and must not be cancelled.
420
+ var initialActivatedRef = (0, _react.useRef)(activated);
421
+ (0, _react.useLayoutEffect)(function() {
422
+ if (activated && !initialActivatedRef.current) {
423
+ initialActivatedRef.current = true;
424
+ instance.scheduleSearch.cancel();
425
+ }
426
+ }, [
427
+ activated,
428
+ instance
429
+ ]);
430
+ if (!activated) {
431
+ var _indexUiState_query, _indexUiState_query1;
432
+ restProps.indices; restProps.feeds; restProps.autoFocus; restProps.placeholder; restProps.classNames; restProps.aiMode; restProps.panelComponent; restProps.getSearchPageURL; restProps.onSelect; var shellRootProps = _object_without_properties._(restProps, [
433
+ "indices",
434
+ "feeds",
435
+ "autoFocus",
436
+ "placeholder",
437
+ "classNames",
438
+ "aiMode",
439
+ "panelComponent",
440
+ "getSearchPageURL",
441
+ "onSelect"
442
+ ]);
443
+ var activateWithQueryMirror = function activateWithQueryMirror() {
444
+ // Routing only fills the parent index's UI state, not the
445
+ // autocomplete's isolated one, so without this, the autocomplete
446
+ // would activate with an empty query and fire a useless search.
447
+ // We copy the parent's query into the autocomplete's slot of
448
+ // `_initialUiState` right before flipping `activated`: that's the
449
+ // moment the isolated `<Index>` is about to mount and read it.
450
+ // Doing this later would mean firing a second search to correct
451
+ // the first.
452
+ if (indexUiState.query) {
453
+ var isoIndexId = "ais-autocomplete-".concat(instanceKey);
454
+ var initial = instance._initialUiState;
455
+ initial[isoIndexId] = _object_spread_props._(_object_spread._({}, initial[isoIndexId]), {
456
+ query: indexUiState.query
457
+ });
458
+ }
459
+ setActivated(true);
460
+ };
461
+ return /*#__PURE__*/ _react.default.createElement(Autocomplete, _object_spread_props._(_object_spread._({}, shellRootProps), {
462
+ classNames: classNames
463
+ }), isDetached ? /*#__PURE__*/ _react.default.createElement(AutocompleteDetachedSearchButton, {
464
+ query: (_indexUiState_query = indexUiState.query) !== null && _indexUiState_query !== void 0 ? _indexUiState_query : '',
465
+ placeholder: placeholder,
466
+ classNames: classNames,
467
+ translations: translations,
468
+ onClick: function onClick() {
469
+ setIsModalOpen(true);
470
+ activateWithQueryMirror();
471
+ }
472
+ }) : /*#__PURE__*/ _react.default.createElement(_AutocompleteSearch.AutocompleteSearch, {
473
+ inputProps: {
474
+ id: "autocomplete".concat(domId, "input"),
475
+ role: 'combobox',
476
+ placeholder: placeholder,
477
+ onFocus: activateWithQueryMirror
478
+ },
479
+ clearQuery: function clearQuery() {},
480
+ query: (_indexUiState_query1 = indexUiState.query) !== null && _indexUiState_query1 !== void 0 ? _indexUiState_query1 : '',
481
+ isSearchStalled: false,
482
+ classNames: classNames
483
+ }));
484
+ }
485
+ var innerAutocomplete = /*#__PURE__*/ _react.default.createElement(InnerAutocomplete, _object_spread_props._(_object_spread._({}, forwardedProps), {
486
+ autoFocus: true,
487
+ domId: domId,
488
+ detached: detached,
312
489
  indicesConfig: indicesConfig,
313
490
  refineSearchBox: refine,
314
491
  isSearchStalled: isSearchStalled,
@@ -316,15 +493,37 @@ function EXPERIMENTAL_Autocomplete(_0) {
316
493
  isSearchPage: isSearchPage,
317
494
  showRecent: showRecent,
318
495
  recentSearchConfig: recentSearchConfig,
319
- showQuerySuggestions: showQuerySuggestions,
320
- detachedMediaQuery: detachedMediaQuery,
496
+ showQuerySuggestions: normalizedShowQuerySuggestions,
321
497
  translations: translations,
322
- showPromptSuggestions: showPromptSuggestions,
498
+ showPromptSuggestions: normalizedShowPromptSuggestions,
499
+ transformItems: effectiveTransformItems,
323
500
  chatRenderState: indexRenderState.chat
324
- }))));
501
+ }));
502
+ if (isFeedsMode) {
503
+ return /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Index, {
504
+ EXPERIMENTAL_isolated: true,
505
+ indexName: compositionID,
506
+ indexId: "ais-autocomplete-".concat(instanceKey)
507
+ }, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Configure, searchParameters), /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Feeds, {
508
+ isolated: false,
509
+ renderFeed: function renderFeed() {
510
+ return null;
511
+ }
512
+ }), innerAutocomplete);
513
+ }
514
+ return /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Index, {
515
+ EXPERIMENTAL_isolated: true,
516
+ indexId: "ais-autocomplete-".concat(instanceKey)
517
+ }, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Configure, searchParameters), indicesConfig.map(function(index) {
518
+ return /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Index, {
519
+ key: index.indexName,
520
+ indexName: index.indexName,
521
+ indexId: "ais-autocomplete-".concat(instanceKey, "-").concat(index.indexName)
522
+ }, /*#__PURE__*/ _react.default.createElement(_reactinstantsearchcore.Configure, index.searchParameters));
523
+ }), innerAutocomplete);
325
524
  }
326
525
  function InnerAutocomplete(_0) {
327
- 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 = _object_without_properties._(_0, [
526
+ 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 = _object_without_properties._(_0, [
328
527
  "indicesConfig",
329
528
  "refineSearchBox",
330
529
  "isSearchStalled",
@@ -341,10 +540,11 @@ function InnerAutocomplete(_0) {
341
540
  "transformItems",
342
541
  "placeholder",
343
542
  "autoFocus",
344
- "detachedMediaQuery",
345
543
  "translations",
346
544
  "classNames",
347
- "aiMode"
545
+ "aiMode",
546
+ "domId",
547
+ "detached"
348
548
  ]);
349
549
  var _indexUiState_query, _ref;
350
550
  var _showPromptSuggestions_searchParameters;
@@ -355,7 +555,7 @@ function InnerAutocomplete(_0) {
355
555
  }
356
556
  }), indices = _useAutocomplete.indices, refineAutocomplete = _useAutocomplete.refine, currentRefinement = _useAutocomplete.currentRefinement;
357
557
  var resolvedQuery = currentRefinement !== undefined ? currentRefinement : (_indexUiState_query = indexUiState.query) !== null && _indexUiState_query !== void 0 ? _indexUiState_query : '';
358
- var _useDetachedMode = useDetachedMode(detachedMediaQuery), isDetached = _useDetachedMode.isDetached, isModalDetached = _useDetachedMode.isModalDetached, isModalOpen = _useDetachedMode.isModalOpen, setIsModalOpen = _useDetachedMode.setIsModalOpen;
558
+ var isDetached = detached.isDetached, isModalDetached = detached.isModalDetached, isModalOpen = detached.isModalOpen, setIsModalOpen = detached.setIsModalOpen;
359
559
  var previousIsDetachedRef = (0, _react.useRef)(isDetached);
360
560
  var _useStorage = useStorage({
361
561
  showRecent: showRecent,
@@ -421,6 +621,7 @@ function InnerAutocomplete(_0) {
421
621
  });
422
622
  var shouldHideEmptyPanel = allIndicesEmpty && recentEmpty && !hasNoResultsTemplate && !PanelComponent;
423
623
  var _usePropGetters = usePropGetters({
624
+ id: domId,
424
625
  indices: indicesForPropGettersWithPromptSuggestions,
425
626
  indicesConfig: indicesConfigForPropGetters,
426
627
  onRefine: function onRefine(query) {
@@ -541,7 +742,7 @@ function InnerAutocomplete(_0) {
541
742
  NoResultsComponent: currentIndexConfig.noResultsComponent,
542
743
  items: hits.map(function(item) {
543
744
  return _object_spread_props._(_object_spread._({}, item), {
544
- __indexName: indexId
745
+ __indexName: indexName
545
746
  });
546
747
  }),
547
748
  getItemProps: getItemProps,
@@ -51,7 +51,8 @@ var _DisplayResultsTool = require("./chat/tools/DisplayResultsTool");
51
51
  var _SearchIndexTool = require("./chat/tools/SearchIndexTool");
52
52
  var ChatUiComponent = (0, _instantsearchuicomponents.createChatComponent)({
53
53
  createElement: _react.createElement,
54
- Fragment: _react.Fragment
54
+ Fragment: _react.Fragment,
55
+ memo: _react.memo
55
56
  });
56
57
  function createDefaultTools(itemComponent, getSearchPageURL) {
57
58
  var _obj;
@@ -139,6 +140,23 @@ function ChatInner(_0, _1) {
139
140
  }, [
140
141
  open
141
142
  ]);
143
+ // Keep the conversation pinned to the bottom while streaming. The stick-to-
144
+ // bottom ResizeObserver only reacts to content *height* changes, but tool
145
+ // results such as a horizontally-growing carousel stream in without changing
146
+ // height — so we also re-pin on every message/status update. Passing
147
+ // `preserveScrollPosition` reuses the existing "only if already at the
148
+ // bottom" gate, so this never fights a user who has scrolled up to read.
149
+ (0, _react.useEffect)(function() {
150
+ if (status === 'streaming' || status === 'submitted') {
151
+ scrollToBottom({
152
+ preserveScrollPosition: true
153
+ });
154
+ }
155
+ }, [
156
+ messages,
157
+ status,
158
+ scrollToBottom
159
+ ]);
142
160
  return /*#__PURE__*/ _react.default.createElement(ChatUiComponent, {
143
161
  title: title,
144
162
  open: open,
@@ -21,36 +21,74 @@ type AutocompleteTranslations = {
21
21
  detachedSearchButtonTitle: string;
22
22
  detachedClearButtonTitle: string;
23
23
  };
24
- export type AutocompleteProps<TItem extends BaseHit> = ComponentProps<'div'> & {
25
- indices?: Array<IndexConfig<TItem>>;
26
- showQuerySuggestions?: Partial<Pick<IndexConfig<{
24
+ export type FeedConfig<TItem extends BaseHit> = {
25
+ feedID: string;
26
+ headerComponent?: AutocompleteIndexProps<TItem>['HeaderComponent'];
27
+ itemComponent: AutocompleteIndexProps<TItem>['ItemComponent'];
28
+ noResultsComponent?: AutocompleteIndexProps<TItem>['NoResultsComponent'];
29
+ getURL?: AutocompleteIndexConfig<TItem>['getURL'];
30
+ getQuery?: AutocompleteIndexConfig<TItem>['getQuery'];
31
+ classNames?: Partial<AutocompleteIndexClassNames>;
32
+ };
33
+ type IndicesShowQuerySuggestionsConfig = Partial<Pick<IndexConfig<{
34
+ query: string;
35
+ }>, 'indexName' | 'getURL' | 'headerComponent' | 'itemComponent' | 'classNames' | 'searchParameters'>>;
36
+ type FeedsShowQuerySuggestionsConfig = {
37
+ feedID: string;
38
+ getURL?: IndexConfig<{
27
39
  query: string;
28
- }>, 'indexName' | 'getURL' | 'headerComponent' | 'itemComponent' | 'classNames' | 'searchParameters'>>;
29
- showPromptSuggestions?: Partial<Pick<IndexConfig<{
40
+ }>['getURL'];
41
+ headerComponent?: IndexConfig<{
42
+ query: string;
43
+ }>['headerComponent'];
44
+ itemComponent?: IndexConfig<{
45
+ query: string;
46
+ }>['itemComponent'];
47
+ classNames?: Partial<AutocompleteIndexClassNames>;
48
+ };
49
+ type IndicesShowPromptSuggestionsConfig = Partial<Pick<IndexConfig<{
50
+ query: string;
51
+ label?: string;
52
+ }>, 'indexName' | 'getURL' | 'headerComponent' | 'itemComponent' | 'classNames' | 'searchParameters'>>;
53
+ type FeedsShowPromptSuggestionsConfig = {
54
+ feedID: string;
55
+ getURL?: IndexConfig<{
56
+ query: string;
57
+ label?: string;
58
+ }>['getURL'];
59
+ headerComponent?: IndexConfig<{
30
60
  query: string;
31
61
  label?: string;
32
- }>, 'indexName' | 'getURL' | 'headerComponent' | 'itemComponent' | 'classNames' | 'searchParameters'>>;
33
- showRecent?: boolean | {
34
- /**
35
- * Storage key to use in the local storage.
36
- */
37
- storageKey?: string;
38
- /**
39
- * Component to use for the header, before the list of items.
40
- */
41
- headerComponent?: AutocompleteIndexProps<{
42
- query: string;
43
- }>['HeaderComponent'];
44
- /**
45
- * Component to use for each recent search item.
46
- */
47
- itemComponent?: AutocompleteIndexProps<{
48
- query: string;
49
- }>['ItemComponent'] & {
50
- onRemoveRecentSearch: () => void;
51
- };
52
- classNames?: Partial<AutocompleteIndexClassNames>;
62
+ }>['headerComponent'];
63
+ itemComponent?: IndexConfig<{
64
+ query: string;
65
+ label?: string;
66
+ }>['itemComponent'];
67
+ classNames?: Partial<AutocompleteIndexClassNames>;
68
+ };
69
+ type AutocompleteShowRecentConfig = {
70
+ /**
71
+ * Storage key to use in the local storage.
72
+ */
73
+ storageKey?: string;
74
+ /**
75
+ * Component to use for the header, before the list of items.
76
+ */
77
+ headerComponent?: AutocompleteIndexProps<{
78
+ query: string;
79
+ }>['HeaderComponent'];
80
+ /**
81
+ * Component to use for each recent search item.
82
+ */
83
+ itemComponent?: AutocompleteIndexProps<{
84
+ query: string;
85
+ }>['ItemComponent'] & {
86
+ onRemoveRecentSearch: () => void;
53
87
  };
88
+ classNames?: Partial<AutocompleteIndexClassNames>;
89
+ };
90
+ type AutocompleteCommonProps<TItem extends BaseHit> = ComponentProps<'div'> & {
91
+ showRecent?: boolean | AutocompleteShowRecentConfig;
54
92
  getSearchPageURL?: (nextUiState: IndexUiState) => string;
55
93
  onSelect?: AutocompleteIndexConfig<TItem>['onSelect'];
56
94
  transformItems?: (indices: TransformItemsIndicesConfig[]) => TransformItemsIndicesConfig[];
@@ -84,5 +122,18 @@ export type AutocompleteProps<TItem extends BaseHit> = ComponentProps<'div'> & {
84
122
  */
85
123
  aiMode?: boolean;
86
124
  };
87
- export declare function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>({ indices, showQuerySuggestions, showPromptSuggestions, showRecent, searchParameters: userSearchParameters, detachedMediaQuery, translations: userTranslations, aiMode, ...props }: AutocompleteProps<TItem>): React.JSX.Element;
125
+ export type AutocompleteIndicesProps<TItem extends BaseHit> = AutocompleteCommonProps<TItem> & {
126
+ indices?: Array<IndexConfig<TItem>>;
127
+ feeds?: never;
128
+ showQuerySuggestions?: IndicesShowQuerySuggestionsConfig;
129
+ showPromptSuggestions?: IndicesShowPromptSuggestionsConfig;
130
+ };
131
+ export type AutocompleteFeedsProps<TItem extends BaseHit> = AutocompleteCommonProps<TItem> & {
132
+ feeds: Array<FeedConfig<TItem>>;
133
+ indices?: never;
134
+ showQuerySuggestions?: FeedsShowQuerySuggestionsConfig;
135
+ showPromptSuggestions?: FeedsShowPromptSuggestionsConfig;
136
+ };
137
+ export type AutocompleteProps<TItem extends BaseHit> = AutocompleteIndicesProps<TItem> | AutocompleteFeedsProps<TItem>;
138
+ export declare function EXPERIMENTAL_Autocomplete<TItem extends BaseHit = BaseHit>(props: AutocompleteProps<TItem>): React.JSX.Element;
88
139
  export {};