@docsearch/react 5.0.0-beta.1 → 5.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/{AskAiScreenState-CRHicWbN.d.ts → AskAiScreenState-Sqbn60f2.d.ts} +5 -2
  3. package/dist/esm/{DocSearch-HJsNvtZr.d.ts → DocSearch-BVqxFxTw.d.ts} +20 -43
  4. package/dist/esm/{DocSearchAskAiModal-KaA6fBV4.js → DocSearchAskAiModal-C_sH1j8Y.js} +31 -38
  5. package/dist/esm/DocSearchAskAiModal-C_sH1j8Y.js.map +1 -0
  6. package/dist/esm/{DocSearchAskAiModal-B7vpLudE.d.ts → DocSearchAskAiModal-DpB7pLCC.d.ts} +4 -4
  7. package/dist/esm/{DocSearchModal-CpvDjo1O.js → DocSearchModal-CITTG0fe.js} +20 -26
  8. package/dist/esm/DocSearchModal-CITTG0fe.js.map +1 -0
  9. package/dist/esm/askaiModal.d.ts +1 -1
  10. package/dist/esm/askaiModal.js +1 -1
  11. package/dist/esm/docsearchAi.d.ts +13 -110
  12. package/dist/esm/docsearchAi.js +14 -4
  13. package/dist/esm/docsearchAi.js.map +1 -1
  14. package/dist/esm/index.d.ts +4 -4
  15. package/dist/esm/index.js +15 -5
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/modal.d.ts +1 -1
  18. package/dist/esm/modal.js +1 -1
  19. package/dist/esm/{normalizeDocSearchIndexes-DAzlMybx.js → normalizeDocSearchIndexes-ChnVvoVt.js} +105 -74
  20. package/dist/esm/normalizeDocSearchIndexes-ChnVvoVt.js.map +1 -0
  21. package/dist/esm/sidepanel.d.ts +31 -27
  22. package/dist/esm/sidepanel.js +14 -11
  23. package/dist/esm/sidepanel.js.map +1 -1
  24. package/dist/esm/useDocSearchKeyboardEvents.js +1 -1
  25. package/dist/esm/useDocSearchKeyboardEvents.js.map +1 -1
  26. package/dist/esm/useSearchClient-mIHVB6ga.js.map +1 -1
  27. package/dist/esm/{useSuggestedQuestions-CG2H3qm4.js → useSuggestedQuestions-DwcUPOf_.js} +107 -50
  28. package/dist/esm/useSuggestedQuestions-DwcUPOf_.js.map +1 -0
  29. package/dist/esm/version.d.ts +1 -1
  30. package/dist/esm/version.js +1 -1
  31. package/dist/esm/version.js.map +1 -1
  32. package/dist/umd/index.js +44 -42
  33. package/dist/umd/index.js.map +1 -1
  34. package/package.json +4 -4
  35. package/dist/esm/DocSearchAskAiModal-KaA6fBV4.js.map +0 -1
  36. package/dist/esm/DocSearchModal-CpvDjo1O.js.map +0 -1
  37. package/dist/esm/normalizeDocSearchIndexes-DAzlMybx.js.map +0 -1
  38. package/dist/esm/useSuggestedQuestions-CG2H3qm4.js.map +0 -1
package/README.md CHANGED
@@ -27,7 +27,7 @@ function App() {
27
27
  return (
28
28
  <DocSearch
29
29
  appId="YOUR_APP_ID"
30
- indexName="YOUR_INDEX_NAME"
30
+ indices={['YOUR_INDEX_NAME']}
31
31
  apiKey="YOUR_SEARCH_API_KEY"
32
32
  />
33
33
  );
@@ -1,5 +1,5 @@
1
1
  import "./index-Bqqv4HmN.js";
2
- import { f as ResultsScreenTranslations, h as StoredSearchesSectionsTranslations, m as ErrorScreenTranslations, p as NoResultsScreenTranslations } from "./DocSearch-HJsNvtZr.js";
2
+ import { _ as StoredSearchesSectionsTranslations, g as ErrorScreenTranslations, h as NoResultsScreenTranslations, m as ResultsScreenTranslations } from "./DocSearch-BVqxFxTw.js";
3
3
  import React, { JSX } from "react";
4
4
  import { AutocompleteState, BaseItem } from "@algolia/autocomplete-core";
5
5
  import "@ai-sdk/react";
@@ -20,7 +20,10 @@ type ToolCallTranslations = {
20
20
  //#region src/AskAiScreen.d.ts
21
21
  type AskAiScreenTranslations = Partial<Omit<ToolCallTranslations, 'searchingText' | 'toolCallResultText'> & {
22
22
  disclaimerText: string;
23
+ /** Text shown describing a singular related source. */
23
24
  relatedSourcesText: string;
25
+ /** Text shown describing multiple related sources. */
26
+ relatedSourcesTextPlural: string;
24
27
  thinkingText: string;
25
28
  copyButtonText: string;
26
29
  copyButtonCopiedText: string;
@@ -103,4 +106,4 @@ type AskAiScreenStateTranslations = Partial<{
103
106
  }>;
104
107
  //#endregion
105
108
  export { NewConversationTranslations as n, ToolCallTranslations as r, AskAiScreenStateTranslations as t };
106
- //# sourceMappingURL=AskAiScreenState-CRHicWbN.d.ts.map
109
+ //# sourceMappingURL=AskAiScreenState-Sqbn60f2.d.ts.map
@@ -148,7 +148,7 @@ type DocSearchModalProps = DocSearchProps & {
148
148
  onClose?: () => void;
149
149
  translations?: ModalTranslations;
150
150
  };
151
- declare function DocSearchModal({ appId, apiKey, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, indexName, searchParameters, facets, ...props }: DocSearchModalProps): JSX.Element;
151
+ declare function DocSearchModal({ appId, apiKey, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, facets, footerAction, ...props }: DocSearchModalProps): JSX.Element;
152
152
  //#endregion
153
153
  //#region src/DocSearch.d.ts
154
154
  type DocSearchTranslations = Partial<{
@@ -168,24 +168,24 @@ interface DocSearchFacet {
168
168
  key: string;
169
169
  label?: string;
170
170
  }
171
+ interface HitComponentProps {
172
+ hit: InternalDocSearchHit | StoredDocSearchHit;
173
+ children: React.ReactNode;
174
+ }
175
+ interface ResultsFooterComponentProps {
176
+ state: AutocompleteState<InternalDocSearchHit>;
177
+ }
171
178
  interface DocSearchProps {
172
179
  /** Algolia application id used by the search client. */
173
180
  appId: string;
174
181
  /** Public api key with search permissions for the index. */
175
182
  apiKey: string;
176
- /**
177
- * Name of the algolia index to query.
178
- *
179
- * @deprecated `indexName` will be removed in a future version. Please use
180
- * `indices` property going forward.
181
- */
182
- indexName?: string;
183
183
  /**
184
184
  * List of indices and _optional_ searchParameters to be used for search.
185
185
  *
186
186
  * @see {@link https://docsearch.algolia.com/docs/api#indices}
187
187
  */
188
- indices?: Array<DocSearchIndex | string>;
188
+ indices: Array<DocSearchIndex | string>;
189
189
  /**
190
190
  * Facets to display as keyword-search filter controls. Values are read
191
191
  * dynamically from the configured Algolia indices.
@@ -197,43 +197,20 @@ interface DocSearchProps {
197
197
  theme?: DocSearchTheme$1;
198
198
  /** Placeholder text for the search input. */
199
199
  placeholder?: string;
200
- /**
201
- * Additional algolia search parameters to merge into each query.
202
- *
203
- * @deprecated `searchParameters` will be removed in a future version. Please
204
- * use `indices` property going forward.
205
- */
206
- searchParameters?: SearchParamsObject;
207
200
  /** Maximum number of hits to display per source/group. */
208
201
  maxResultsPerGroup?: number;
209
202
  /** Hook to post-process hits before rendering. */
210
203
  transformItems?: (items: DocSearchHit[]) => DocSearchHit[];
204
+ /** Custom component to render an individual hit. */
205
+ hitComponent?: (props: HitComponentProps) => JSX.Element;
206
+ /** Custom component rendered at the bottom of the results panel. */
207
+ resultsFooterComponent?: (props: ResultsFooterComponentProps) => JSX.Element | null;
211
208
  /**
212
- * Custom component to render an individual hit. Supports template patterns:
213
- *
214
- * - HTML strings with html helper: (props, { html }) => html`<div>...</div>`
215
- * - JSX templates: (props) => <div>...</div>
216
- * - Function-based templates: (props) => string | JSX.Element | Function.
217
- */
218
- hitComponent?: (props: {
219
- hit: InternalDocSearchHit | StoredDocSearchHit;
220
- children: React.ReactNode;
221
- }, helpers?: {
222
- html: (template: TemplateStringsArray, ...values: any[]) => any;
223
- }) => JSX.Element;
224
- /**
225
- * Custom component rendered at the bottom of the results panel. Supports
226
- * template patterns:
227
- *
228
- * - HTML strings with html helper: (props, { html }) => html`<div>...</div>`
229
- * - JSX templates: (props) => <div>...</div>
230
- * - Function-based templates: (props) => string | JSX.Element | Function.
209
+ * A custom action that can be rendered in the Modal's footer before the
210
+ * Algolia logo. The component will be rendered as a child of `<div
211
+ * className="DocSearch-Footer-Action" />`.
231
212
  */
232
- resultsFooterComponent?: (props: {
233
- state: AutocompleteState<InternalDocSearchHit>;
234
- }, helpers?: {
235
- html: (template: TemplateStringsArray, ...values: any[]) => any;
236
- }) => JSX.Element | null;
213
+ footerAction?: React.ReactNode;
237
214
  /** Hook to wrap or modify the algolia search client. */
238
215
  transformSearchClient?: (searchClient: DocSearchTransformClient) => DocSearchTransformClient;
239
216
  /** Disable storage and usage of recent and favorite searches. */
@@ -289,7 +266,7 @@ interface DocSearchProps {
289
266
  resultBadgeKey?: string;
290
267
  }
291
268
  declare const DocSearch$1: React.ForwardRefExoticComponent<DocSearchProps & React.RefAttributes<DocSearchRef>>;
292
- declare function DocSearchInner(props: DocSearchProps): JSX.Element;
269
+ declare function DocSearchInner(props: Omit<DocSearchProps, 'appId' | 'apiKey'>): JSX.Element;
293
270
  //#endregion
294
- export { FacetBarTranslations as _, DocSearchProps as a, DocSearchTranslations as c, ModalTranslations as d, ResultsScreenTranslations as f, FooterTranslations as g, StoredSearchesSectionsTranslations as h, DocSearchInner as i, DocSearchModal as l, ErrorScreenTranslations as m, DocSearchFacet as n, DocSearchRef$1 as o, NoResultsScreenTranslations as p, DocSearchIndex as r, DocSearchTransformClient as s, DocSearch$1 as t, DocSearchModalProps as u, InternalDocSearchHit as v };
295
- //# sourceMappingURL=DocSearch-HJsNvtZr.d.ts.map
271
+ export { StoredSearchesSectionsTranslations as _, DocSearchProps as a, InternalDocSearchHit as b, DocSearchTranslations as c, DocSearchModal as d, DocSearchModalProps as f, ErrorScreenTranslations as g, NoResultsScreenTranslations as h, DocSearchInner as i, HitComponentProps as l, ResultsScreenTranslations as m, DocSearchFacet as n, DocSearchRef$1 as o, ModalTranslations as p, DocSearchIndex as r, DocSearchTransformClient as s, DocSearch$1 as t, ResultsFooterComponentProps as u, FooterTranslations as v, FacetBarTranslations as y };
272
+ //# sourceMappingURL=DocSearch-BVqxFxTw.d.ts.map
@@ -1,8 +1,8 @@
1
1
  import { t as _objectSpread2 } from "./objectSpread2-BNmiQYyW.js";
2
- import { C as noop, D as getCollection, E as SOURCE_IDS, S as scrollTo, T as identity, _ as Hit, a as NoResultsScreen, b as SearchBoxForm, c as Results, d as useRefreshOnInitialQuery, f as useModalRefs, g as useDocSearchFacets, h as useSendItemClickEvent, i as ResultsScreen, l as useStoredDocSearches, m as useInitialModalQuery, n as buildNoQuerySources, o as ErrorScreen, p as useModalEnvironment, r as buildQuerySources, s as StoredSearchesSections, t as normalizeDocSearchIndexes, u as useSaveRecentSearch, v as Footer, w as isModifierEvent, x as FacetBar, y as ModalShell } from "./normalizeDocSearchIndexes-DAzlMybx.js";
2
+ import { C as noop, D as SOURCE_IDS, E as identity, O as getCollection, S as scrollTo, T as isModifierEvent, _ as Hit, a as NoResultsScreen, b as SearchBoxForm, c as Results, d as useRefreshOnInitialQuery, f as useModalRefs, g as useDocSearchFacets, h as useSendItemClickEvent, i as ResultsScreen, l as useStoredDocSearches, m as useInitialModalQuery, n as buildNoQuerySources, o as ErrorScreen, p as useModalEnvironment, r as buildQuerySources, s as StoredSearchesSections, t as normalizeDocSearchIndexes, u as useSaveRecentSearch, v as Footer, w as isQueryEmpty, x as FacetBar, y as ModalShell } from "./normalizeDocSearchIndexes-ChnVvoVt.js";
3
3
  import { n as SearchIcon, t as _objectWithoutProperties } from "./objectWithoutProperties-phqYxDS0.js";
4
4
  import { l as CloseIcon, m as LoadingIcon, p as SparklesIcon, t as useSearchClient } from "./useSearchClient-mIHVB6ga.js";
5
- import { S as AlertIcon, _ as BackIcon, a as MemoizedMarkdown, b as MoreVerticalIcon, c as buildDummyAskAiHit, d as getMessageContent, f as isAIToolPart, g as ConversationPromptSuggestions, h as FeedbackActions, i as groupConsecutiveToolResults, l as extractLinksFromMessage, m as SourcesPanel, n as useAskAi, o as ToolCall, p as isThreadDepthError, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-CG2H3qm4.js";
5
+ import { S as AlertIcon, _ as BackIcon, a as MemoizedMarkdown, b as MoreVerticalIcon, c as buildDummyAskAiHit, d as getMessageContent, f as isAIToolPart, g as ConversationPromptSuggestions, h as FeedbackActions, i as groupConsecutiveToolResults, l as extractLinksFromMessage, m as SourcesPanel, n as useAskAi, o as ToolCall, p as isThreadDepthError, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-DwcUPOf_.js";
6
6
  import React, { Fragment, useMemo } from "react";
7
7
  import { createAutocomplete } from "@algolia/autocomplete-core";
8
8
 
@@ -69,9 +69,9 @@ function AskAiScreenDisclaimer({ disclaimerText }) {
69
69
  return /* @__PURE__ */ React.createElement("p", { className: "DocSearch-AskAiScreen-Disclaimer" }, /* @__PURE__ */ React.createElement(SparklesIcon, null), " ", disclaimerText);
70
70
  }
71
71
  function AskAiExchangeCard({ exchange, askAiError, isLastExchange, loadingStatus, onSearchQueryClick, translations, tools, conversations, onFeedback, memoryEnabled, onSelectPromptSuggestion }) {
72
- var _userMessage$metadata, _assistantMessage$met, _userContent$text;
72
+ var _userMessage$metadata, _assistantMessage$met;
73
73
  const { userMessage, assistantMessage } = exchange;
74
- const { stoppedStreamingText = "You stopped this response", errorTitleText = "Chat error", relatedSourcesText, suggestedPromptsTitleText = "Suggested prompts" } = translations;
74
+ const { stoppedStreamingText = "You stopped this response", errorTitleText = "Chat error", relatedSourcesText, relatedSourcesTextPlural, suggestedPromptsTitleText = "Suggested prompts" } = translations;
75
75
  const toolCallTranslations = useMemo(() => toToolCallTranslations(translations), [translations]);
76
76
  const isThreadDepth = isThreadDepthError(askAiError);
77
77
  const assistantContent = useMemo(() => getMessageContent(assistantMessage), [assistantMessage]);
@@ -88,7 +88,7 @@ function AskAiExchangeCard({ exchange, askAiError, isLastExchange, loadingStatus
88
88
  const showActions = !wasStopped && (!isLastExchange || isLastExchange && loadingStatus === "ready" && Boolean(assistantMessage));
89
89
  const isThinking = ["submitted", "streaming"].includes(loadingStatus) && isLastExchange && !displayParts.some((part) => part.type !== "step-start");
90
90
  const messageId = (assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.id) || exchange.id;
91
- return /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Response-Container" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Response" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user" }, /* @__PURE__ */ React.createElement("p", { className: "DocSearch-AskAiScreen-Query" }, (_userContent$text = userContent === null || userContent === void 0 ? void 0 : userContent.text) !== null && _userContent$text !== void 0 ? _userContent$text : "")), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-MessageContent" }, loadingStatus === "error" && askAiError && isLastExchange && !isThreadDepth && /* @__PURE__ */ React.createElement("div", {
91
+ return /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Response-Container" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Response" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user" }, /* @__PURE__ */ React.createElement("p", { className: "DocSearch-AskAiScreen-Query" }, userContent !== null && userContent !== void 0 ? userContent : "")), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant" }, /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-MessageContent" }, loadingStatus === "error" && askAiError && isLastExchange && !isThreadDepth && /* @__PURE__ */ React.createElement("div", {
92
92
  className: "DocSearch-AskAiScreen-Error",
93
93
  role: "alert"
94
94
  }, /* @__PURE__ */ React.createElement(AlertIcon, { "aria-hidden": "true" }), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Error-Content" }, /* @__PURE__ */ React.createElement("h4", { className: "DocSearch-AskAiScreen-Error-Title" }, errorTitleText), /* @__PURE__ */ React.createElement(MemoizedMarkdown, {
@@ -136,11 +136,12 @@ function AskAiExchangeCard({ exchange, askAiError, isLastExchange, loadingStatus
136
136
  return null;
137
137
  })), wasStopped && /* @__PURE__ */ React.createElement("p", { className: "DocSearch-AskAiScreen-MessageContent-Stopped" }, stoppedStreamingText)), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Answer-Footer" }, /* @__PURE__ */ React.createElement(SourcesPanel, {
138
138
  links: urlsToDisplay,
139
- titleText: relatedSourcesText
139
+ titleText: relatedSourcesText,
140
+ pluralTitleText: relatedSourcesTextPlural
140
141
  }), /* @__PURE__ */ React.createElement(FeedbackActions, {
141
142
  id: messageId,
142
143
  showActions,
143
- latestAssistantMessageContent: (assistantContent === null || assistantContent === void 0 ? void 0 : assistantContent.text) || null,
144
+ latestAssistantMessageContent: assistantContent || null,
144
145
  translations,
145
146
  conversations,
146
147
  onFeedback
@@ -211,7 +212,7 @@ function RecentConversationsResults(_ref) {
211
212
  return /* @__PURE__ */ React.createElement(Results, _objectSpread2(_objectSpread2({}, props), {}, {
212
213
  title: recentConversationsTitle,
213
214
  collection: recentConversations,
214
- renderIcon: () => /* @__PURE__ */ React.createElement("div", { className: "DocSearch-Hit-icon DocSearch-Hit-icon--small" }, /* @__PURE__ */ React.createElement(MessageIcon, null)),
215
+ renderIcon: () => /* @__PURE__ */ React.createElement("div", { className: "DocSearch-Hit-icon DocSearch-Hit-icon--start" }, /* @__PURE__ */ React.createElement(MessageIcon, null)),
215
216
  renderAction: ({ item }) => /* @__PURE__ */ React.createElement("div", { className: "DocSearch-Hit-action" }, /* @__PURE__ */ React.createElement("button", {
216
217
  className: "DocSearch-Hit-action-button",
217
218
  title: removeRecentConversationButtonTitle,
@@ -301,15 +302,18 @@ const AskAiScreenState = React.memo((_ref) => {
301
302
  onSelectPromptSuggestion: handleSelectPromptSuggestion
302
303
  }));
303
304
  if (((_props$state = props.state) === null || _props$state === void 0 ? void 0 : _props$state.status) === "error") return /* @__PURE__ */ React.createElement(ErrorScreen, { translations: translations === null || translations === void 0 ? void 0 : translations.errorScreen });
304
- if (!props.state.query) return /* @__PURE__ */ React.createElement(AskAiStartScreen, _objectSpread2(_objectSpread2({}, props), {}, {
305
+ if (isQueryEmpty(props.state.query)) return /* @__PURE__ */ React.createElement(AskAiStartScreen, _objectSpread2(_objectSpread2({}, props), {}, {
305
306
  hasCollections: props.hasCollections,
306
307
  translations: translations === null || translations === void 0 ? void 0 : translations.startScreen,
307
308
  selectAskAiQuestion
308
309
  }));
309
310
  if (!props.hasCollections && !props.canHandleAskAi) return /* @__PURE__ */ React.createElement(NoResultsScreen, _objectSpread2(_objectSpread2({}, props), {}, { translations: translations === null || translations === void 0 ? void 0 : translations.noResultsScreen }));
310
311
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ResultsScreen, _objectSpread2(_objectSpread2({}, props), {}, { translations: translations === null || translations === void 0 ? void 0 : translations.resultsScreen })), props.canHandleAskAi && !props.hasCollections && /* @__PURE__ */ React.createElement(NoResultsScreen, _objectSpread2(_objectSpread2({}, props), {}, { translations: translations === null || translations === void 0 ? void 0 : translations.noResultsScreen })));
311
- }, function areEqual(_prevProps, nextProps) {
312
- return nextProps.state.status === "loading" || nextProps.state.status === "stalled";
312
+ }, function areEqual(prevProps, nextProps) {
313
+ if (prevProps.isAskAiActive !== nextProps.isAskAiActive || prevProps.askAiState !== nextProps.askAiState || prevProps.canHandleAskAi !== nextProps.canHandleAskAi) return false;
314
+ const isLoading = nextProps.state.status === "loading" || nextProps.state.status === "stalled";
315
+ const isWaitingForCollections = nextProps.state.status === "idle" && !isQueryEmpty(nextProps.state.query) && prevProps.state.query !== nextProps.state.query && prevProps.state.collections === nextProps.state.collections;
316
+ return isLoading || isWaitingForCollections;
313
317
  });
314
318
 
315
319
  //#endregion
@@ -370,7 +374,7 @@ function AskAiSearchBox(_ref) {
370
374
  onKeyDown: (e) => {
371
375
  let askAiHandled = false;
372
376
  if (props.isAskAiActive && blockedKeys.has(e.key)) {
373
- if (e.key === "Enter" && !isAskAiStreaming && props.state.query) props.onAskAgain(props.state.query);
377
+ if (e.key === "Enter" && !isAskAiStreaming && !isQueryEmpty(props.state.query)) props.onAskAgain(props.state.query);
374
378
  askAiHandled = true;
375
379
  }
376
380
  if (askAiHandled) {
@@ -578,10 +582,9 @@ const _excluded = [
578
582
  "recentSearchesLimit",
579
583
  "recentSearchesWithFavoritesLimit",
580
584
  "indices",
581
- "indexName",
582
- "searchParameters",
583
585
  "facets",
584
- "isHybridModeSupported"
586
+ "isHybridModeSupported",
587
+ "footerAction"
585
588
  ];
586
589
  const _excluded2 = [
587
590
  "footer",
@@ -590,7 +593,7 @@ const _excluded2 = [
590
593
  ];
591
594
  function DocSearchAskAiModal(_ref) {
592
595
  var _translations$searchB, _askAiConfig$memory$e, _askAiConfig$memory, _askAiConfig$tools;
593
- let { appId, apiKey, askAi, maxResultsPerGroup, theme, onClose = noop, transformItems = identity, hitComponent = Hit, resultsFooterComponent = () => null, navigator, initialScrollY = 0, transformSearchClient = identity, disableUserPersonalization = false, initialQuery: initialQueryFromProp = "", translations = {}, getMissingResultsUrl, insights = false, onAskAiToggle, interceptAskAiEvent, isAskAiActive = false, recentSearchesLimit = 7, recentSearchesWithFavoritesLimit = 4, indices = [], indexName, searchParameters, facets, isHybridModeSupported = false } = _ref, props = _objectWithoutProperties(_ref, _excluded);
596
+ let { appId, apiKey, askAi, maxResultsPerGroup, theme, onClose = noop, transformItems = identity, hitComponent = Hit, resultsFooterComponent = () => null, navigator, initialScrollY = 0, transformSearchClient = identity, disableUserPersonalization = false, initialQuery: initialQueryFromProp = "", translations = {}, getMissingResultsUrl, insights = false, onAskAiToggle, interceptAskAiEvent, isAskAiActive = false, recentSearchesLimit = 7, recentSearchesWithFavoritesLimit = 4, indices, facets, isHybridModeSupported = false, footerAction } = _ref, props = _objectWithoutProperties(_ref, _excluded);
594
597
  const { footer: footerTranslations, searchBox: searchBoxTranslations, facets: facetBarTranslations } = translations, screenStateTranslations = _objectWithoutProperties(translations, _excluded2);
595
598
  const [state, setState] = React.useState({
596
599
  query: "",
@@ -611,29 +614,21 @@ function DocSearchAskAiModal(_ref) {
611
614
  var _translations$searchB3;
612
615
  placeholder = (translations === null || translations === void 0 || (_translations$searchB3 = translations.searchBox) === null || _translations$searchB3 === void 0 ? void 0 : _translations$searchB3.placeholderTextAskAi) || "Ask another question...";
613
616
  }
614
- const { containerRef, modalRef, formElementRef, dropdownRef, inputRef, snippetLength } = useModalRefs();
617
+ const { containerRef, modalRef, formElementRef, dropdownRef, inputRef } = useModalRefs();
615
618
  const { initialQuery, initialQueryFromSelection } = useInitialModalQuery(initialQueryFromProp);
616
619
  const searchClient = useSearchClient(appId, apiKey, transformSearchClient);
617
620
  const askAiConfig = typeof askAi === "object" ? askAi : null;
618
- const askAiConfigurationId = askAiConfig ? askAiConfig.assistantId : askAi;
621
+ const askAiConfigurationId = askAiConfig ? askAiConfig.agentId : askAi;
619
622
  const askAiSearchParameters = askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.searchParameters;
620
623
  const [askAiState, setAskAiState] = React.useState("initial");
621
624
  const suggestedQuestions = useSuggestedQuestions({
622
- assistantId: askAiConfigurationId,
625
+ agentId: askAiConfigurationId,
623
626
  searchClient,
624
627
  suggestedQuestionsEnabled: askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.suggestedQuestions
625
628
  });
626
629
  const memoryEnabled = (_askAiConfig$memory$e = askAiConfig === null || askAiConfig === void 0 || (_askAiConfig$memory = askAiConfig.memory) === null || _askAiConfig$memory === void 0 ? void 0 : _askAiConfig$memory.enabled) !== null && _askAiConfig$memory$e !== void 0 ? _askAiConfig$memory$e : false;
627
630
  const tools = (_askAiConfig$tools = askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.tools) !== null && _askAiConfig$tools !== void 0 ? _askAiConfig$tools : EMPTY_TOOLS;
628
- const indexes = React.useMemo(() => normalizeDocSearchIndexes({
629
- indexName,
630
- indices,
631
- searchParameters
632
- }), [
633
- indexName,
634
- indices,
635
- searchParameters
636
- ]);
631
+ const indexes = React.useMemo(() => normalizeDocSearchIndexes({ indices }), [indices]);
637
632
  const defaultIndexName = indexes[0].name;
638
633
  const autocompleteRef = React.useRef(void 0);
639
634
  const { visibleFacets, facetSelections, facetSelectionsRef, handleFacetSelectionChange, clearFacetSelections } = useDocSearchFacets({
@@ -652,10 +647,9 @@ function DocSearchAskAiModal(_ref) {
652
647
  });
653
648
  const [stoppedStream, setStoppedStream] = React.useState(false);
654
649
  const { chatId, messages, status, setMessages, sendMessage, stopAskAiStreaming, askAiError, sendFeedback, conversations, startNewConversation, restoreConversation } = useAskAi({
655
- assistantId: askAiConfigurationId,
650
+ agentId: askAiConfigurationId,
656
651
  apiKey: (askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.apiKey) || apiKey,
657
652
  appId: (askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.appId) || appId,
658
- indexName: (askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.indexName) || defaultIndexName,
659
653
  searchParameters: askAiSearchParameters,
660
654
  tools,
661
655
  memory: askAiConfig === null || askAiConfig === void 0 ? void 0 : askAiConfig.memory,
@@ -752,7 +746,7 @@ function DocSearchAskAiModal(_ref) {
752
746
  setState(changes.state);
753
747
  },
754
748
  async getSources({ query, state: sourcesState, setContext, setStatus }) {
755
- if (!query) {
749
+ if (isQueryEmpty(query)) {
756
750
  const noQuerySources = buildNoQuerySources({
757
751
  recentSearches,
758
752
  favoriteSearches,
@@ -774,7 +768,6 @@ function DocSearchAskAiModal(_ref) {
774
768
  setStatus,
775
769
  searchClient,
776
770
  indexes,
777
- snippetLength,
778
771
  insights: Boolean(insights),
779
772
  appId,
780
773
  apiKey,
@@ -804,7 +797,6 @@ function DocSearchAskAiModal(_ref) {
804
797
  inputRef,
805
798
  initialScrollY,
806
799
  modalRef,
807
- snippetLength,
808
800
  theme
809
801
  });
810
802
  React.useEffect(() => {
@@ -850,7 +842,7 @@ function DocSearchAskAiModal(_ref) {
850
842
  };
851
843
  let showDocsearchDropdown = true;
852
844
  const hasCollections = state.collections.some((collection) => collection.source.sourceId !== SOURCE_IDS.askAI && collection.items.length > 0);
853
- if (state.status === "idle" && hasCollections === false && state.query.length === 0 && !isAskAiActive) showDocsearchDropdown = false;
845
+ if (state.status === "idle" && hasCollections === false && isQueryEmpty(state.query) && !isAskAiActive) showDocsearchDropdown = false;
854
846
  return /* @__PURE__ */ React.createElement(ModalShell, {
855
847
  state,
856
848
  containerRef,
@@ -862,7 +854,7 @@ function DocSearchAskAiModal(_ref) {
862
854
  searchBox: /* @__PURE__ */ React.createElement(AskAiSearchBox, _objectSpread2(_objectSpread2({}, autocomplete), {}, {
863
855
  state,
864
856
  placeholder: placeholder || "Search docs",
865
- autoFocus: initialQuery.length === 0,
857
+ autoFocus: isQueryEmpty(initialQuery),
866
858
  inputRef,
867
859
  isFromSelection: Boolean(initialQuery) && initialQuery === initialQueryFromSelection,
868
860
  translations: searchBoxTranslations,
@@ -881,7 +873,7 @@ function DocSearchAskAiModal(_ref) {
881
873
  onNewConversation: handleNewConversation,
882
874
  onViewConversationHistory: handleViewConversationHistory
883
875
  })),
884
- filterBar: !isAskAiActive && state.query !== "" ? /* @__PURE__ */ React.createElement(FacetBar, {
876
+ filterBar: !isAskAiActive && !isQueryEmpty(state.query) ? /* @__PURE__ */ React.createElement(FacetBar, {
885
877
  facets: visibleFacets,
886
878
  selections: facetSelections,
887
879
  translations: facetBarTranslations,
@@ -943,7 +935,8 @@ function DocSearchAskAiModal(_ref) {
943
935
  })),
944
936
  footer: /* @__PURE__ */ React.createElement(Footer, {
945
937
  translations: footerTranslations,
946
- isAskAiActive
938
+ isAskAiActive,
939
+ footerAction
947
940
  }),
948
941
  onClose
949
942
  });
@@ -951,4 +944,4 @@ function DocSearchAskAiModal(_ref) {
951
944
 
952
945
  //#endregion
953
946
  export { DocSearchAskAiModal as t };
954
- //# sourceMappingURL=DocSearchAskAiModal-KaA6fBV4.js.map
947
+ //# sourceMappingURL=DocSearchAskAiModal-C_sH1j8Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocSearchAskAiModal-C_sH1j8Y.js","names":[],"sources":["../../src/icons/MessageIcon.tsx","../../src/AggregatedSearchBlock.tsx","../../src/AskAiScreen.tsx","../../src/components/ui/RecentConversationsResults.tsx","../../src/components/AskAiStartScreen.tsx","../../src/ConversationHistoryScreen.tsx","../../src/NewConversationScreen.tsx","../../src/AskAiScreenState.tsx","../../src/ModalHeading.tsx","../../src/components/AskAiSearchBox.tsx","../../src/utils/createAskAiSources.ts","../../src/DocSearchAskAiModal.tsx"],"sourcesContent":["import React, { type JSX } from 'react';\n\nexport function MessageIcon(): JSX.Element {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n","import React, { type JSX, Fragment } from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { SearchIcon } from './icons';\n\ninterface AggregatedSearchBlockProps {\n queries: string[];\n translations: AskAiScreenTranslations;\n onSearchQueryClick: (query: string) => void;\n}\n\n// allow translators to return either simple string parts or a fully custom node\nexport interface AggregatedToolCallParts {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n}\n\n// default english implementation (\"Searched for \\\"A\\\", \\\"B\\\" and \\\"C\\\"\")\nconst defaultAggregatedToolCallParts: AggregatedToolCallParts = {\n before: 'Searched for ',\n separator: ', ',\n lastSeparator: ' and ',\n after: '',\n};\n\nexport function AggregatedSearchBlock({\n queries,\n translations,\n onSearchQueryClick,\n}: AggregatedSearchBlockProps): JSX.Element | null {\n // no queries? no render\n if (queries.length === 0) return null;\n\n // if the translator provides a fully custom node, render it and bail out.\n if (typeof translations.aggregatedToolCallNode === 'function') {\n return (\n <>{translations.aggregatedToolCallNode(queries, onSearchQueryClick)}</>\n );\n }\n\n // otherwise fall back to the classic english-pattern renderer.\n const parts = translations.aggregatedToolCallText\n ? translations.aggregatedToolCallText(queries)\n : defaultAggregatedToolCallParts;\n\n const {\n before = '',\n separator = ', ',\n lastSeparator = ' and ',\n after = '',\n } = parts || {};\n\n return (\n <div className=\"DocSearch-AskAiScreen-MessageContent-Tool Tool--AggregatedResult\">\n <SearchIcon size={18} />\n <span>\n {before && <span>{before}</span>}\n {queries.map((q, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={q + idx}>\n <span\n role=\"button\"\n tabIndex={0}\n className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSearchQueryClick(q);\n }\n }}\n onClick={() => onSearchQueryClick(q)}\n >\n &quot;{q}&quot;\n </span>\n {idx < queries.length - 2 && separator}\n {idx === queries.length - 2 && lastSeparator}\n </Fragment>\n ))}\n {after && <span>{after}</span>}\n </span>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport React, { type JSX, useMemo } from 'react';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { ConversationPromptSuggestions } from './components/ConversationPromptSuggestions';\nimport { FeedbackActions } from './components/FeedbackActions';\nimport { SourcesPanel } from './components/SourcesPanel';\nimport { ToolCall, type ToolCallTranslations } from './components/ToolCall';\nimport { AlertIcon, LoadingIcon, SparklesIcon } from './icons';\nimport { MemoizedMarkdown } from './MemoizedMarkdown';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n} from './types';\nimport { type AIMessage, type ToolCalls } from './types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n isThreadDepthError,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from './utils/ai';\nimport { groupConsecutiveToolResults } from './utils/groupConsecutiveToolResults';\n\nexport type AskAiScreenTranslations = Partial<\n // Inherit the shared tool-call translations, but expose the search-related\n // keys under AskAiScreen's own public names (see mapping below).\n Omit<ToolCallTranslations, 'searchingText' | 'toolCallResultText'> & {\n // Misc texts\n disclaimerText: string;\n /** Text shown describing a singular related source. */\n relatedSourcesText: string;\n /** Text shown describing multiple related sources. */\n relatedSourcesTextPlural: string;\n thinkingText: string;\n copyButtonText: string;\n copyButtonCopiedText: string;\n // Feedback buttons\n copyButtonTitle: string;\n likeButtonTitle: string;\n dislikeButtonTitle: string;\n thanksForFeedbackText: string;\n // Negative feedback note panel\n feedbackPanelTitle: string;\n feedbackDetailsPlaceholder: string;\n feedbackDisclaimerText: string;\n feedbackSubmitButtonText: string;\n feedbackCloseButtonTitle: string;\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n // Tool call texts\n /**\n * Text shown while assistant is performing search tool call. Maps to\n * `ToolCallTranslations.searchingText`.\n */\n duringToolCallText: string;\n /**\n * Text shown while assistant is finished performing tool call. Maps to\n * `ToolCallTranslations.toolCallResultText`.\n */\n afterToolCallText: string;\n /**\n * Build the full jsx element for the aggregated search block. If provided,\n * completely overrides the default english renderer.\n */\n aggregatedToolCallNode?: (\n queries: string[],\n onSearchQueryClick: (query: string) => void\n ) => React.ReactNode;\n /**\n * Generate the list connective parts only (backwards compatibility).\n * Receives full list of queries and should return translation parts for\n * before/after/separators. Example: (qs) => ({ before: 'searched for ',\n * separator: ', ', lastSeparator: ' and ', after: '' }).\n */\n aggregatedToolCallText?: (queries: string[]) => {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n };\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText: string;\n /** Message shown when thread depth limit is exceeded (AI-217 error). */\n threadDepthExceededMessage: string;\n /** Button text for starting a new conversation after thread depth error. */\n startNewConversationButtonText: string;\n suggestedPromptsTitleText: string;\n }\n>;\n\n/**\n * Maps AskAiScreen's public translation keys to the shared\n * `ToolCallTranslations` shape consumed by the `ToolCall` component, applying\n * default English values.\n */\nfunction toToolCallTranslations(\n translations: AskAiScreenTranslations\n): ToolCallTranslations {\n const {\n preToolCallText = 'Searching...',\n duringToolCallText = 'Searching...',\n afterToolCallText = 'Searched for',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n } = translations;\n\n return {\n preToolCallText,\n searchingText: duringToolCallText,\n toolCallResultText: afterToolCallText,\n savedMemoryToolResultText,\n memoryToolResultText,\n };\n}\n\ntype AskAiScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n messages: AIMessage[];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n translations?: AskAiScreenTranslations;\n onNewConversation: () => void;\n onSelectPromptSuggestion: (prompt: string) => void;\n memoryEnabled?: boolean;\n};\n\ninterface AskAiScreenHeaderProps {\n disclaimerText: string;\n}\n\nexport interface Exchange {\n id: string;\n userMessage: AIMessage;\n assistantMessage: AIMessage | null;\n}\n\nfunction AskAiScreenDisclaimer({\n disclaimerText,\n}: AskAiScreenHeaderProps): JSX.Element {\n return (\n <p className=\"DocSearch-AskAiScreen-Disclaimer\">\n <SparklesIcon /> {disclaimerText}\n </p>\n );\n}\n\ninterface AskAiExchangeCardProps {\n exchange: Exchange;\n askAiError?: Error;\n isLastExchange: boolean;\n loadingStatus: UseChatHelpers<AIMessage>['status'];\n onSearchQueryClick: (query: string) => void;\n translations: AskAiScreenTranslations;\n tools: ToolCalls;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onFeedback?: OnAskAiFeedback;\n memoryEnabled?: boolean;\n onSelectPromptSuggestion: (prompt: string) => void;\n}\n\nfunction AskAiExchangeCard({\n exchange,\n askAiError,\n isLastExchange,\n loadingStatus,\n onSearchQueryClick,\n translations,\n tools,\n conversations,\n onFeedback,\n memoryEnabled,\n onSelectPromptSuggestion,\n}: AskAiExchangeCardProps): JSX.Element {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n stoppedStreamingText = 'You stopped this response',\n errorTitleText = 'Chat error',\n relatedSourcesText,\n relatedSourcesTextPlural,\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const toolCallTranslations = useMemo(\n () => toToolCallTranslations(translations),\n [translations]\n );\n\n const isThreadDepth = isThreadDepthError(askAiError);\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n\n const displayParts = React.useMemo(() => {\n return groupConsecutiveToolResults(assistantMessage?.parts || []);\n }, [assistantMessage]);\n\n const promptSuggestions = useMemo(() => {\n if (!isLastExchange) return [];\n return getAgentPromptSuggestions(assistantMessage?.parts || []);\n }, [assistantMessage, isLastExchange]);\n\n const wasStopped =\n userMessage.metadata?.stopped || assistantMessage?.metadata?.stopped;\n\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange &&\n loadingStatus === 'ready' &&\n Boolean(assistantMessage)));\n\n const isThinking =\n ['submitted', 'streaming'].includes(loadingStatus) &&\n isLastExchange &&\n !displayParts.some((part) => part.type !== 'step-start');\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div className=\"DocSearch-AskAiScreen-Response-Container\">\n <div className=\"DocSearch-AskAiScreen-Response\">\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user\">\n <p className=\"DocSearch-AskAiScreen-Query\">{userContent ?? ''}</p>\n </div>\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant\">\n <div className=\"DocSearch-AskAiScreen-MessageContent\">\n {loadingStatus === 'error' &&\n askAiError &&\n isLastExchange &&\n !isThreadDepth && (\n <div className=\"DocSearch-AskAiScreen-Error\" role=\"alert\">\n <AlertIcon aria-hidden=\"true\" />\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <h4 className=\"DocSearch-AskAiScreen-Error-Title\">\n {errorTitleText}\n </h4>\n <MemoizedMarkdown\n content={askAiError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n {isThinking && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"DocSearch-shimmer\">\n {translations.thinkingText || 'Thinking...'}\n </span>\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-shimmer\" />\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short DocSearch-shimmer\" />\n </div>\n )}\n {displayParts.map((part, idx) => {\n const index = idx;\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={loadingStatus === 'streaming'}\n />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n translations={toolCallTranslations}\n part={part}\n tools={tools}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock\n key={index}\n queries={part.queries}\n translations={translations}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'reasoning' && part.state === 'streaming') {\n return (\n <div\n key={index}\n className=\"DocSearch-AskAiScreen-MessageContent-Reasoning DocSearch-shimmer\"\n >\n <LoadingIcon className=\"DocSearch-AskAiScreen-SmallerLoadingIcon\" />\n <span className=\"DocSearch-shimmer\">Reasoning...</span>\n </div>\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n // fallback for unknown part type\n return null;\n })}\n </div>\n\n {wasStopped && (\n <p className=\"DocSearch-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n pluralTitleText={relatedSourcesTextPlural}\n />\n <FeedbackActions\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {promptSuggestions.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={promptSuggestions}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n}\n\nexport function AskAiScreen({\n translations = {},\n ...props\n}: AskAiScreenProps): JSX.Element | null {\n const {\n disclaimerText = 'Answers are generated with AI which can make mistakes.',\n threadDepthExceededMessage = 'This conversation is now closed to keep responses accurate.',\n startNewConversationButtonText = 'Start a new conversation',\n } = translations;\n\n const { messages, tools, askAiError, status, memoryEnabled } = props;\n\n // Check if there's a thread depth error\n const hasThreadDepthError = useMemo(() => {\n return status === 'error' && isThreadDepthError(askAiError);\n }, [status, askAiError]);\n\n // Group messages into exchanges (user + assistant pairs)\n const exchanges: Exchange[] = useMemo(() => {\n const grouped: Exchange[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n const userMessage = messages[i];\n const assistantMessage =\n messages[i + 1]?.role === 'assistant' ? messages[i + 1] : null;\n grouped.push({ id: userMessage.id, userMessage, assistantMessage });\n if (assistantMessage) {\n i++;\n }\n }\n }\n\n // If there's a thread depth error, remove the last exchange (the one that triggered the error)\n // We only want to show successful exchanges\n if (hasThreadDepthError && grouped.length > 0) {\n // Check if the last exchange has no assistant message (failed to complete)\n const lastExchange = grouped[grouped.length - 1];\n if (!lastExchange.assistantMessage) {\n grouped.pop();\n }\n }\n\n return grouped;\n }, [messages, hasThreadDepthError]);\n\n const handleSearchQueryClick = (query: string): void => {\n props.onAskAiToggle(false);\n props.setQuery(query);\n };\n\n // Only show the thread depth error if we have assistant messages\n const showThreadDepthError =\n hasThreadDepthError && messages.some((m) => m.role === 'assistant');\n\n return (\n <div className=\"DocSearch-AskAiScreen DocSearch-AskAiScreen-Container\">\n {/* Thread Depth Error */}\n {showThreadDepthError && (\n <div className=\"DocSearch-AskAiScreen-MessageContent DocSearch-AskAiScreen-Error DocSearch-AskAiScreen-Error--ThreadDepth\">\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <p>\n {threadDepthExceededMessage}{' '}\n <button\n type=\"button\"\n className=\"DocSearch-ThreadDepthError-Link\"\n onClick={props.onNewConversation}\n >\n {startNewConversationButtonText}\n </button>{' '}\n to continue.\n </p>\n </div>\n </div>\n )}\n\n <AskAiScreenDisclaimer disclaimerText={disclaimerText} />\n\n <div className=\"DocSearch-AskAiScreen-Body\">\n <div className=\"DocSearch-AskAiScreen-ExchangesList\">\n {exchanges\n .slice()\n .reverse()\n .map((exchange, index) => (\n <AskAiExchangeCard\n key={exchange.id}\n exchange={exchange}\n askAiError={props.askAiError}\n isLastExchange={index === 0}\n loadingStatus={props.status}\n translations={translations}\n tools={tools}\n conversations={props.conversations}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={handleSearchQueryClick}\n onFeedback={props.onFeedback}\n onSelectPromptSuggestion={props.onSelectPromptSuggestion}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../../AskAiScreenState';\nimport { CloseIcon, MessageIcon } from '../../icons';\nimport { Results } from '../../Results';\nimport type { InternalDocSearchHit } from '../../types';\nimport { getCollection } from '../../utils';\n\nexport type RecentConversationsResultsTranslations = Partial<{\n recentConversationsTitle: string;\n removeRecentConversationButtonTitle: string;\n}>;\n\ntype RecentConversationsResultsProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: RecentConversationsResultsTranslations;\n};\n\nexport function RecentConversationsResults({\n translations = {},\n ...props\n}: RecentConversationsResultsProps): JSX.Element | null {\n const {\n recentConversationsTitle = 'Resume AI conversations',\n removeRecentConversationButtonTitle = 'Remove this conversation from history',\n } = translations;\n const recentConversations = getCollection(props.state, 'recentConversations');\n\n if (!recentConversations) {\n return null;\n }\n\n return (\n <Results\n {...props}\n title={recentConversationsTitle}\n collection={recentConversations}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon DocSearch-Hit-icon--start\">\n <MessageIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n title={removeRecentConversationButtonTitle}\n type=\"submit\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../AskAiScreenState';\nimport type { InternalDocSearchHit } from '../types';\n\nimport type { RecentConversationsResultsTranslations } from './ui/RecentConversationsResults';\nimport { RecentConversationsResults } from './ui/RecentConversationsResults';\nimport type { StoredSearchesSectionsTranslations } from './ui/StoredSearchesSections';\nimport { StoredSearchesSections } from './ui/StoredSearchesSections';\n\nexport type AskAiStartScreenTranslations =\n RecentConversationsResultsTranslations & StoredSearchesSectionsTranslations;\n\ntype AskAiStartScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n hasCollections: boolean;\n translations?: AskAiStartScreenTranslations;\n};\n\nexport function AskAiStartScreen({\n translations = {},\n ...props\n}: AskAiStartScreenProps): JSX.Element | null {\n return (\n <div className=\"DocSearch-Dropdown-Container\">\n <RecentConversationsResults {...props} translations={translations} />\n <StoredSearchesSections {...props} translations={translations} />\n </div>\n );\n}\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { CloseIcon, SparklesIcon } from './icons';\nimport { Results } from './Results';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport type { InternalDocSearchHit } from './types';\nimport { getCollection } from './utils';\n\ntype ConversationHistoryScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: ResultsScreenTranslations;\n};\n\nexport function ConversationHistoryScreen({\n onAskAiToggle,\n ...props\n}: ConversationHistoryScreenProps): JSX.Element | null {\n const collection = React.useMemo(\n () => getCollection(props.state, 'recentConversations'),\n [props.state]\n );\n\n React.useEffect(() => {\n if (!collection || collection.items.length === 0) {\n onAskAiToggle(true);\n }\n }, [collection, onAskAiToggle]);\n\n if (!collection) {\n return null;\n }\n\n return (\n <div className=\"DocSearch-Dropdown-Container DocSearch-Conversation-History\">\n <Results\n {...props}\n key={collection.source.sourceId}\n title=\"\"\n translations={props.translations}\n collection={collection}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon\">\n <SparklesIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n type=\"button\"\n className=\"DocSearch-Hit-action-button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { SuggestedQuestionHit } from './types';\n\nexport type NewConversationTranslations = Partial<{\n newConversationTitle: string;\n newConversationDescription: string;\n}>;\n\ninterface NewConversationProps {\n suggestedQuestions?: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationTranslations;\n}\n\nexport function NewConversationScreen({\n translations = {},\n suggestedQuestions = [],\n selectSuggestedQuestion,\n}: NewConversationProps): JSX.Element {\n const {\n newConversationTitle = 'How can I help you today?',\n newConversationDescription = 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.',\n } = translations;\n\n return (\n <div className=\"DocSearch-NewConversationScreen\">\n <h3 className=\"DocSearch-NewConversationScreen-Title\">\n {newConversationTitle}\n </h3>\n <p className=\"DocSearch-NewConversationScreen-Description\">\n {newConversationDescription}\n </p>\n\n <div className=\"DocSearch-NewConversationScreen-SuggestedQuestions\">\n {suggestedQuestions.map((question) => (\n <button\n key={question.objectID}\n type=\"button\"\n className=\"DocSearch-NewConversationScreen-SuggestedQuestion\"\n onClick={() => selectSuggestedQuestion(question)}\n >\n {question.question}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n BaseItem,\n} from '@algolia/autocomplete-core';\nimport type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { AskAiScreen } from './AskAiScreen';\nimport type { AskAiStartScreenTranslations } from './components/AskAiStartScreen';\nimport { AskAiStartScreen } from './components/AskAiStartScreen';\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { DocSearchProps } from './DocSearch';\nimport type { ErrorScreenTranslations } from './ErrorScreen';\nimport { ErrorScreen } from './ErrorScreen';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport type { NoResultsScreenTranslations } from './NoResultsScreen';\nimport { NoResultsScreen } from './NoResultsScreen';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport { ResultsScreen } from './ResultsScreen';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n StoredDocSearchHit,\n SuggestedQuestionHit,\n} from './types';\nimport type { AIMessage, AskAiState, ToolCalls } from './types/AskiAi';\nimport { isQueryEmpty } from './utils';\n\nexport type AskAiScreenStateTranslations = Partial<{\n errorScreen: ErrorScreenTranslations;\n startScreen: AskAiStartScreenTranslations;\n noResultsScreen: NoResultsScreenTranslations;\n resultsScreen: ResultsScreenTranslations;\n askAiScreen: AskAiScreenTranslations;\n newConversation: NewConversationTranslations;\n}>;\n\nexport interface AskAiScreenStateProps<\n TItem extends BaseItem,\n> extends AutocompleteApi<\n TItem,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<TItem>;\n recentSearches: StoredSearchPlugin<StoredDocSearchHit>;\n favoriteSearches: StoredSearchPlugin<StoredDocSearchHit>;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onItemClick: (\n item: InternalDocSearchHit,\n event: KeyboardEvent | MouseEvent\n ) => void;\n onAskAiToggle: (toggle: boolean) => void;\n isAskAiActive: boolean;\n canHandleAskAi: boolean;\n inputRef: React.MutableRefObject<HTMLInputElement | null>;\n hitComponent: DocSearchProps['hitComponent'];\n indexName: string;\n messages: UseChatHelpers<AIMessage>['messages'];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n disableUserPersonalization: boolean;\n resultsFooterComponent: DocSearchProps['resultsFooterComponent'];\n translations: AskAiScreenStateTranslations;\n getMissingResultsUrl?: DocSearchProps['getMissingResultsUrl'];\n hasCollections: boolean;\n onFeedback?: OnAskAiFeedback;\n askAiState: AskAiState;\n selectAskAiQuestion: (toggle: boolean, query: string) => void;\n suggestedQuestions: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n onNewConversation: () => void;\n memoryEnabled?: boolean;\n resultBadgeKey?: string;\n}\n\nexport const AskAiScreenState = React.memo(\n ({\n translations = {},\n selectAskAiQuestion,\n ...props\n }: AskAiScreenStateProps<InternalDocSearchHit>): JSX.Element => {\n const handleSelectPromptSuggestion = React.useCallback(\n (prompt: string) => {\n selectAskAiQuestion(true, prompt);\n },\n [selectAskAiQuestion]\n );\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'conversation-history'\n ) {\n return (\n <ConversationHistoryScreen\n selectAskAiQuestion={selectAskAiQuestion}\n {...props}\n />\n );\n }\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'new-conversation'\n ) {\n return (\n <NewConversationScreen\n translations={translations?.newConversation}\n selectSuggestedQuestion={props.selectSuggestedQuestion}\n suggestedQuestions={props.suggestedQuestions}\n />\n );\n }\n\n if (props.isAskAiActive && props.canHandleAskAi) {\n return (\n <AskAiScreen\n {...props}\n messages={props.messages}\n tools={props.tools}\n status={props.status}\n askAiError={props.askAiError}\n translations={translations?.askAiScreen}\n memoryEnabled={props.memoryEnabled}\n selectAskAiQuestion={selectAskAiQuestion}\n onSelectPromptSuggestion={handleSelectPromptSuggestion}\n />\n );\n }\n\n if (props.state?.status === 'error') {\n return <ErrorScreen translations={translations?.errorScreen} />;\n }\n\n if (isQueryEmpty(props.state.query)) {\n return (\n <AskAiStartScreen\n {...props}\n hasCollections={props.hasCollections}\n translations={translations?.startScreen}\n selectAskAiQuestion={selectAskAiQuestion}\n />\n );\n }\n\n if (!props.hasCollections && !props.canHandleAskAi) {\n return (\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n );\n }\n\n return (\n <>\n <ResultsScreen {...props} translations={translations?.resultsScreen} />\n {props.canHandleAskAi &&\n !props.hasCollections && (\n // if there's one collection it is the ask ai action, show the no results screen\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n )}\n </>\n );\n },\n function areEqual(prevProps, nextProps) {\n const askAiStateChanged =\n prevProps.isAskAiActive !== nextProps.isAskAiActive ||\n prevProps.askAiState !== nextProps.askAiState ||\n prevProps.canHandleAskAi !== nextProps.canHandleAskAi;\n\n // Something triggered an Ask AI related state change, perform a new render\n if (askAiStateChanged) {\n return false;\n }\n\n const isLoading =\n nextProps.state.status === 'loading' ||\n nextProps.state.status === 'stalled';\n\n const isWaitingForCollections =\n nextProps.state.status === 'idle' &&\n !isQueryEmpty(nextProps.state.query) &&\n prevProps.state.query !== nextProps.state.query &&\n prevProps.state.collections === nextProps.state.collections;\n\n return isLoading || isWaitingForCollections;\n }\n);\n","import React from 'react';\nimport type { JSX } from 'react';\n\ntype ModalHeadingProps = {\n heading: string;\n shimmer?: boolean;\n};\n\nexport function ModalHeading({\n heading,\n shimmer = false,\n}: ModalHeadingProps): JSX.Element {\n return (\n <span\n className={`DocSearch-Modal-heading${shimmer ? ' DocSearch-shimmer' : ''}`}\n >\n {heading}\n </span>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n} from '@algolia/autocomplete-core';\nimport React, { type JSX, type RefObject } from 'react';\n\nimport {\n ConversationHistoryIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n StopIcon,\n BackIcon,\n} from '../icons';\nimport { Menu } from '../Menu';\nimport { ModalHeading } from '../ModalHeading';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, AskAiState } from '../types/AskiAi';\nimport { getCollection, isQueryEmpty } from '../utils';\n\nimport { SearchBoxForm } from './ui/SearchBoxForm';\n\nexport type AskAiSearchBoxTranslations = Partial<{\n clearButtonTitle: string;\n clearButtonAriaLabel: string;\n closeButtonText: string;\n closeButtonAriaLabel: string;\n placeholderText: string;\n placeholderTextAskAi: string;\n placeholderTextAskAiStreaming: string;\n enterKeyHint: string;\n enterKeyHintAskAi: string;\n searchInputLabel: string;\n backToKeywordSearchButtonText: string;\n backToKeywordSearchButtonAriaLabel: string;\n newConversationPlaceholder: string;\n conversationHistoryTitle: string;\n startNewConversationText: string;\n viewConversationHistoryText: string;\n threadDepthErrorPlaceholder: string;\n}>;\n\ninterface AskAiSearchBoxProps extends AutocompleteApi<\n InternalDocSearchHit,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<InternalDocSearchHit>;\n autoFocus: boolean;\n inputRef: RefObject<HTMLInputElement | null>;\n onClose: () => void;\n onAskAiToggle: (toggle: boolean) => void;\n onAskAgain: (query: string) => void;\n onStopAskAiStreaming: () => Promise<void>;\n placeholder: string;\n isAskAiActive: boolean;\n askAiStatus: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n isFromSelection: boolean;\n translations?: AskAiSearchBoxTranslations;\n askAiState: AskAiState;\n setAskAiState: (state: AskAiState) => void;\n onNewConversation: () => void;\n onViewConversationHistory: () => void;\n isThreadDepthError?: boolean;\n}\n\nexport function AskAiSearchBox({\n translations = {},\n askAiState,\n onAskAiToggle,\n setAskAiState,\n ...props\n}: AskAiSearchBoxProps): JSX.Element {\n const {\n clearButtonTitle = 'Clear',\n clearButtonAriaLabel = 'Clear the query',\n closeButtonText = 'Close',\n closeButtonAriaLabel = 'Close',\n searchInputLabel = 'Search',\n backToKeywordSearchButtonText = 'Back to keyword search',\n backToKeywordSearchButtonAriaLabel = 'Back to keyword search',\n placeholderTextAskAiStreaming = 'Answering...',\n newConversationPlaceholder = 'Ask a question',\n conversationHistoryTitle = 'My conversation history',\n startNewConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n threadDepthErrorPlaceholder = 'Conversation limit reached',\n } = translations;\n\n const hasRecentConversations = React.useMemo(() => {\n const askAiSource = getCollection(props.state, 'recentConversations');\n\n if (!askAiSource) {\n return false;\n }\n\n return askAiSource.items.length > 0;\n }, [props.state]);\n\n const baseInputProps = props.getInputProps({\n inputElement: props.inputRef.current!,\n autoFocus: props.autoFocus,\n });\n const blockedKeys = new Set(['ArrowUp', 'ArrowDown', 'Enter']);\n const origOnKeyDown = baseInputProps.onKeyDown;\n const origOnChange = baseInputProps.onChange;\n const isAskAiStreaming =\n props.askAiStatus === 'streaming' || props.askAiStatus === 'submitted';\n const renderMoreOptions =\n props.isAskAiActive && askAiState !== 'conversation-history';\n\n // Use the thread depth error state passed from parent\n const isThreadDepthError = props.isThreadDepthError || false;\n let searchPlaceholder = props.placeholder;\n\n if (askAiState === 'new-conversation') {\n searchPlaceholder = newConversationPlaceholder;\n }\n\n // Override placeholder when thread depth error occurs (only in Ask AI mode)\n if (isThreadDepthError && props.isAskAiActive) {\n searchPlaceholder = threadDepthErrorPlaceholder;\n }\n\n let heading: string | null = null;\n\n if (isAskAiStreaming) {\n heading = placeholderTextAskAiStreaming;\n }\n\n if (askAiState === 'conversation-history') {\n heading = conversationHistoryTitle;\n }\n\n // when returning to another status than streaming or submitted, we focus on the input\n React.useEffect(() => {\n if (\n props.askAiStatus !== 'streaming' &&\n props.askAiStatus !== 'submitted' &&\n props.inputRef.current\n ) {\n props.inputRef.current.focus();\n }\n }, [props.askAiStatus, props.inputRef]);\n\n /**\n * We need to block the default behavior of the input when Ask AI is active.\n * This is because the input is used to ask another question when the user\n * presses enter.\n *\n * Learn more on default autocomplete behavior:\n * https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/getDefaultProps.ts.\n */\n const inputProps = {\n enterKeyHint: props.isAskAiActive\n ? ('enter' as const)\n : ('search' as const),\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void => {\n let askAiHandled = false;\n // block these up, down, enter listeners when Ask AI is active\n if (props.isAskAiActive && blockedKeys.has(e.key)) {\n // enter key asks another question\n if (\n e.key === 'Enter' &&\n !isAskAiStreaming &&\n !isQueryEmpty(props.state.query)\n ) {\n props.onAskAgain(props.state.query);\n }\n\n askAiHandled = true;\n }\n\n if (askAiHandled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n origOnKeyDown?.(e);\n },\n onChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n if (props.isAskAiActive) {\n props.setQuery(e.currentTarget.value);\n // block search when Ask AI is active\n // we don't want to trigger the search when the user types\n // we already know they are asking a question\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n origOnChange?.(e);\n },\n disabled: isAskAiStreaming || (isThreadDepthError && props.isAskAiActive),\n };\n\n const handleAskAiBackClick = React.useCallback((): void => {\n // If there's a thread depth error, start a new conversation instead of exiting\n if (isThreadDepthError) {\n props.onNewConversation();\n return;\n }\n\n if (askAiState === 'conversation-history') {\n onAskAiToggle(true);\n setAskAiState('initial');\n return;\n }\n\n onAskAiToggle(false);\n }, [askAiState, isThreadDepthError, onAskAiToggle, setAskAiState, props]);\n\n const leadingElement = props.isAskAiActive ? (\n <button\n type=\"button\"\n tabIndex={0}\n className=\"DocSearch-Action DocSearch-AskAi-Return\"\n title={backToKeywordSearchButtonText}\n aria-label={backToKeywordSearchButtonAriaLabel}\n onClick={handleAskAiBackClick}\n >\n <BackIcon />\n </button>\n ) : undefined;\n const inputOverlay = heading ? (\n <ModalHeading heading={heading} shimmer={isAskAiStreaming} />\n ) : null;\n const actionsBeforeClose = (\n <>\n {!props.isAskAiActive && (\n <>\n <button\n className=\"DocSearch-Clear\"\n type=\"reset\"\n aria-label={clearButtonAriaLabel}\n hidden={!props.state.query}\n tabIndex={props.state.query ? 0 : -1}\n aria-hidden={!props.state.query ? 'true' : 'false'}\n >\n {clearButtonTitle}\n </button>\n\n {props.state.query && <div className=\"DocSearch-Divider\" />}\n </>\n )}\n\n {isAskAiStreaming && (\n <>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-StopStreaming\"\n onClick={props.onStopAskAiStreaming}\n >\n <StopIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n\n {renderMoreOptions && (\n <>\n <Menu>\n <Menu.Trigger className=\"DocSearch-Action\">\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item onClick={props.onNewConversation}>\n <NewConversationIcon />\n {startNewConversationText}\n </Menu.Item>\n {hasRecentConversations && (\n <Menu.Item onClick={props.onViewConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n </>\n );\n\n return (\n <SearchBoxForm\n {...props}\n placeholder={searchPlaceholder}\n clearButtonTitle={clearButtonTitle}\n clearButtonAriaLabel={clearButtonAriaLabel}\n closeButtonText={closeButtonText}\n closeButtonAriaLabel={closeButtonAriaLabel}\n searchInputLabel={searchInputLabel}\n leadingElement={leadingElement}\n inputOverlay={inputOverlay}\n hideInput={Boolean(heading)}\n actionsBeforeClose={actionsBeforeClose}\n inputProps={inputProps}\n />\n );\n}\n","import type { AutocompleteSource } from '@algolia/autocomplete-core';\nimport type { SearchResponse } from 'algoliasearch/lite';\n\nimport type { DocSearchTransformClient } from '../DocSearch';\nimport type { PromptSuggestions } from '../DocSearchAI';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, PromptSuggestion } from '../types/AskiAi';\n\nimport { SOURCE_IDS } from './collections';\n\nconst MAX_RECENT_CONVERSATIONS_DISPLAYED = 3;\n\nconst EMPTY_RESULT_CONTENT = {\n value: '',\n matchLevel: 'none',\n matchedWords: [],\n} satisfies InternalDocSearchHit['_highlightResult']['content'];\nconst EMPTY_HIERARCHY_HIGHLIGHT_RESULT = {\n lvl0: EMPTY_RESULT_CONTENT,\n lvl1: EMPTY_RESULT_CONTENT,\n lvl2: EMPTY_RESULT_CONTENT,\n lvl3: EMPTY_RESULT_CONTENT,\n lvl4: EMPTY_RESULT_CONTENT,\n lvl5: EMPTY_RESULT_CONTENT,\n lvl6: EMPTY_RESULT_CONTENT,\n} satisfies InternalDocSearchHit['_highlightResult']['hierarchy'];\nconst EMPTY_HIGHLIGHT_RESULT: InternalDocSearchHit['_highlightResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\nconst EMPTY_SNIPPET_RESULT: InternalDocSearchHit['_snippetResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\n\nexport function buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n}: {\n conversations: { getAll: () => unknown[] };\n disableUserPersonalization: boolean;\n setMessages: (messages: AIMessage[]) => void;\n onAskAiToggle: (toggle: boolean) => void;\n}): Array<\n AutocompleteSource<InternalDocSearchHit & { messages?: AIMessage[] }>\n> {\n return [\n {\n sourceId: SOURCE_IDS.recentConversations,\n getItems(): InternalDocSearchHit[] {\n if (disableUserPersonalization) {\n return [];\n }\n return (\n conversations.getAll() as unknown as InternalDocSearchHit[]\n ).slice(0, MAX_RECENT_CONVERSATIONS_DISPLAYED);\n },\n onSelect({ item }): void {\n if (item.messages) {\n setMessages(item.messages);\n onAskAiToggle(true);\n }\n },\n },\n ];\n}\n\nfunction createAskAiHit({\n query,\n objectID,\n lvl0,\n}: {\n query: string;\n objectID: string;\n lvl0: string;\n}): InternalDocSearchHit {\n return {\n type: 'askAI',\n query,\n url_without_anchor: '',\n objectID,\n content: null,\n url: '',\n anchor: null,\n hierarchy: {\n lvl0,\n lvl1: query,\n lvl2: null,\n lvl3: null,\n lvl4: null,\n lvl5: null,\n lvl6: null,\n },\n _highlightResult: EMPTY_HIGHLIGHT_RESULT,\n _snippetResult: EMPTY_SNIPPET_RESULT,\n __docsearch_parent: null,\n };\n}\n\nasync function getPromptSuggestions({\n query,\n indexName,\n searchClient,\n hitsPerPage = 3,\n}: {\n query: string;\n indexName: string;\n searchClient: DocSearchTransformClient;\n hitsPerPage?: number;\n}): Promise<InternalDocSearchHit[]> {\n try {\n const { results } = await searchClient.search<PromptSuggestion>({\n requests: [\n {\n query,\n indexName,\n hitsPerPage,\n attributesToRetrieve: ['prompt'],\n },\n ],\n });\n\n const res = results[0] as SearchResponse<PromptSuggestion>;\n\n return res.hits.map((hit) =>\n createAskAiHit({\n query: hit.prompt,\n objectID: hit.objectID,\n lvl0: 'Prompt Suggestions',\n })\n );\n // NOTE: Not checking the exception here and just returning empty array since this isn't the hot path\n } catch {\n return [];\n }\n}\n\nexport async function buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions,\n searchClient,\n}: {\n query: string;\n handleSelectAskAiQuestion: (toggle: boolean, query: string) => void;\n promptSuggestionsOptions?: PromptSuggestions;\n searchClient: DocSearchTransformClient;\n}): Promise<Array<AutocompleteSource<InternalDocSearchHit>>> {\n const promptSuggestions = promptSuggestionsOptions\n ? await getPromptSuggestions({\n query,\n indexName: promptSuggestionsOptions.indexName,\n hitsPerPage: promptSuggestionsOptions.hitsPerPage,\n searchClient,\n })\n : [];\n\n return [\n {\n sourceId: SOURCE_IDS.askAI,\n getItems(): InternalDocSearchHit[] {\n return [\n createAskAiHit({ query, objectID: 'ask-ai-button', lvl0: 'Ask AI' }),\n ...promptSuggestions,\n ];\n },\n onSelect({ item }): void {\n if (item.type === 'askAI' && item.query) {\n handleSelectAskAiQuestion(true, item.query);\n }\n },\n },\n ];\n}\n","import { createAutocomplete } from '@algolia/autocomplete-core';\nimport type { InitialAskAiMessage, OnAskAiToggle } from '@docsearch/core';\nimport type { ChatRequestOptions } from 'ai';\nimport React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateTranslations } from './AskAiScreenState';\nimport { AskAiScreenState } from './AskAiScreenState';\nimport type { AskAiSearchBoxTranslations } from './components/AskAiSearchBox';\nimport { AskAiSearchBox } from './components/AskAiSearchBox';\nimport type { FacetBarTranslations } from './components/FacetBar';\nimport { FacetBar } from './components/FacetBar';\nimport { ModalShell } from './components/ui/ModalShell';\nimport type { DocSearchAIProps } from './DocSearchAI';\nimport type { FooterTranslations } from './Footer';\nimport { Footer } from './Footer';\nimport { Hit } from './Hit';\nimport { useDocSearchFacets } from './hooks/useDocSearchFacets';\nimport { useSendItemClickEvent } from './hooks/useDocSearchInsights';\nimport { useInitialModalQuery } from './hooks/useInitialModalQuery';\nimport { useModalEnvironment } from './hooks/useModalEnvironment';\nimport { useModalRefs } from './hooks/useModalRefs';\nimport { useRefreshOnInitialQuery } from './hooks/useRefreshOnInitialQuery';\nimport { useSaveRecentSearch } from './hooks/useSaveRecentSearch';\nimport { useStoredDocSearches } from './hooks/useStoredDocSearches';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport type {\n DocSearchState,\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiMessage,\n StoredAskAiState,\n SuggestedQuestionHit,\n} from './types';\nimport { type AskAiState } from './types/AskiAi';\nimport { useAskAi } from './useAskAi';\nimport { useSearchClient } from './useSearchClient';\nimport { useSuggestedQuestions } from './useSuggestedQuestions';\nimport {\n identity,\n isModifierEvent,\n isQueryEmpty,\n noop,\n scrollTo as scrollToUtils,\n SOURCE_IDS,\n} from './utils';\nimport {\n buildDummyAskAiHit,\n isThreadDepthError,\n EMPTY_TOOLS,\n} from './utils/ai';\nimport {\n buildAskAiActionSources,\n buildRecentConversationSources,\n} from './utils/createAskAiSources';\nimport {\n buildNoQuerySources,\n buildQuerySources,\n type BuildQuerySourcesState,\n} from './utils/createDocSearchSources';\nimport { normalizeDocSearchIndexes } from './utils/normalizeDocSearchIndexes';\n\nexport type DocSearchAskAiModalTranslations = AskAiScreenStateTranslations &\n Partial<{\n searchBox: AskAiSearchBoxTranslations;\n newConversation: NewConversationTranslations;\n footer: FooterTranslations;\n facets: FacetBarTranslations;\n }>;\n\nexport type DocSearchAskAiModalProps = DocSearchAIProps & {\n initialScrollY: number;\n onAskAiToggle: OnAskAiToggle;\n onClose?: () => void;\n isAskAiActive?: boolean;\n translations?: DocSearchAskAiModalTranslations;\n isHybridModeSupported?: boolean;\n};\n\nexport function DocSearchAskAiModal({\n appId,\n apiKey,\n askAi,\n maxResultsPerGroup,\n theme,\n onClose = noop,\n transformItems = identity,\n hitComponent = Hit,\n resultsFooterComponent = (): JSX.Element | null => null,\n navigator,\n initialScrollY = 0,\n transformSearchClient = identity,\n disableUserPersonalization = false,\n initialQuery: initialQueryFromProp = '',\n translations = {},\n getMissingResultsUrl,\n insights = false,\n onAskAiToggle,\n interceptAskAiEvent,\n isAskAiActive = false,\n recentSearchesLimit = 7,\n recentSearchesWithFavoritesLimit = 4,\n indices,\n facets,\n isHybridModeSupported = false,\n footerAction,\n ...props\n}: DocSearchAskAiModalProps): JSX.Element {\n const {\n footer: footerTranslations,\n searchBox: searchBoxTranslations,\n facets: facetBarTranslations,\n ...screenStateTranslations\n } = translations;\n const [state, setState] = React.useState<\n DocSearchState<InternalDocSearchHit>\n >({\n query: '',\n collections: [],\n completion: null,\n context: {},\n isOpen: false,\n activeItemId: null,\n status: 'idle',\n });\n\n // check if the instance is configured to handle ask ai\n const canHandleAskAi = Boolean(askAi);\n\n let placeholder =\n translations?.searchBox?.placeholderText ||\n props.placeholder ||\n 'Search docs';\n\n if (canHandleAskAi) {\n placeholder =\n translations?.searchBox?.placeholderText ||\n 'Search docs or ask AI a question';\n }\n\n if (isAskAiActive) {\n placeholder =\n translations?.searchBox?.placeholderTextAskAi ||\n 'Ask another question...';\n }\n\n const { containerRef, modalRef, formElementRef, dropdownRef, inputRef } =\n useModalRefs();\n const { initialQuery, initialQueryFromSelection } =\n useInitialModalQuery(initialQueryFromProp);\n\n const searchClient = useSearchClient(appId, apiKey, transformSearchClient);\n\n const askAiConfig = typeof askAi === 'object' ? askAi : null;\n const askAiConfigurationId = askAiConfig\n ? askAiConfig.agentId\n : (askAi as string);\n const askAiSearchParameters = askAiConfig?.searchParameters;\n const [askAiState, setAskAiState] = React.useState<AskAiState>('initial');\n const suggestedQuestions = useSuggestedQuestions({\n agentId: askAiConfigurationId,\n searchClient,\n suggestedQuestionsEnabled: askAiConfig?.suggestedQuestions,\n });\n const memoryEnabled = askAiConfig?.memory?.enabled ?? false;\n const tools = askAiConfig?.tools ?? EMPTY_TOOLS;\n\n const indexes = React.useMemo(\n () =>\n normalizeDocSearchIndexes({\n indices,\n }),\n [indices]\n );\n const defaultIndexName = indexes[0].name;\n\n const autocompleteRef =\n React.useRef<\n ReturnType<\n typeof createAutocomplete<\n InternalDocSearchHit,\n React.FormEvent<HTMLFormElement>,\n React.MouseEvent,\n React.KeyboardEvent\n >\n >\n >(undefined);\n\n const {\n visibleFacets,\n facetSelections,\n facetSelectionsRef,\n handleFacetSelectionChange,\n clearFacetSelections,\n } = useDocSearchFacets({\n facets,\n indexes,\n searchClient,\n onSelectionsChange: () => autocompleteRef.current?.refresh(),\n });\n\n const { favoriteSearches, recentSearches } = useStoredDocSearches({\n defaultIndexName,\n recentSearchesLimit,\n recentSearchesWithFavoritesLimit,\n });\n\n const [stoppedStream, setStoppedStream] = React.useState(false);\n\n const {\n chatId,\n messages,\n status,\n setMessages,\n sendMessage,\n stopAskAiStreaming,\n askAiError,\n sendFeedback,\n conversations,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n agentId: askAiConfigurationId,\n apiKey: askAiConfig?.apiKey || apiKey,\n appId: askAiConfig?.appId || appId,\n searchParameters: askAiSearchParameters,\n tools,\n memory: askAiConfig?.memory,\n indices: askAiConfig?.indices,\n });\n\n const prevStatus = React.useRef(status);\n React.useEffect(() => {\n if (disableUserPersonalization) {\n return;\n }\n // if we just transitioned from \"streaming\" → \"ready\", persist\n if (prevStatus.current === 'streaming' && status === 'ready') {\n // if we stopped the stream, store it on the most recent message\n if (stoppedStream && messages.at(-1)) {\n messages.at(-1)!.metadata = {\n stopped: true,\n };\n }\n\n for (const part of messages[0].parts) {\n if (part.type === 'text') {\n conversations.add(buildDummyAskAiHit(part.text, messages, chatId));\n }\n }\n }\n prevStatus.current = status;\n }, [\n status,\n messages,\n conversations,\n disableUserPersonalization,\n stoppedStream,\n chatId,\n ]);\n\n // Check if there's a thread depth error (AI-217)\n const hasThreadDepthError = React.useMemo(() => {\n return (\n status === 'error' && isThreadDepthError(askAiError as Error | undefined)\n );\n }, [status, askAiError]);\n\n const saveRecentSearch = useSaveRecentSearch({\n favoriteSearches,\n recentSearches,\n disableUserPersonalization,\n });\n const sendItemClickEvent = useSendItemClickEvent(state);\n\n const handleSelectAskAiQuestion = React.useCallback(\n (\n toggle: boolean,\n query: string,\n suggestedQuestion: SuggestedQuestionHit | undefined = undefined\n ) => {\n if (toggle) {\n const initialMessage: InitialAskAiMessage = {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n // Consumer handled it. Avoid *all* default Ask AI behavior.\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n return;\n }\n }\n\n if (toggle && askAiState === 'new-conversation') {\n setAskAiState('initial');\n }\n\n onAskAiToggle(toggle, {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n });\n\n // If we're in hybrid mode, we don't need to send the message,\n // it will be handled by the Sidepanel.\n if (isHybridModeSupported) return;\n\n setStoppedStream(false);\n\n const messageOptions: ChatRequestOptions = {};\n\n if (suggestedQuestion) {\n messageOptions.body = {\n suggestedQuestionId: suggestedQuestion.objectID,\n };\n }\n\n sendMessage(\n {\n role: 'user',\n parts: [\n {\n type: 'text',\n text: query,\n },\n ],\n },\n messageOptions\n );\n\n if (dropdownRef.current) {\n // some test environments (like jsdom) don't implement element.scrollTo\n const el = dropdownRef.current;\n if (typeof (el as any).scrollTo === 'function') {\n el.scrollTo({ top: 0, behavior: 'smooth' });\n } else {\n // fallback for environments without scrollTo support\n el.scrollTop = 0;\n }\n }\n\n // clear the query\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n },\n [\n askAiState,\n onAskAiToggle,\n isHybridModeSupported,\n sendMessage,\n dropdownRef,\n interceptAskAiEvent,\n ]\n );\n\n // feedback handler\n const handleFeedbackSubmit = React.useCallback<OnAskAiFeedback>(\n async (messageId, feedback): Promise<void> => {\n if (!askAiConfigurationId || !appId) return;\n await sendFeedback(messageId, feedback);\n },\n [askAiConfigurationId, appId, sendFeedback]\n );\n\n if (!autocompleteRef.current) {\n autocompleteRef.current = createAutocomplete({\n id: 'docsearch',\n defaultActiveItemId: 0,\n openOnFocus: true,\n initialState: {\n query: initialQuery,\n context: {\n searchSuggestions: [],\n },\n },\n insights: Boolean(insights),\n navigator,\n onStateChange(changes) {\n setState(changes.state);\n },\n async getSources({ query, state: sourcesState, setContext, setStatus }) {\n if (isQueryEmpty(query)) {\n const noQuerySources = buildNoQuerySources({\n recentSearches,\n favoriteSearches,\n saveRecentSearch,\n onClose,\n disableUserPersonalization,\n });\n\n const recentConversationSource = canHandleAskAi\n ? buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n })\n : [];\n return [...recentConversationSource, ...noQuerySources];\n }\n\n const querySourcesState: BuildQuerySourcesState = {\n context: sourcesState.context,\n };\n\n const algoliaSourcesPromise = buildQuerySources({\n query,\n state: querySourcesState,\n setContext,\n setStatus,\n searchClient,\n indexes,\n insights: Boolean(insights),\n appId,\n apiKey,\n maxResultsPerGroup,\n transformItems,\n saveRecentSearch,\n onClose,\n facetSelections: facetSelectionsRef,\n });\n\n const askAiSourcesPromise = canHandleAskAi\n ? buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions: askAiConfig?.promptSuggestions,\n searchClient,\n })\n : Promise.resolve([]);\n\n const [askAiSources, algoliaSources] = await Promise.all([\n askAiSourcesPromise,\n algoliaSourcesPromise,\n ]);\n\n // Combine Algolia results (once resolved) with the Ask AI source\n return [...askAiSources, ...algoliaSources];\n },\n });\n }\n\n const autocomplete = autocompleteRef.current;\n\n const { getEnvironmentProps, getRootProps, refresh } = autocomplete;\n\n useModalEnvironment({\n getEnvironmentProps,\n containerRef,\n dropdownRef,\n formElementRef,\n inputRef,\n initialScrollY,\n modalRef,\n theme,\n });\n\n React.useEffect(() => {\n if (dropdownRef.current && !isAskAiActive) {\n scrollToUtils(dropdownRef.current);\n }\n }, [state.query, isAskAiActive, dropdownRef]);\n\n useRefreshOnInitialQuery({ initialQuery, inputRef, refresh });\n\n const hasCurrentMessages = messages.length > 0;\n\n // Refresh the autocomplete results when ask ai is toggled off\n // helps return to the previous ac state and start screen\n React.useEffect(() => {\n if (!isAskAiActive) {\n autocomplete.refresh();\n\n if (hasCurrentMessages) {\n startNewConversation();\n }\n }\n }, [isAskAiActive, autocomplete, startNewConversation, hasCurrentMessages]);\n\n // Track external state in order to manage internal askAiState\n React.useEffect(() => {\n setAskAiState('initial');\n }, [isAskAiActive, setAskAiState]);\n\n const onStopAskAiStreaming = async (): Promise<void> => {\n setStoppedStream(true);\n\n await stopAskAiStreaming();\n };\n\n const handleNewConversation = (): void => {\n startNewConversation();\n setAskAiState('new-conversation');\n };\n\n const handleViewConversationHistory = (): void => {\n setAskAiState('conversation-history');\n };\n\n const selectSuggestedQuestion = (\n suggestedQuestion: SuggestedQuestionHit\n ): void => {\n handleSelectAskAiQuestion(\n true,\n suggestedQuestion.question,\n suggestedQuestion\n );\n };\n\n // hide the dropdown on idle and no collections\n let showDocsearchDropdown = true;\n const hasCollections = state.collections.some(\n (collection) =>\n collection.source.sourceId !== SOURCE_IDS.askAI &&\n collection.items.length > 0\n );\n if (\n state.status === 'idle' &&\n hasCollections === false &&\n isQueryEmpty(state.query) &&\n !isAskAiActive\n ) {\n showDocsearchDropdown = false;\n }\n\n return (\n <ModalShell\n state={state}\n containerRef={containerRef}\n modalRef={modalRef}\n formElementRef={formElementRef}\n dropdownRef={dropdownRef}\n getRootProps={getRootProps}\n showDropdown={showDocsearchDropdown}\n searchBox={\n <AskAiSearchBox\n {...autocomplete}\n state={state}\n placeholder={placeholder || 'Search docs'}\n autoFocus={isQueryEmpty(initialQuery)}\n inputRef={inputRef}\n isFromSelection={\n Boolean(initialQuery) && initialQuery === initialQueryFromSelection\n }\n translations={searchBoxTranslations}\n isAskAiActive={isAskAiActive}\n askAiStatus={status}\n askAiError={askAiError}\n askAiState={askAiState}\n setAskAiState={setAskAiState}\n isThreadDepthError={\n hasThreadDepthError && askAiState !== 'new-conversation'\n }\n onClose={onClose}\n onAskAiToggle={onAskAiToggle}\n onAskAgain={(query) => {\n handleSelectAskAiQuestion(true, query);\n }}\n onStopAskAiStreaming={onStopAskAiStreaming}\n onNewConversation={handleNewConversation}\n onViewConversationHistory={handleViewConversationHistory}\n />\n }\n filterBar={\n !isAskAiActive && !isQueryEmpty(state.query) ? (\n <FacetBar\n facets={visibleFacets}\n selections={facetSelections}\n translations={facetBarTranslations}\n clearSelections={clearFacetSelections}\n onSelectionChange={handleFacetSelectionChange}\n />\n ) : null\n }\n screenState={\n <AskAiScreenState\n {...autocomplete}\n indexName={defaultIndexName}\n state={state}\n hitComponent={hitComponent}\n resultsFooterComponent={resultsFooterComponent}\n disableUserPersonalization={disableUserPersonalization}\n recentSearches={recentSearches}\n favoriteSearches={favoriteSearches}\n conversations={conversations}\n inputRef={inputRef}\n translations={screenStateTranslations}\n getMissingResultsUrl={getMissingResultsUrl}\n isAskAiActive={isAskAiActive}\n canHandleAskAi={canHandleAskAi}\n messages={messages}\n tools={tools}\n askAiError={askAiError}\n status={status}\n hasCollections={hasCollections}\n askAiState={askAiState}\n selectAskAiQuestion={handleSelectAskAiQuestion}\n suggestedQuestions={suggestedQuestions}\n selectSuggestedQuestion={selectSuggestedQuestion}\n memoryEnabled={memoryEnabled}\n resultBadgeKey={props.resultBadgeKey}\n onAskAiToggle={onAskAiToggle}\n onNewConversation={handleNewConversation}\n onItemClick={(item, event) => {\n if (item.type === 'askAI' && item.query) {\n if (item.anchor === 'stored' && 'messages' in item) {\n const hitMessages = item.messages as StoredAskAiMessage[];\n restoreConversation(\n hitMessages,\n (item as StoredAskAiState).chatId\n );\n const initialMessage: InitialAskAiMessage = {\n query: item.query,\n messageId: hitMessages[0].id,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n event.preventDefault();\n return;\n }\n\n onAskAiToggle(true, initialMessage);\n } else {\n handleSelectAskAiQuestion(true, item.query);\n }\n setAskAiState('initial');\n event.preventDefault();\n return;\n }\n\n sendItemClickEvent(item);\n saveRecentSearch(item);\n if (!isModifierEvent(event)) {\n onClose();\n }\n }}\n onFeedback={handleFeedbackSubmit}\n />\n }\n footer={\n <Footer\n translations={footerTranslations}\n isAskAiActive={isAskAiActive}\n footerAction={footerAction}\n />\n }\n onClose={onClose}\n />\n );\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import "./index-Bqqv4HmN.js";
2
- import { _ as FacetBarTranslations, g as FooterTranslations } from "./DocSearch-HJsNvtZr.js";
2
+ import { v as FooterTranslations, y as FacetBarTranslations } from "./DocSearch-BVqxFxTw.js";
3
3
  import { DocSearchAIProps } from "./docsearchAi.js";
4
- import { n as NewConversationTranslations, t as AskAiScreenStateTranslations } from "./AskAiScreenState-CRHicWbN.js";
4
+ import { n as NewConversationTranslations, t as AskAiScreenStateTranslations } from "./AskAiScreenState-Sqbn60f2.js";
5
5
  import { OnAskAiToggle } from "@docsearch/core";
6
6
  import React, { JSX } from "react";
7
7
  import { AutocompleteState } from "@algolia/autocomplete-core";
@@ -42,7 +42,7 @@ type DocSearchAskAiModalProps = DocSearchAIProps & {
42
42
  translations?: DocSearchAskAiModalTranslations;
43
43
  isHybridModeSupported?: boolean;
44
44
  };
45
- declare function DocSearchAskAiModal({ appId, apiKey, askAi, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, onAskAiToggle, interceptAskAiEvent, isAskAiActive, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, indexName, searchParameters, facets, isHybridModeSupported, ...props }: DocSearchAskAiModalProps): JSX.Element;
45
+ declare function DocSearchAskAiModal({ appId, apiKey, askAi, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, onAskAiToggle, interceptAskAiEvent, isAskAiActive, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, facets, isHybridModeSupported, footerAction, ...props }: DocSearchAskAiModalProps): JSX.Element;
46
46
  //#endregion
47
47
  export { DocSearchAskAiModalProps as n, DocSearchAskAiModalTranslations as r, DocSearchAskAiModal as t };
48
- //# sourceMappingURL=DocSearchAskAiModal-B7vpLudE.d.ts.map
48
+ //# sourceMappingURL=DocSearchAskAiModal-DpB7pLCC.d.ts.map