@docsearch/react 5.0.0-beta.0 → 5.0.0-beta.2

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 (41) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/{AskAiScreenState-D0IZsCMJ.d.ts → AskAiScreenState-Bw2WIgv_.d.ts} +6 -3
  3. package/dist/esm/{DocSearch-Dq5Utfyb.d.ts → DocSearch-CVj6U-nI.d.ts} +6 -20
  4. package/dist/esm/{DocSearchAskAiModal-CCrk6YLb.js → DocSearchAskAiModal-BczGFkvR.js} +32 -39
  5. package/dist/esm/DocSearchAskAiModal-BczGFkvR.js.map +1 -0
  6. package/dist/esm/{DocSearchAskAiModal-BwbMrrHv.d.ts → DocSearchAskAiModal-MF2py4NM.d.ts} +5 -5
  7. package/dist/esm/{DocSearchButton-CRlNPf5k.d.ts → DocSearchButton-CZM_jACU.d.ts} +2 -2
  8. package/dist/esm/{DocSearchModal-CpvDjo1O.js → DocSearchModal-D_tfhoN1.js} +13 -21
  9. package/dist/esm/DocSearchModal-D_tfhoN1.js.map +1 -0
  10. package/dist/esm/askaiModal.d.ts +1 -1
  11. package/dist/esm/askaiModal.js +1 -1
  12. package/dist/esm/button.d.ts +1 -1
  13. package/dist/esm/docsearchAi.d.ts +5 -10
  14. package/dist/esm/docsearchAi.js +14 -4
  15. package/dist/esm/docsearchAi.js.map +1 -1
  16. package/dist/esm/{index-Dl8FMlR5.d.ts → index-Bqqv4HmN.d.ts} +19 -9
  17. package/dist/esm/index.d.ts +5 -5
  18. package/dist/esm/index.js +15 -5
  19. package/dist/esm/index.js.map +1 -1
  20. package/dist/esm/modal.d.ts +1 -1
  21. package/dist/esm/modal.js +1 -1
  22. package/dist/esm/{normalizeDocSearchIndexes-DAzlMybx.js → normalizeDocSearchIndexes-D8P3VEXa.js} +90 -55
  23. package/dist/esm/normalizeDocSearchIndexes-D8P3VEXa.js.map +1 -0
  24. package/dist/esm/sidepanel.d.ts +16 -24
  25. package/dist/esm/sidepanel.js +17 -14
  26. package/dist/esm/sidepanel.js.map +1 -1
  27. package/dist/esm/{useDocSearchKeyboardEvents-68G8dw6c.d.ts → useDocSearchKeyboardEvents-u23fFhR9.d.ts} +2 -2
  28. package/dist/esm/useDocSearchKeyboardEvents.d.ts +1 -1
  29. package/dist/esm/{useSuggestedQuestions-D2TGVPsI.js → useSuggestedQuestions-Ds7H1JCr.js} +69 -55
  30. package/dist/esm/useSuggestedQuestions-Ds7H1JCr.js.map +1 -0
  31. package/dist/esm/useTheme.d.ts +1 -1
  32. package/dist/esm/version.d.ts +1 -1
  33. package/dist/esm/version.js +1 -1
  34. package/dist/esm/version.js.map +1 -1
  35. package/dist/umd/index.js +34 -32
  36. package/dist/umd/index.js.map +1 -1
  37. package/package.json +4 -4
  38. package/dist/esm/DocSearchAskAiModal-CCrk6YLb.js.map +0 -1
  39. package/dist/esm/DocSearchModal-CpvDjo1O.js.map +0 -1
  40. package/dist/esm/normalizeDocSearchIndexes-DAzlMybx.js.map +0 -1
  41. package/dist/esm/useSuggestedQuestions-D2TGVPsI.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { o as ToolCalls } from "./index-Dl8FMlR5.js";
2
- import "./DocSearch-Dq5Utfyb.js";
1
+ import { o as ToolCalls } from "./index-Bqqv4HmN.js";
2
+ import "./DocSearch-CVj6U-nI.js";
3
3
  import { AgentStudioIndices, AgentStudioSearchParameters, Memory } from "./docsearchAi.js";
4
- import { r as ToolCallTranslations } from "./AskAiScreenState-D0IZsCMJ.js";
4
+ import { r as ToolCallTranslations } from "./AskAiScreenState-Bw2WIgv_.js";
5
5
  import { DocSearchCallbacks, DocSearchCallbacks as DocSearchCallbacks$1, DocSearchRef, DocSearchRef as DocSearchRef$1, DocSearchTheme, InitialAskAiMessage, SidepanelShortcuts } from "@docsearch/core";
6
6
  import React, { JSX } from "react";
7
7
  import "@ai-sdk/react";
@@ -18,8 +18,10 @@ type ConversationScreenTranslations = Partial<ToolCallTranslations & {
18
18
  reasoningText: string;
19
19
  /** Text show while assistant is thinking. */
20
20
  thinkingText: string;
21
- /** Text shown describing related sources. */
21
+ /** Text shown describing a singular related source. */
22
22
  relatedSourcesText: string;
23
+ /** Text shown describing multiple related sources. */
24
+ relatedSourcesTextPlural: string;
23
25
  /** Message that's shown when user has stopped the streaming of a message. */
24
26
  stoppedStreamingText: string;
25
27
  /** Text shown for copy button on code snippets. */
@@ -50,7 +52,7 @@ type ConversationScreenTranslations = Partial<ToolCallTranslations & {
50
52
  feedbackTagSafetyOrLegal: string;
51
53
  feedbackTagOther: string;
52
54
  /** Error title shown if there is an error while chatting. */
53
- errorTitleText: any;
55
+ errorTitleText: string;
54
56
  suggestedPromptsTitleText: string;
55
57
  }>;
56
58
  //#endregion
@@ -176,7 +178,7 @@ type SidepanelProps = Pick<DocSearchSidepanelProps, 'indices' | 'memory' | 'tool
176
178
  */
177
179
  keyboardShortcuts?: SidepanelShortcuts;
178
180
  };
179
- declare const Sidepanel: React.ForwardRefExoticComponent<Omit<DocSearchSidepanelProps, "indices" | "button" | "panel" | "tools" | "memory"> & Pick<DocSearchSidepanelProps, "indices" | "tools" | "memory"> & {
181
+ declare const Sidepanel: React.ForwardRefExoticComponent<Omit<DocSearchSidepanelProps, "button" | "panel" | "tools" | "memory" | "indices"> & Pick<DocSearchSidepanelProps, "tools" | "memory" | "indices"> & {
180
182
  /**
181
183
  * Variant of the Sidepanel positioning.
182
184
  *
@@ -293,17 +295,12 @@ type SidepanelSearchParameters = {
293
295
  searchParameters?: AgentStudioSearchParameters;
294
296
  };
295
297
  type DocSearchSidepanelProps = DocSearchCallbacks$1 & {
296
- /** The assistant ID to use for the ask AI feature. */
297
- assistantId: string;
298
- /** Public api key with search permissions for the index. */
298
+ /** The Agent Studio agent ID to use for Ask AI. */
299
+ agentId: string;
300
+ /** Search only API key. */
299
301
  apiKey: string;
300
- /** Algolia application id used by the search client. */
302
+ /** Algolia application ID that hosts the Agent Studio agent. */
301
303
  appId: string;
302
- /**
303
- * The index name to use for the ask AI feature. Your assistant will search
304
- * this index for relevant documents.
305
- */
306
- indexName: string;
307
304
  /**
308
305
  * Configuration for keyboard shortcuts. Allows enabling/disabling specific
309
306
  * shortcuts.
@@ -342,17 +339,12 @@ type DocSearchSidepanelProps = DocSearchCallbacks$1 & {
342
339
  indices?: AgentStudioIndices[];
343
340
  };
344
341
  declare const DocSearchSidepanel: React.ForwardRefExoticComponent<DocSearchCallbacks$1 & {
345
- /** The assistant ID to use for the ask AI feature. */
346
- assistantId: string;
347
- /** Public api key with search permissions for the index. */
342
+ /** The Agent Studio agent ID to use for Ask AI. */
343
+ agentId: string;
344
+ /** Search only API key. */
348
345
  apiKey: string;
349
- /** Algolia application id used by the search client. */
346
+ /** Algolia application ID that hosts the Agent Studio agent. */
350
347
  appId: string;
351
- /**
352
- * The index name to use for the ask AI feature. Your assistant will search
353
- * this index for relevant documents.
354
- */
355
- indexName: string;
356
348
  /**
357
349
  * Configuration for keyboard shortcuts. Allows enabling/disabling specific
358
350
  * shortcuts.
@@ -2,7 +2,7 @@ import { t as _objectSpread2 } from "./objectSpread2-BNmiQYyW.js";
2
2
  import { n as isAppleDevice, t as ACTION_KEY_DEFAULT } from "./keyboard-BkSdCzTU.js";
3
3
  import { n as SearchIcon, t as _objectWithoutProperties } from "./objectWithoutProperties-phqYxDS0.js";
4
4
  import { a as AlgoliaLogo, f as RecentIcon, 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, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-D2TGVPsI.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, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-Ds7H1JCr.js";
6
6
  import { version } from "./version.js";
7
7
  import { DocSearch, useDocSearch } from "@docsearch/core";
8
8
  import React, { Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
@@ -133,9 +133,9 @@ function AggregatedSearchBlock({ queries }) {
133
133
  //#endregion
134
134
  //#region src/Sidepanel/ConversationScreen.tsx
135
135
  const ConversationExchange = React.forwardRef(({ exchange, translations = {}, isLastExchange, conversations, onFeedback, status, streamError, memoryEnabled, tools, onSelectPromptSuggestion }, conversationRef) => {
136
- var _userMessage$metadata, _assistantMessage$met, _userContent$text;
136
+ var _userMessage$metadata, _assistantMessage$met;
137
137
  const { userMessage, assistantMessage } = exchange;
138
- const { reasoningText = "Reasoning...", thinkingText = "Thinking...", searchingText = "Searching...", relatedSourcesText, stoppedStreamingText = "You stopped this response", preToolCallText = "Searching...", toolCallResultText = "Searched for", copyButtonText = "Copy", copyButtonCopiedText = "Copied!", errorTitleText = "Chat error", savedMemoryToolResultText = "Saved to memory", memoryToolResultText = "Used memory to enhance results", suggestedPromptsTitleText = "Suggested prompts" } = translations;
138
+ const { reasoningText = "Reasoning...", thinkingText = "Thinking...", searchingText = "Searching...", relatedSourcesText, relatedSourcesTextPlural, stoppedStreamingText = "You stopped this response", preToolCallText = "Searching...", toolCallResultText = "Searched for", copyButtonText = "Copy", copyButtonCopiedText = "Copied!", errorTitleText = "Chat error", savedMemoryToolResultText = "Saved to memory", memoryToolResultText = "Used memory to enhance results", suggestedPromptsTitleText = "Suggested prompts" } = translations;
139
139
  const assistantContent = useMemo(() => getMessageContent(assistantMessage), [assistantMessage]);
140
140
  const userContent = useMemo(() => getMessageContent(userMessage), [userMessage]);
141
141
  const assistantParts = useMemo(() => groupConsecutiveToolResults((assistantMessage === null || assistantMessage === void 0 ? void 0 : assistantMessage.parts) || []), [assistantMessage]);
@@ -151,7 +151,7 @@ const ConversationExchange = React.forwardRef(({ exchange, translations = {}, is
151
151
  return /* @__PURE__ */ React.createElement("div", {
152
152
  className: "DocSearch-AskAiScreen-Response-Container",
153
153
  ref: conversationRef
154
- }, /* @__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" }, status === "error" && streamError && isLastExchange && /* @__PURE__ */ React.createElement("div", {
154
+ }, /* @__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" }, status === "error" && streamError && isLastExchange && /* @__PURE__ */ React.createElement("div", {
155
155
  className: "DocSearch-AskAiScreen-Error",
156
156
  role: "alert"
157
157
  }, /* @__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, {
@@ -163,8 +163,8 @@ const ConversationExchange = React.forwardRef(({ exchange, translations = {}, is
163
163
  const index = idx;
164
164
  if (part.type === "reasoning" && part.state === "streaming") return /* @__PURE__ */ React.createElement("div", {
165
165
  key: index,
166
- className: "DocSearch-AskAiScreen-MessageContent-Reasoning shimmer"
167
- }, /* @__PURE__ */ React.createElement(LoadingIcon, { className: "DocSearch-AskAiScreen-SmallerLoadingIcon" }), /* @__PURE__ */ React.createElement("span", { className: "shimmer" }, reasoningText));
166
+ className: "DocSearch-AskAiScreen-MessageContent-Reasoning DocSearch-shimmer"
167
+ }, /* @__PURE__ */ React.createElement(LoadingIcon, { className: "DocSearch-AskAiScreen-SmallerLoadingIcon" }), /* @__PURE__ */ React.createElement("span", { className: "DocSearch-shimmer" }, reasoningText));
168
168
  if (part.type === "aggregated-tool-call") return /* @__PURE__ */ React.createElement(AggregatedSearchBlock, {
169
169
  key: index,
170
170
  queries: part.queries
@@ -200,14 +200,15 @@ const ConversationExchange = React.forwardRef(({ exchange, translations = {}, is
200
200
  }), isThinking && isLastExchange && assistantParts.length === 0 && /* @__PURE__ */ React.createElement("div", {
201
201
  className: "DocSearch-AskAiScreen-MessageContent-Thinking",
202
202
  role: "status"
203
- }, /* @__PURE__ */ React.createElement("span", { className: "shimmer" }, thinkingText), /* @__PURE__ */ React.createElement("span", { className: "DocSearch-AskAi-Thinking-Skeleton shimmer" }), /* @__PURE__ */ React.createElement("span", { className: "DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short shimmer" }))), wasStopped && /* @__PURE__ */ React.createElement("p", { className: "DocSearck-AskAiScreen-MessageContent-Stopped" }, stoppedStreamingText)), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Answer-Footer" }, /* @__PURE__ */ React.createElement(SourcesPanel, {
203
+ }, /* @__PURE__ */ React.createElement("span", { className: "DocSearch-shimmer" }, thinkingText), /* @__PURE__ */ React.createElement("span", { className: "DocSearch-AskAi-Thinking-Skeleton DocSearch-shimmer" }), /* @__PURE__ */ React.createElement("span", { className: "DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short DocSearch-shimmer" }))), wasStopped && /* @__PURE__ */ React.createElement("p", { className: "DocSearch-AskAiScreen-MessageContent-Stopped" }, stoppedStreamingText)), /* @__PURE__ */ React.createElement("div", { className: "DocSearch-AskAiScreen-Answer-Footer" }, /* @__PURE__ */ React.createElement(SourcesPanel, {
204
204
  links: urlsToDisplay,
205
- titleText: relatedSourcesText
205
+ titleText: relatedSourcesText,
206
+ pluralTitleText: relatedSourcesTextPlural
206
207
  }), /* @__PURE__ */ React.createElement(FeedbackActions, {
207
208
  isSidepanel: true,
208
209
  id: messageId,
209
210
  showActions,
210
- latestAssistantMessageContent: (assistantContent === null || assistantContent === void 0 ? void 0 : assistantContent.text) || null,
211
+ latestAssistantMessageContent: assistantContent || null,
211
212
  translations,
212
213
  conversations,
213
214
  onFeedback
@@ -497,7 +498,7 @@ const useSidepanelWidth = ({ isExpanded, width, expandedWidth }) => {
497
498
 
498
499
  //#endregion
499
500
  //#region src/Sidepanel/Sidepanel.tsx
500
- function SidepanelInner({ isOpen = false, onOpen, onClose, assistantId, apiKey, appId, indexName, variant = "floating", searchParameters, pushSelector, width, expandedWidth, suggestedQuestions: suggestedQuestionsEnabled = false, translations = {}, keyboardShortcuts, side = "right", initialMessage, tools = EMPTY_TOOLS, memory, indices }, ref) {
501
+ function SidepanelInner({ isOpen = false, onOpen, onClose, agentId, apiKey, appId, variant = "floating", searchParameters, pushSelector, width, expandedWidth, suggestedQuestions: suggestedQuestionsEnabled = false, translations = {}, keyboardShortcuts, side = "right", initialMessage, tools = EMPTY_TOOLS, memory, indices }, ref) {
501
502
  var _memory$enabled;
502
503
  const [isExpanded, setIsExpanded] = React.useState(false);
503
504
  const [sidepanelState, setSidepanelState] = React.useState("new-conversation");
@@ -517,8 +518,7 @@ function SidepanelInner({ isOpen = false, onOpen, onClose, assistantId, apiKey,
517
518
  const searchClient = useSearchClient(appId, apiKey, setSidepanelSearchClient);
518
519
  const { chatId, status, sendMessage, stopAskAiStreaming, isStreaming, exchanges, conversations, messages, sendFeedback, askAiError, startNewConversation, restoreConversation } = useAskAi({
519
520
  appId,
520
- indexName,
521
- assistantId,
521
+ agentId,
522
522
  apiKey,
523
523
  searchParameters,
524
524
  tools,
@@ -526,7 +526,7 @@ function SidepanelInner({ isOpen = false, onOpen, onClose, assistantId, apiKey,
526
526
  indices
527
527
  });
528
528
  const suggestedQuestions = useSuggestedQuestions({
529
- assistantId,
529
+ agentId,
530
530
  suggestedQuestionsEnabled,
531
531
  searchClient
532
532
  });
@@ -725,6 +725,8 @@ const _excluded3 = ["button", "panel"];
725
725
  function DocSearchSidepanelComponent(_ref, ref) {
726
726
  let { keyboardShortcuts, theme, onReady, onOpen, onClose, onSidepanelOpen, onSidepanelClose } = _ref, props = _objectWithoutProperties(_ref, _excluded);
727
727
  return /* @__PURE__ */ React.createElement(DocSearch, {
728
+ appId: props.appId,
729
+ apiKey: props.apiKey,
728
730
  keyboardShortcuts,
729
731
  theme,
730
732
  ref,
@@ -738,7 +740,8 @@ function DocSearchSidepanelComponent(_ref, ref) {
738
740
  const DocSearchSidepanel = React.forwardRef(DocSearchSidepanelComponent);
739
741
  function DocSearchSidepanelComp(_ref2) {
740
742
  let { button: buttonProps = {}, panel: _ref3 = {} } = _ref2, { portalContainer } = _ref3, panelProps = _objectWithoutProperties(_ref3, _excluded2), rootProps = _objectWithoutProperties(_ref2, _excluded3);
741
- const { docsearchState, setDocsearchState, keyboardShortcuts, registerView, initialAskAiMessage } = useDocSearch();
743
+ const { docsearchState, setDocsearchState, keyboardShortcuts, registerView, initialAskAiMessage, appId, apiKey } = useDocSearch();
744
+ if (!appId || !apiKey) throw new Error("`Sidepanel` requires `appId` and `apiKey` props or values configured on the `DocSearch` provider.");
742
745
  const toggleSidepanelState = React.useCallback(() => {
743
746
  setDocsearchState(docsearchState === "sidepanel" ? "ready" : "sidepanel");
744
747
  }, [docsearchState, setDocsearchState]);
@@ -1 +1 @@
1
- {"version":3,"file":"sidepanel.js","names":[],"sources":["../../src/icons/SendIcon.tsx","../../src/icons/ExpandIcon.tsx","../../src/icons/FolderIcon.tsx","../../src/icons/EditIcon.tsx","../../src/useIsMobile.ts","../../src/Sidepanel/ConversationHistoryScreen.tsx","../../src/Sidepanel/AggregatedSearchBlock.tsx","../../src/Sidepanel/ConversationScreen.tsx","../../src/Sidepanel/NewConversationScreen.tsx","../../src/Sidepanel/PromptForm.tsx","../../src/Sidepanel/setSidepanelSearchClient.ts","../../src/Sidepanel/SidepanelHeader.tsx","../../src/Sidepanel/useManageSidepanelLayout.ts","../../src/Sidepanel/useSidepanelKeyboardEvents.ts","../../src/Sidepanel/useSidepanelWidth.ts","../../src/Sidepanel/Sidepanel.tsx","../../src/Sidepanel/SidepanelButton.tsx","../../src/Sidepanel.tsx"],"sourcesContent":["import type { JSX } from 'react';\nimport React from 'react';\n\nexport const SendIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\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=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n );\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nexport const ExpandIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 13 13\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M8 0.5C8 0.223858 8.22386 0 8.5 0H12.5C12.7761 0 13 0.223858 13 0.5V4.5C13 4.77614 12.7761 5 12.5 5C12.2239 5 12 4.77614 12 4.5V1.70711L8.18689 5.52022C7.99162 5.71548 7.67504 5.71548 7.47978 5.52022C7.28452 5.32496 7.28452 5.00838 7.47978 4.81311L11.2929 1H8.5C8.22386 1 8 0.776142 8 0.5ZM5.52022 7.47978C5.71548 7.67504 5.71548 7.99162 5.52022 8.18689L1.70711 12H4.5C4.77614 12 5 12.2239 5 12.5C5 12.7761 4.77614 13 4.5 13H0.5C0.223858 13 0 12.7761 0 12.5V8.5C0 8.22386 0.223858 8 0.5 8C0.776142 8 1 8.22386 1 8.5V11.2929L4.81311 7.47978C5.00838 7.28452 5.32496 7.28452 5.52022 7.47978Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const FolderIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\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=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const EditIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\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=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </svg>\n );\n};\n","import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */\nimport React from 'react';\nimport type { JSX } from 'react';\n\nimport { CloseIcon, RecentIcon } from '../icons';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { StoredAskAiState } from '../types';\n\ntype ConversationHistoryScreenProps = {\n conversations: StoredSearchPlugin<StoredAskAiState>;\n selectConversation: (conversation: StoredAskAiState) => void;\n};\n\nexport const ConversationHistoryScreen = ({\n conversations,\n selectConversation,\n}: ConversationHistoryScreenProps): JSX.Element => {\n const [items, setItems] = React.useState(() => conversations.getAll());\n\n const handleRemoveConversation = (item: StoredAskAiState): void => {\n conversations.remove(item);\n setItems(conversations.getAll());\n };\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationHistoryScreen\">\n <ul>\n {items.map((item) => (\n <li\n key={item.objectID}\n className=\"DocSearch-Sidepanel-RecentConversation\"\n >\n <a\n href={item.url}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n\n selectConversation(item);\n }}\n >\n <div className=\"DocSearch-Sidepanel-RecentConversation-container\">\n <div className=\"DocSearch-Sidepanel-RecentConversation-icon\">\n <RecentIcon />\n </div>\n\n <div className=\"DocSearch-Sidepanel-RecentConversation-content\">\n <span className=\"DocSearch-Sidepanel-RecentConversation-title\">\n {item.hierarchy.lvl1}\n </span>\n </div>\n\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n type=\"button\"\n title=\"Remove conversation from history\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleRemoveConversation(item);\n }}\n >\n <CloseIcon />\n </button>\n </div>\n </div>\n </a>\n </li>\n ))}\n </ul>\n </div>\n );\n};\n","import React, { Fragment } from 'react';\nimport type { JSX } from 'react';\n\nimport { SearchIcon } from '../icons';\n\ntype AggregatedSearchBlockProps = {\n queries: string[];\n};\n\nconst before = 'Searched for ';\nconst separator = ', ';\nconst lastSeparator = ' and ';\nconst after = '';\n\nexport function AggregatedSearchBlock({\n queries,\n}: AggregatedSearchBlockProps): JSX.Element {\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 className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\">\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 type { JSX } from 'react';\nimport React, { memo, useMemo } from 'react';\n\nimport { type Exchange } from '../AskAiScreen';\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 } from '../icons';\nimport { MemoizedMarkdown } from '../MemoizedMarkdown';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { OnAskAiFeedback, StoredAskAiState } from '../types';\nimport { type AIMessage, type ToolCalls } from '../types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n EMPTY_TOOLS,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from '../utils/ai';\nimport { groupConsecutiveToolResults } from '../utils/groupConsecutiveToolResults';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\n\nexport type ConversationScreenTranslations = Partial<\n ToolCallTranslations & {\n /** Text shown as an LLM disclaimer. */\n conversationDisclaimer: string;\n /** Text shown while assistant is reasoning. */\n reasoningText: string;\n /** Text show while assistant is thinking. */\n thinkingText: string;\n /** Text shown describing related sources. */\n relatedSourcesText: string;\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Text shown for copy button on code snippets. */\n copyButtonText: string;\n /** Message shown after clicking copy. */\n copyButtonCopiedText: string;\n /** Title for thumbs up feedback icon. */\n likeButtonTitle: string;\n /** Title for thumbs down feedback icon. */\n dislikeButtonTitle: string;\n /** Message displayed after feedback action. */\n thanksForFeedbackText: string;\n /** Title shown at the top of the negative feedback note panel. */\n feedbackPanelTitle: string;\n /** Placeholder for the negative feedback details textarea. */\n feedbackDetailsPlaceholder: string;\n /** Disclaimer shown inside the negative feedback note panel. */\n feedbackDisclaimerText: string;\n /** Submit button text for the negative feedback note panel. */\n feedbackSubmitButtonText: string;\n /** Accessible title for the negative feedback note panel close button. */\n feedbackCloseButtonTitle: string;\n /** Reason chip labels for the negative feedback note panel. */\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText;\n suggestedPromptsTitleText: string;\n }\n>;\n\nexport type ConversationScreenProps = {\n exchanges: Exchange[];\n conversations: StoredSearchPlugin<StoredAskAiState>;\n translations?: ConversationScreenTranslations;\n status: UseChatHelpers<AIMessage>['status'];\n handleFeedback?: OnAskAiFeedback;\n streamError?: Error;\n memoryEnabled?: boolean;\n tools?: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\ntype ConversationnExchangeProps = {\n exchange: Exchange;\n isLastExchange: boolean;\n status: ConversationScreenProps['status'];\n conversations: ConversationScreenProps['conversations'];\n translations?: ConversationScreenTranslations;\n onFeedback?: ConversationScreenProps['handleFeedback'];\n streamError?: ConversationScreenProps['streamError'];\n memoryEnabled?: boolean;\n tools: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\nconst ConversationExchange = React.forwardRef<\n HTMLDivElement,\n ConversationnExchangeProps\n>(\n (\n {\n exchange,\n translations = {},\n isLastExchange,\n conversations,\n onFeedback,\n status,\n streamError,\n memoryEnabled,\n tools,\n onSelectPromptSuggestion,\n },\n conversationRef\n ): JSX.Element => {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n reasoningText = 'Reasoning...',\n thinkingText = 'Thinking...',\n searchingText = 'Searching...',\n relatedSourcesText,\n stoppedStreamingText = 'You stopped this response',\n preToolCallText = 'Searching...',\n toolCallResultText = 'Searched for',\n copyButtonText = 'Copy',\n copyButtonCopiedText = 'Copied!',\n errorTitleText = 'Chat error',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const assistantParts = useMemo(\n () => groupConsecutiveToolResults(assistantMessage?.parts || []),\n [assistantMessage]\n );\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n const suggestedPrompts = React.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 const isThinking =\n ['submitted', 'streaming'].includes(status) &&\n !assistantParts.some((part) => part.type !== 'step-start');\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange && status === 'ready' && Boolean(assistantMessage)));\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div\n className=\"DocSearch-AskAiScreen-Response-Container\"\n ref={conversationRef}\n >\n <div className=\"DocSearch-AskAiScreen-Response\">\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user\">\n <p className=\"DocSearch-AskAiScreen-Query\">\n {userContent?.text ?? ''}\n </p>\n </div>\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant\">\n <div className=\"DocSearch-AskAiScreen-MessageContent\">\n {status === 'error' && streamError && isLastExchange && (\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={streamError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n\n {assistantParts.map((part, idx) => {\n const index = idx;\n\n if (part.type === 'reasoning' && part.state === 'streaming') {\n return (\n <div\n key={index}\n className=\"DocSearch-AskAiScreen-MessageContent-Reasoning shimmer\"\n >\n <LoadingIcon className=\"DocSearch-AskAiScreen-SmallerLoadingIcon\" />\n <span className=\"shimmer\">{reasoningText}</span>\n </div>\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock key={index} queries={part.queries} />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n part={part}\n translations={{\n preToolCallText,\n searchingText,\n toolCallResultText,\n savedMemoryToolResultText,\n memoryToolResultText,\n }}\n tools={tools}\n memoryEnabled={memoryEnabled}\n />\n );\n }\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={false}\n />\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n return null;\n })}\n\n {isThinking && isLastExchange && assistantParts.length === 0 && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"shimmer\">{thinkingText}</span>\n <span className=\"DocSearch-AskAi-Thinking-Skeleton shimmer\" />\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short shimmer\" />\n </div>\n )}\n </div>\n\n {wasStopped && (\n <p className=\"DocSearck-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n />\n <FeedbackActions\n isSidepanel={true}\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent?.text || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {suggestedPrompts.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={suggestedPrompts}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n }\n);\n\nexport const ConversationScreen = memo(\n ({\n exchanges,\n translations = {},\n handleFeedback,\n tools = EMPTY_TOOLS,\n status,\n conversations,\n streamError,\n memoryEnabled,\n onSelectPromptSuggestion,\n }: ConversationScreenProps): JSX.Element => {\n const {\n conversationDisclaimer = 'Answers are generated with AI which can make mistakes. Verify responses.',\n } = translations;\n\n const mostRecentExchangeRef = React.useRef<HTMLDivElement>(null);\n const totalExchanges = exchanges.length;\n\n // Only scroll the most recent exchange into view when needed\n React.useEffect(() => {\n if (mostRecentExchangeRef.current) {\n mostRecentExchangeRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [totalExchanges]);\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationScreen\">\n <p className=\"DocSearch-Sidepanel-ConversationScreen-disclaimer\">\n {conversationDisclaimer}\n </p>\n\n {exchanges.slice().map((exchange, idx) => {\n const isLastExchange = idx === exchanges.length - 1;\n return (\n <ConversationExchange\n key={exchange.id}\n exchange={exchange}\n translations={translations}\n isLastExchange={isLastExchange}\n ref={isLastExchange ? mostRecentExchangeRef : null}\n tools={tools}\n status={status}\n conversations={conversations}\n streamError={streamError}\n memoryEnabled={memoryEnabled}\n onFeedback={handleFeedback}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n );\n })}\n </div>\n );\n }\n);\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { SuggestedQuestionHit } from '../types';\n\nexport type NewConversationScreenTranslations = Partial<{\n /** Title to be shown on the new conversation/starting screen. */\n titleText: string;\n /** Introduction text displayed on the new conversation/starting screen. */\n introductionText: string;\n}>;\n\ntype NewConversationScreenProps = {\n suggestedQuestions: SuggestedQuestionHit[];\n onSelectQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationScreenTranslations;\n};\n\nexport const NewConversationScreen = ({\n suggestedQuestions,\n onSelectQuestion,\n translations = {},\n}: NewConversationScreenProps): JSX.Element => {\n const {\n titleText = 'How can I help you today?',\n introductionText = '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-Sidepanel-NewConversationScreen\">\n <h4 className=\"DocSearch-Sidepanel-Screen--title\">{titleText}</h4>\n <p className=\"DocSearch-Sidepanel-Screen--introduction\">\n {introductionText}\n </p>\n\n <div className=\"DocSearch-Sidepanel-List\">\n {suggestedQuestions.map((q) => (\n <button\n key={q.objectID}\n type=\"button\"\n className=\"DocSearch-Sidepanel-SuggestedQuestion\"\n title=\"View conversation\"\n onClick={() => {\n onSelectQuestion(q);\n }}\n >\n <span>{q.question}</span>\n </button>\n ))}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport { SendIcon, StopIcon } from '../icons';\nimport { useIsMobile } from '../useIsMobile';\n\nexport type PromptFormTranslations = Partial<{\n /** Initial placeholder for the prompt input. */\n promptPlaceholderText: string;\n /** Placeholder text for wile a conversation is streaming. */\n promptAnsweringText: string;\n /** Placeholder text for after a question has already been asked. */\n promptAskAnotherQuestionText: string;\n /** Disclaimer text displayed beneath the prompt form. */\n promptDisclaimerText: string;\n promptLabelText: string;\n promptAriaLabelText: string;\n}>;\n\ntype Props = {\n exchanges: Exchange[];\n isStreaming: boolean;\n translations?: PromptFormTranslations;\n onSend: (prompt: string) => void;\n onStopStreaming: () => void;\n};\n\nconst MAX_PROMPT_ROWS = 8;\n\nexport const PromptForm = React.forwardRef<HTMLTextAreaElement, Props>(\n (\n { exchanges, isStreaming, translations = {}, onSend, onStopStreaming },\n ref\n ): JSX.Element => {\n const isMobile = useIsMobile();\n const [userPrompt, setUserPrompt] = React.useState('');\n const promptRef = React.useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(\n ref,\n () => promptRef.current as HTMLTextAreaElement\n );\n\n const {\n promptPlaceholderText = 'Ask a question',\n promptAnsweringText = 'Answering...',\n promptAskAnotherQuestionText = 'Ask another question',\n promptDisclaimerText = 'Answers are generated with AI which can make mistakes.',\n promptLabelText = 'Press Enter to send, or Shift and Enter for new line.',\n promptAriaLabelText = 'Prompt input',\n } = translations;\n\n const managePromptHeight = (): void => {\n if (!promptRef.current) return;\n\n const textArea = promptRef.current;\n const styles = getComputedStyle(textArea);\n\n const lineHeight = parseFloat(styles.lineHeight);\n const paddingTop = parseFloat(styles.paddingTop);\n const paddingBottom = parseFloat(styles.paddingBottom);\n const padding = paddingTop + paddingBottom;\n\n textArea.style.height = 'auto';\n\n const fullHeight = textArea.scrollHeight;\n const maxHeight = MAX_PROMPT_ROWS * lineHeight + padding;\n\n textArea.style.overflowY = fullHeight > maxHeight ? 'auto' : 'hidden';\n textArea.style.height = `${Math.min(fullHeight, maxHeight)}px`;\n };\n\n const handleSend = (): void => {\n if (isStreaming) return;\n\n const prompt = userPrompt.trim();\n\n if (prompt === '') return;\n\n onSend(prompt);\n\n setUserPrompt('');\n\n requestAnimationFrame(() => {\n promptRef.current?.focus();\n\n managePromptHeight();\n });\n };\n\n const handleKeyDown = (\n e: React.KeyboardEvent<HTMLTextAreaElement>\n ): void => {\n // Allow Enter to work normally (new line) when streaming\n if (isStreaming) return;\n\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n\n handleSend();\n }\n };\n\n React.useLayoutEffect(() => {\n managePromptHeight();\n }, [isMobile]);\n\n let promptPlaceholder = promptPlaceholderText;\n\n if (isStreaming) {\n promptPlaceholder = promptAnsweringText;\n } else if (exchanges.length > 0) {\n promptPlaceholder = promptAskAnotherQuestionText;\n }\n\n return (\n <div className=\"DocSearch-Sidepanel-Prompt\">\n <form\n className=\"DocSearch-Sidepanel-Prompt--form\"\n onSubmit={(e) => {\n e.preventDefault();\n\n if (isStreaming) return;\n\n handleSend();\n }}\n >\n <textarea\n ref={promptRef}\n placeholder={promptPlaceholder}\n className=\"DocSearch-Sidepanel-Prompt--textarea\"\n value={userPrompt}\n aria-label={promptAriaLabelText}\n aria-labelledby=\"prompt-label\"\n autoComplete=\"off\"\n translate=\"no\"\n rows={isMobile ? 1 : 2}\n onKeyDown={handleKeyDown}\n onInput={managePromptHeight}\n onChange={(e) => setUserPrompt(e.target.value)}\n />\n <span id=\"prompt-label\" className=\"sr-only\">\n {promptLabelText}\n </span>\n <div className=\"DocSearch-Sidepanel-Prompt--actions\">\n {isStreaming && (\n <button\n type=\"button\"\n title=\"Stop streaming\"\n className=\"DocSearch-Sidepanel-Prompt--stop\"\n onClick={onStopStreaming}\n >\n <StopIcon />\n </button>\n )}\n {!isStreaming && (\n <button\n type=\"submit\"\n aria-label=\"Send question\"\n title=\"Send question\"\n className=\"DocSearch-Sidepanel-Prompt--submit\"\n aria-disabled={userPrompt === ''}\n >\n <SendIcon />\n </button>\n )}\n </div>\n </form>\n <p className=\"DocSearch-Sidepanel-Prompt--disclaimer\">\n {promptDisclaimerText}\n </p>\n </div>\n );\n }\n);\n","import type { DocSearchTransformClient } from '..';\nimport { version } from '../version';\n\nexport const setSidepanelSearchClient = (\n client: DocSearchTransformClient\n): DocSearchTransformClient => {\n if (\n /docsearch-sidepanel.js \\(.*\\)/.test(\n client.transporter.algoliaAgent.value\n ) === false\n ) {\n client.addAlgoliaAgent('docsearch-sidepanel', version);\n }\n\n return client;\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport {\n CloseIcon,\n ConversationHistoryIcon,\n EditIcon,\n ExpandIcon,\n FolderIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n SparklesIcon,\n} from '../icons';\nimport { BackIcon } from '../icons/BackIcon';\nimport { Menu } from '../Menu';\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { SidepanelState } from './types';\n\ntype BackButtonProps = {\n mobile?: boolean;\n onBack: () => void;\n disabled?: boolean;\n};\n\nconst BackButton = ({\n onBack,\n mobile = false,\n disabled = false,\n}: BackButtonProps): JSX.Element => {\n return (\n <button\n type=\"button\"\n className={`DocSearch-Action DocSearch-Sidepanel-Action-back${mobile ? ' mobile' : ''}`}\n title=\"Go back to previous screen\"\n aria-disabled={disabled}\n onClick={disabled ? undefined : onBack}\n >\n <BackIcon />\n </button>\n );\n};\n\nexport type HeaderTranslations = Partial<{\n /** The main title text shown on the header. */\n title: string;\n /** The title text shown on the conversation history screen. */\n conversationHistoryTitle: string;\n /** The text shown on the start a conversation button. */\n newConversationText: string;\n /** The text shown on the view conversation history button. */\n viewConversationHistoryText: string;\n}>;\n\ntype SidepanelHeaderProps = {\n sidepanelState: SidepanelState;\n exchanges: Exchange[];\n setSidepanelState: (state: SidepanelState) => void;\n onNewConversation: () => void;\n onToggleExpanded: () => void;\n onClose: () => void;\n translations?: HeaderTranslations;\n hasConversations: boolean;\n isStreaming: boolean;\n};\n\nexport const SidepanelHeader = React.memo(\n ({\n sidepanelState,\n exchanges,\n setSidepanelState,\n onNewConversation,\n onToggleExpanded,\n onClose,\n translations = {},\n hasConversations,\n isStreaming,\n }: SidepanelHeaderProps): JSX.Element => {\n const {\n title = 'Ask AI',\n conversationHistoryTitle = 'My conversation history',\n newConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n } = translations;\n\n const isMobile = useIsMobile();\n\n const goToConversationHistory = (): void => {\n setSidepanelState('conversation-history');\n };\n\n const onBack = React.useCallback((): void => {\n if (exchanges.length > 0) {\n setSidepanelState('conversation');\n } else {\n setSidepanelState('new-conversation');\n }\n }, [exchanges, setSidepanelState]);\n\n const newConversationDisabled =\n sidepanelState === 'new-conversation' && exchanges.length < 1;\n\n let header = title;\n\n if (sidepanelState === 'conversation-history') {\n header = conversationHistoryTitle;\n }\n\n if (isMobile) {\n header = title;\n }\n\n return (\n <header className=\"DocSearch-Sidepanel-Header\">\n <div className=\"DocSearch-Sidepanel-Header--left\">\n <BackButton mobile={true} disabled={isStreaming} onBack={onBack} />\n\n {sidepanelState === 'conversation-history' && (\n <div className=\"DocSearch-Divider\" />\n )}\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={newConversationText}\n onClick={onNewConversation}\n >\n <EditIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={viewConversationHistoryText}\n onClick={goToConversationHistory}\n >\n <FolderIcon />\n </button>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--center\">\n <BackButton disabled={isStreaming} onBack={onBack} />\n <SparklesIcon className=\"DocSearch-Sidepanel-Header-TitleIcon\" />\n <h2 className=\"DocSearch-Sidepanel-Title\">{header}</h2>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--right\">\n {sidepanelState !== 'conversation-history' &&\n (!newConversationDisabled || hasConversations) && (\n <Menu>\n <Menu.Trigger\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-menu\"\n disabled={isStreaming}\n >\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n {!newConversationDisabled && (\n <Menu.Item onClick={onNewConversation}>\n <NewConversationIcon />\n {newConversationText}\n </Menu.Item>\n )}\n {hasConversations && (\n <Menu.Item onClick={goToConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n )}\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-expand\"\n title=\"Expand or collapse Sidepanel\"\n onClick={onToggleExpanded}\n >\n <ExpandIcon />\n </button>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-close\"\n title=\"Close Sidepanel\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n </div>\n </header>\n );\n }\n);\n","import { useLayoutEffect, useRef } from 'react';\n\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { PanelSide, PanelVariant } from './types';\n\ntype UseManageSidepanelLayoutProps = {\n variant: PanelVariant;\n side: PanelSide;\n selectors: string;\n isOpen: boolean;\n expectedWidth: string;\n};\n\nexport function useManageSidepanelLayout({\n variant,\n selectors,\n isOpen,\n expectedWidth,\n side,\n}: UseManageSidepanelLayoutProps): void {\n const targetRef = useRef<HTMLElement | null>(null);\n const lastSelectorRef = useRef<string | null>(null);\n const isMobile = useIsMobile();\n\n useLayoutEffect(() => {\n if (variant === 'floating' || isMobile) return;\n\n if (lastSelectorRef.current !== selectors) {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n\n const candidates = Array.from(document.querySelectorAll(selectors));\n const nextTarget: HTMLElement | null =\n (candidates[0] as HTMLElement) || document.body;\n targetRef.current = nextTarget;\n lastSelectorRef.current = selectors;\n\n if (targetRef.current) {\n targetRef.current.style.transition = `margin-${side} 280ms cubic-bezier(0.22, 1, 0.36, 1)`;\n }\n }\n\n const target = targetRef.current;\n if (!target) return;\n\n const offset = isOpen ? expectedWidth : '0px';\n\n if (side === 'left') {\n target.style.marginLeft = offset;\n } else {\n target.style.marginRight = offset;\n }\n }, [isOpen, expectedWidth, variant, selectors, side, isMobile]);\n\n useLayoutEffect(() => {\n return (): void => {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n };\n }, [side]);\n}\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport { useEffect } from 'react';\n\ntype UseSidepanelKeyboardEventsProps = {\n onClose: () => void;\n onOpen: () => void;\n isOpen: boolean;\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\nexport function useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n}: UseSidepanelKeyboardEventsProps): void {\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent): void {\n if (isOpen && e.code === 'Escape') {\n onClose();\n return;\n }\n\n const cmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n\n if (!cmdIEnabled) return;\n\n const isCmdI = e.key?.toLowerCase() === 'i' && (e.metaKey || e.ctrlKey);\n\n if (isCmdI) {\n e.preventDefault();\n\n if (isOpen) {\n onClose();\n } else {\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [isOpen, onClose, onOpen, keyboardShortcuts]);\n}\n","import React from 'react';\n\nconst BASE_WIDTH = 360;\nconst EXPANDED_WIDTH = 580;\n\ntype UseSidepanelWidthProps = {\n isExpanded: boolean;\n width?: number | string;\n expandedWidth?: number | string;\n};\n\nexport const useSidepanelWidth = ({\n isExpanded,\n width,\n expandedWidth,\n}: UseSidepanelWidthProps): string => {\n const baseWidth = React.useMemo(() => {\n return typeof width === 'number'\n ? `${width}px`\n : (width ?? `${BASE_WIDTH}px`);\n }, [width]);\n\n const resolvedExpandedWidth = React.useMemo(() => {\n return typeof expandedWidth === 'number'\n ? `${expandedWidth}px`\n : (expandedWidth ?? `${EXPANDED_WIDTH}px`);\n }, [expandedWidth]);\n\n const expectedWidth = isExpanded ? resolvedExpandedWidth : baseWidth;\n\n return expectedWidth;\n};\n","import type { SidepanelShortcuts, InitialAskAiMessage } from '@docsearch/core';\nimport React, { useCallback } from 'react';\nimport type { JSX } from 'react';\n\nimport { AlgoliaLogo, type AlgoliaLogoTranslations } from '../AlgoliaLogo';\nimport type {\n DocSearchSidepanelProps,\n SidepanelSearchParameters,\n} from '../Sidepanel';\nimport type { StoredAskAiState, SuggestedQuestionHit } from '../types';\nimport { useAskAi } from '../useAskAi';\nimport { useIsMobile } from '../useIsMobile';\nimport { useSearchClient } from '../useSearchClient';\nimport { useSuggestedQuestions } from '../useSuggestedQuestions';\nimport { EMPTY_TOOLS, buildDummyAskAiHit } from '../utils/ai';\n\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { ConversationScreenTranslations } from './ConversationScreen';\nimport { ConversationScreen } from './ConversationScreen';\nimport type { NewConversationScreenTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport { PromptForm, type PromptFormTranslations } from './PromptForm';\nimport { setSidepanelSearchClient } from './setSidepanelSearchClient';\nimport type { HeaderTranslations } from './SidepanelHeader';\nimport { SidepanelHeader } from './SidepanelHeader';\nimport type { PanelSide, PanelVariant, SidepanelState } from './types';\nimport { useManageSidepanelLayout } from './useManageSidepanelLayout';\nimport { useSidepanelKeyboardEvents } from './useSidepanelKeyboardEvents';\nimport { useSidepanelWidth } from './useSidepanelWidth';\n\n/**\n * Imperative handle exposed by the Sidepanel component for programmatic\n * control.\n */\nexport interface SidepanelRef {\n /** Opens the sidepanel. */\n open: () => void;\n /** Closes the sidepanel. */\n close: () => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isOpen: boolean;\n}\n\nexport type SidepanelTranslations = Partial<{\n /** Translation texts for the Sidepanel header. */\n header: HeaderTranslations;\n /** Translation texts for the prompt form. */\n promptForm: PromptFormTranslations;\n /** Translation texts for the conversation screen. */\n conversationScreen: ConversationScreenTranslations;\n /** Translation texts for the new conversation/starting screen. */\n newConversationScreen: NewConversationScreenTranslations;\n /** Translation text for the Algolia logo. */\n logo: AlgoliaLogoTranslations;\n}>;\n\nexport type SidepanelProps = Pick<\n DocSearchSidepanelProps,\n 'indices' | 'memory' | 'tools'\n> & {\n /**\n * Variant of the Sidepanel positioning.\n *\n * - `inline` pushes page content when opened\n * - `floating` is positioned above all other content on page.\n *\n * @default 'floating'\n */\n variant?: PanelVariant;\n /**\n * Side of the page which the panel will originate from.\n *\n * @default 'right'\n */\n side?: PanelSide;\n /**\n * The selector of the element to push when Sidepanel opens with `inline`\n * variant.\n *\n * @default `'#root, main, .app, body'`\n */\n pushSelector?: string;\n /**\n * Width of the Sidepanel (px or any CSS width).\n *\n * @default `360px`\n */\n width?: number | string;\n /**\n * Width when expanded (px or any CSS width).\n *\n * @default `580px`\n */\n expandedWidth?: number | string;\n /**\n * The container element where the panel should be portaled to.\n *\n * @default `document.body`\n */\n portalContainer?: DocumentFragment | Element | null;\n /**\n * Enables displaying suggested questions on new conversation screen.\n *\n * @default false\n */\n suggestedQuestions?: boolean;\n /** Translations specific to the Sidepanel panel. */\n translations?: SidepanelTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = Omit<\n DocSearchSidepanelProps,\n 'button' | 'indices' | 'memory' | 'panel' | 'tools'\n> &\n SidepanelProps &\n SidepanelSearchParameters & {\n isOpen?: boolean;\n onOpen: () => void;\n onClose: () => void;\n initialMessage?: InitialAskAiMessage;\n };\n\nfunction SidepanelInner(\n {\n isOpen = false,\n onOpen,\n onClose,\n assistantId,\n apiKey,\n appId,\n indexName,\n variant = 'floating',\n searchParameters,\n pushSelector,\n width,\n expandedWidth,\n suggestedQuestions: suggestedQuestionsEnabled = false,\n translations = {},\n keyboardShortcuts,\n side = 'right',\n initialMessage,\n tools = EMPTY_TOOLS,\n memory,\n indices,\n }: Props,\n ref: React.ForwardedRef<SidepanelRef>\n): JSX.Element {\n const [isExpanded, setIsExpanded] = React.useState(false);\n const [sidepanelState, setSidepanelState] =\n React.useState<SidepanelState>('new-conversation');\n const [stoppedStreaming, setStoppedStreaming] = React.useState(false);\n const sidepanelContainerRef = React.useRef<HTMLDivElement>(null);\n const promptInputRef = React.useRef<HTMLTextAreaElement>(null);\n const isMobile = useIsMobile();\n\n const expectedWidth = useSidepanelWidth({\n isExpanded,\n width,\n expandedWidth,\n });\n\n const selectors = React.useMemo(\n () => pushSelector ?? '#root, main, .app, body',\n [pushSelector]\n );\n\n const toggleIsExpanded = useCallback((): void => {\n setIsExpanded(!isExpanded);\n }, [isExpanded]);\n\n const searchClient = useSearchClient(appId, apiKey, setSidepanelSearchClient);\n\n const {\n chatId,\n status,\n sendMessage,\n stopAskAiStreaming,\n isStreaming,\n exchanges,\n conversations,\n messages,\n sendFeedback,\n askAiError,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n appId,\n indexName,\n assistantId,\n apiKey,\n searchParameters,\n tools,\n memory,\n indices,\n });\n\n const suggestedQuestions = useSuggestedQuestions({\n assistantId,\n suggestedQuestionsEnabled,\n searchClient,\n });\n\n const prevStatus = React.useRef(status);\n\n const handleSend = React.useCallback(\n (prompt: string): void => {\n setStoppedStreaming(false);\n\n sendMessage({ text: prompt });\n setSidepanelState('conversation');\n },\n [sendMessage]\n );\n\n const handleStartNewConversation = (): void => {\n startNewConversation();\n setSidepanelState('new-conversation');\n };\n\n const handleSelectQuestion = (question: SuggestedQuestionHit): void => {\n setStoppedStreaming(false);\n startNewConversation();\n sendMessage(\n { text: question.question },\n {\n body: {\n suggestedQuestionId: question.objectID,\n },\n }\n );\n setSidepanelState('conversation');\n };\n\n const handleStopStreaming = (): void => {\n setStoppedStreaming(true);\n stopAskAiStreaming();\n };\n\n const handleSelectConversation = React.useCallback(\n (conversation: StoredAskAiState): void => {\n if (conversation.messages) {\n restoreConversation(conversation.messages, conversation.chatId);\n } else if (conversation.query) {\n sendMessage({ text: conversation.query });\n }\n\n setSidepanelState('conversation');\n },\n [sendMessage, restoreConversation]\n );\n\n useManageSidepanelLayout({\n variant,\n expectedWidth,\n selectors,\n isOpen,\n side,\n });\n\n useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n });\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: onOpen,\n close: onClose,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isOpen;\n },\n }),\n [onOpen, onClose, isOpen]\n );\n\n React.useEffect(() => {\n if (prevStatus.current === 'streaming' && status === 'ready') {\n if (stoppedStreaming && 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\n prevStatus.current = status;\n }, [conversations, status, messages, stoppedStreaming, chatId]);\n\n React.useEffect(() => {\n function setFullViewportHeight(): void {\n if (sidepanelContainerRef.current) {\n const vh = window.innerHeight * 0.01;\n sidepanelContainerRef.current.style.setProperty('--sp-vh', `${vh}px`);\n }\n }\n\n setFullViewportHeight();\n\n window.addEventListener('resize', setFullViewportHeight);\n\n return (): void => {\n window.removeEventListener('resize', setFullViewportHeight);\n };\n }, []);\n\n React.useEffect(() => {\n if (!initialMessage) return;\n\n let selectedConversation: StoredAskAiState | undefined;\n\n if (initialMessage.messageId) {\n selectedConversation = conversations.getConversation?.(\n initialMessage.messageId\n );\n }\n\n if (selectedConversation) {\n handleSelectConversation(selectedConversation);\n } else {\n startNewConversation();\n sendMessage(\n {\n text: initialMessage.query,\n },\n initialMessage.suggestedQuestionId\n ? {\n body: {\n suggestedQuestionId: initialMessage.suggestedQuestionId,\n },\n }\n : {}\n );\n setSidepanelState('conversation');\n }\n }, [\n initialMessage,\n sendMessage,\n conversations,\n handleSelectConversation,\n startNewConversation,\n ]);\n\n // Autofocus the prompt input when the sidepanel opens and blur it when\n // it closes. Disabled on mobile because focusing the textarea triggers the\n // virtual keyboard which disrupts the layout — this is a known issue that\n // has not been resolved yet.\n React.useEffect(() => {\n if (isOpen && !isMobile) {\n promptInputRef.current?.focus();\n }\n\n if (!isOpen) {\n promptInputRef.current?.blur();\n }\n }, [isOpen, isMobile]);\n\n return (\n <div\n className={`DocSearch-Sidepanel-Container ${variant} side-${side}${isOpen ? ' is-open' : ''}${isExpanded ? ' is-expanded' : ''}`}\n style={\n {\n '--sp-width': expectedWidth,\n } as React.CSSProperties\n }\n role=\"dialog\"\n tabIndex={-1}\n ref={sidepanelContainerRef}\n >\n <aside\n id=\"docsearch-sidepanel\"\n className={`DocSearch-Sidepanel ${sidepanelState}`}\n >\n <SidepanelHeader\n sidepanelState={sidepanelState}\n exchanges={exchanges}\n setSidepanelState={setSidepanelState}\n hasConversations={conversations.getAll().length > 0}\n isStreaming={isStreaming}\n onNewConversation={handleStartNewConversation}\n onToggleExpanded={toggleIsExpanded}\n onClose={onClose}\n />\n <div className=\"DocSearch-Sidepanel-Content\">\n {sidepanelState === 'new-conversation' && (\n <NewConversationScreen\n suggestedQuestions={suggestedQuestions}\n translations={translations.newConversationScreen}\n onSelectQuestion={handleSelectQuestion}\n />\n )}\n {sidepanelState === 'conversation' && (\n <ConversationScreen\n exchanges={exchanges}\n status={status}\n conversations={conversations}\n handleFeedback={sendFeedback}\n translations={translations.conversationScreen}\n streamError={askAiError}\n memoryEnabled={memory?.enabled ?? false}\n tools={tools}\n onSelectPromptSuggestion={handleSend}\n />\n )}\n {sidepanelState === 'conversation-history' && (\n <ConversationHistoryScreen\n conversations={conversations}\n selectConversation={handleSelectConversation}\n />\n )}\n </div>\n <PromptForm\n ref={promptInputRef}\n exchanges={exchanges}\n isStreaming={isStreaming}\n translations={translations.promptForm}\n onSend={handleSend}\n onStopStreaming={handleStopStreaming}\n />\n <footer className=\"DocSearch-Sidepanel-Footer\">\n <span className=\"DocSearch-Logo DocSearch-Sidepanel--powered-by\">\n <AlgoliaLogo translations={translations.logo} />\n </span>\n </footer>\n </aside>\n </div>\n );\n}\n\nexport const Sidepanel = React.forwardRef(SidepanelInner);\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport React, { useEffect, useState } from 'react';\nimport type { JSX } from 'react';\n\nimport { SparklesIcon } from '../icons';\nimport { ACTION_KEY_APPLE, ACTION_KEY_DEFAULT, isAppleDevice } from '../utils';\n\nexport type SidepanelButtonTranslations = Partial<{\n /**\n * Text to be displayed when button has variant: `inline`.\n *\n * @default 'Ask AI'\n */\n buttonText: string;\n /**\n * Aria label text for the button.\n *\n * @default 'Ask AI'\n */\n buttonAriaLabel: string;\n}>;\n\nexport type ButtonVariant = 'floating' | 'inline';\n\nexport type SidepanelButtonProps = {\n /**\n * Variant of the button positioning and styling.\n *\n * - `inline` displays the button inline where rendered, with extra text\n * - `floating` displays the button floating in bottom right of screen with just\n * icon.\n *\n * @default 'floating'\n */\n variant?: ButtonVariant;\n /** Translations specific to the Sidepanel button. */\n translations?: SidepanelButtonTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = React.ComponentProps<'button'> & SidepanelButtonProps;\n\nexport const SidepanelButton = ({\n variant = 'floating',\n keyboardShortcuts,\n translations = {},\n ...props\n}: Props): JSX.Element => {\n const { buttonText = 'Ask AI', buttonAriaLabel = 'Ask AI' } = translations;\n const [key, setKey] = useState<\n typeof ACTION_KEY_APPLE | typeof ACTION_KEY_DEFAULT | null\n >(null);\n\n useEffect(() => {\n if (typeof navigator !== 'undefined') {\n isAppleDevice() ? setKey(ACTION_KEY_APPLE) : setKey(ACTION_KEY_DEFAULT);\n }\n }, []);\n\n const actionKeyAltText = key === ACTION_KEY_DEFAULT ? 'Control' : 'Meta';\n const isCtrlCmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n const shortcut = `${actionKeyAltText}+i`;\n\n return (\n <button\n className={`DocSearch-SidepanelButton ${variant}`}\n type=\"button\"\n aria-label={\n isCtrlCmdIEnabled ? `${buttonAriaLabel} (${shortcut})` : buttonAriaLabel\n }\n aria-keyshortcuts={isCtrlCmdIEnabled ? shortcut : undefined}\n {...(variant === 'floating' ? { tabIndex: -1 } : {})}\n {...props}\n >\n <SparklesIcon />\n {variant !== 'floating' && buttonText}\n </button>\n );\n};\n","import { DocSearch, useDocSearch } from '@docsearch/core';\nimport type {\n DocSearchCallbacks,\n DocSearchRef,\n DocSearchTheme,\n SidepanelShortcuts,\n} from '@docsearch/core';\nimport type { JSX } from 'react';\nimport React from 'react';\nimport { createPortal } from 'react-dom';\n\nimport type {\n AgentStudioIndices,\n AgentStudioSearchParameters,\n Memory,\n} from './DocSearchAI';\nimport type {\n SidepanelButtonProps,\n SidepanelProps as SidepanelPanelProps,\n} from './Sidepanel/index';\nimport { SidepanelButton, Sidepanel } from './Sidepanel/index';\nimport type { ToolCalls } from './types/AskiAi';\n\nexport type { DocSearchRef, DocSearchCallbacks } from '@docsearch/core';\n\nexport type SidepanelSearchParameters = {\n /**\n * The search parameters to use for the ask AI feature. Keyed by the index\n * name.\n *\n * @example\n * {\n * \"INDEX_NAME\": { distinct: false }\n * }\n */\n searchParameters?: AgentStudioSearchParameters;\n};\n\nexport type DocSearchSidepanelProps = DocSearchCallbacks & {\n /** The assistant ID to use for the ask AI feature. */\n assistantId: string;\n /** Public api key with search permissions for the index. */\n apiKey: string;\n /** Algolia application id used by the search client. */\n appId: string;\n /**\n * The index name to use for the ask AI feature. Your assistant will search\n * this index for relevant documents.\n */\n indexName: string;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n /**\n * Theme overrides applied to the Sidepanel button and panel.\n *\n * @default 'light'\n */\n theme?: DocSearchTheme;\n /** Props specific to the Sidepanel button. */\n button?: Omit<SidepanelButtonProps, 'keyboardShortcuts'>;\n /** Props specific to the Sidepanel panel. */\n panel?: Omit<SidepanelPanelProps, 'keyboardShortcuts'>;\n /**\n * Use custom tools driven by Agent Studio.\n *\n * For best performance, memoize this object with `useMemo` or define it\n * outside the component. Inline object literals will be recreated every\n * render but will not affect correctness.\n */\n tools?: ToolCalls;\n /**\n * Configuration for the Agent Studio memory feature.\n *\n * @example\n * { enabled: true, userToken: '{{SERVER_GENERATED_JWT_TOKEN}}' }\n *\n * @see https://www.algolia.com/doc/guides/algolia-ai/agent-studio/how-to/memory/overview\n */\n memory?: Memory;\n /** List of dynamic indices for the Agent Studio search tool to use. */\n indices?: AgentStudioIndices[];\n};\n\ntype SidepanelProps = DocSearchSidepanelProps & SidepanelSearchParameters;\n\nfunction DocSearchSidepanelComponent(\n {\n keyboardShortcuts,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: SidepanelProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n return (\n <DocSearch\n keyboardShortcuts={keyboardShortcuts}\n theme={theme}\n ref={ref}\n onReady={onReady}\n onOpen={onOpen}\n onClose={onClose}\n onSidepanelOpen={onSidepanelOpen}\n onSidepanelClose={onSidepanelClose}\n >\n <DocSearchSidepanelComp {...props} />\n </DocSearch>\n );\n}\n\nexport const DocSearchSidepanel = React.forwardRef(DocSearchSidepanelComponent);\n\nfunction DocSearchSidepanelComp({\n button: buttonProps = {},\n panel: { portalContainer, ...panelProps } = {},\n ...rootProps\n}: DocSearchSidepanelProps): JSX.Element {\n const {\n docsearchState,\n setDocsearchState,\n keyboardShortcuts,\n registerView,\n initialAskAiMessage,\n } = useDocSearch();\n\n const toggleSidepanelState = React.useCallback(() => {\n setDocsearchState(docsearchState === 'sidepanel' ? 'ready' : 'sidepanel');\n }, [docsearchState, setDocsearchState]);\n\n const handleClose = (): void => {\n setDocsearchState('ready');\n };\n\n const handleOpen = (): void => {\n setDocsearchState('sidepanel');\n };\n\n const containerElement = React.useMemo(\n () => portalContainer ?? document.body,\n [portalContainer]\n );\n\n React.useEffect(() => {\n registerView('sidepanel');\n }, [registerView]);\n\n const ButtonComp = React.useMemo(\n () => (\n <SidepanelButton\n keyboardShortcuts={keyboardShortcuts}\n onClick={toggleSidepanelState}\n {...buttonProps}\n />\n ),\n [keyboardShortcuts, toggleSidepanelState, buttonProps]\n );\n\n return (\n <>\n {buttonProps.variant === 'inline'\n ? ButtonComp\n : createPortal(ButtonComp, containerElement)}\n {createPortal(\n <Sidepanel\n initialMessage={initialAskAiMessage}\n isOpen={docsearchState === 'sidepanel'}\n onClose={handleClose}\n onOpen={handleOpen}\n {...rootProps}\n {...panelProps}\n keyboardShortcuts={keyboardShortcuts}\n />,\n containerElement\n )}\n </>\n );\n}\n\nexport * from './Sidepanel/index';\n"],"mappings":"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"}
1
+ {"version":3,"file":"sidepanel.js","names":[],"sources":["../../src/icons/SendIcon.tsx","../../src/icons/ExpandIcon.tsx","../../src/icons/FolderIcon.tsx","../../src/icons/EditIcon.tsx","../../src/useIsMobile.ts","../../src/Sidepanel/ConversationHistoryScreen.tsx","../../src/Sidepanel/AggregatedSearchBlock.tsx","../../src/Sidepanel/ConversationScreen.tsx","../../src/Sidepanel/NewConversationScreen.tsx","../../src/Sidepanel/PromptForm.tsx","../../src/Sidepanel/setSidepanelSearchClient.ts","../../src/Sidepanel/SidepanelHeader.tsx","../../src/Sidepanel/useManageSidepanelLayout.ts","../../src/Sidepanel/useSidepanelKeyboardEvents.ts","../../src/Sidepanel/useSidepanelWidth.ts","../../src/Sidepanel/Sidepanel.tsx","../../src/Sidepanel/SidepanelButton.tsx","../../src/Sidepanel.tsx"],"sourcesContent":["import type { JSX } from 'react';\nimport React from 'react';\n\nexport const SendIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\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=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n );\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nexport const ExpandIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 13 13\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M8 0.5C8 0.223858 8.22386 0 8.5 0H12.5C12.7761 0 13 0.223858 13 0.5V4.5C13 4.77614 12.7761 5 12.5 5C12.2239 5 12 4.77614 12 4.5V1.70711L8.18689 5.52022C7.99162 5.71548 7.67504 5.71548 7.47978 5.52022C7.28452 5.32496 7.28452 5.00838 7.47978 4.81311L11.2929 1H8.5C8.22386 1 8 0.776142 8 0.5ZM5.52022 7.47978C5.71548 7.67504 5.71548 7.99162 5.52022 8.18689L1.70711 12H4.5C4.77614 12 5 12.2239 5 12.5C5 12.7761 4.77614 13 4.5 13H0.5C0.223858 13 0 12.7761 0 12.5V8.5C0 8.22386 0.223858 8 0.5 8C0.776142 8 1 8.22386 1 8.5V11.2929L4.81311 7.47978C5.00838 7.28452 5.32496 7.28452 5.52022 7.47978Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const FolderIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\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=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const EditIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\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=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </svg>\n );\n};\n","import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */\nimport React from 'react';\nimport type { JSX } from 'react';\n\nimport { CloseIcon, RecentIcon } from '../icons';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { StoredAskAiState } from '../types';\n\ntype ConversationHistoryScreenProps = {\n conversations: StoredSearchPlugin<StoredAskAiState>;\n selectConversation: (conversation: StoredAskAiState) => void;\n};\n\nexport const ConversationHistoryScreen = ({\n conversations,\n selectConversation,\n}: ConversationHistoryScreenProps): JSX.Element => {\n const [items, setItems] = React.useState(() => conversations.getAll());\n\n const handleRemoveConversation = (item: StoredAskAiState): void => {\n conversations.remove(item);\n setItems(conversations.getAll());\n };\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationHistoryScreen\">\n <ul>\n {items.map((item) => (\n <li\n key={item.objectID}\n className=\"DocSearch-Sidepanel-RecentConversation\"\n >\n <a\n href={item.url}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n\n selectConversation(item);\n }}\n >\n <div className=\"DocSearch-Sidepanel-RecentConversation-container\">\n <div className=\"DocSearch-Sidepanel-RecentConversation-icon\">\n <RecentIcon />\n </div>\n\n <div className=\"DocSearch-Sidepanel-RecentConversation-content\">\n <span className=\"DocSearch-Sidepanel-RecentConversation-title\">\n {item.hierarchy.lvl1}\n </span>\n </div>\n\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n type=\"button\"\n title=\"Remove conversation from history\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleRemoveConversation(item);\n }}\n >\n <CloseIcon />\n </button>\n </div>\n </div>\n </a>\n </li>\n ))}\n </ul>\n </div>\n );\n};\n","import React, { Fragment } from 'react';\nimport type { JSX } from 'react';\n\nimport { SearchIcon } from '../icons';\n\ntype AggregatedSearchBlockProps = {\n queries: string[];\n};\n\nconst before = 'Searched for ';\nconst separator = ', ';\nconst lastSeparator = ' and ';\nconst after = '';\n\nexport function AggregatedSearchBlock({\n queries,\n}: AggregatedSearchBlockProps): JSX.Element {\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 className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\">\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 type { JSX } from 'react';\nimport React, { memo, useMemo } from 'react';\n\nimport { type Exchange } from '../AskAiScreen';\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 } from '../icons';\nimport { MemoizedMarkdown } from '../MemoizedMarkdown';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { OnAskAiFeedback, StoredAskAiState } from '../types';\nimport { type AIMessage, type ToolCalls } from '../types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n EMPTY_TOOLS,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from '../utils/ai';\nimport { groupConsecutiveToolResults } from '../utils/groupConsecutiveToolResults';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\n\nexport type ConversationScreenTranslations = Partial<\n ToolCallTranslations & {\n /** Text shown as an LLM disclaimer. */\n conversationDisclaimer: string;\n /** Text shown while assistant is reasoning. */\n reasoningText: string;\n /** Text show while assistant is thinking. */\n thinkingText: string;\n /** Text shown describing a singular related source. */\n relatedSourcesText: string;\n /** Text shown describing multiple related sources. */\n relatedSourcesTextPlural: string;\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Text shown for copy button on code snippets. */\n copyButtonText: string;\n /** Message shown after clicking copy. */\n copyButtonCopiedText: string;\n /** Title for thumbs up feedback icon. */\n likeButtonTitle: string;\n /** Title for thumbs down feedback icon. */\n dislikeButtonTitle: string;\n /** Message displayed after feedback action. */\n thanksForFeedbackText: string;\n /** Title shown at the top of the negative feedback note panel. */\n feedbackPanelTitle: string;\n /** Placeholder for the negative feedback details textarea. */\n feedbackDetailsPlaceholder: string;\n /** Disclaimer shown inside the negative feedback note panel. */\n feedbackDisclaimerText: string;\n /** Submit button text for the negative feedback note panel. */\n feedbackSubmitButtonText: string;\n /** Accessible title for the negative feedback note panel close button. */\n feedbackCloseButtonTitle: string;\n /** Reason chip labels for the negative feedback note panel. */\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText: string;\n suggestedPromptsTitleText: string;\n }\n>;\n\nexport type ConversationScreenProps = {\n exchanges: Exchange[];\n conversations: StoredSearchPlugin<StoredAskAiState>;\n translations?: ConversationScreenTranslations;\n status: UseChatHelpers<AIMessage>['status'];\n handleFeedback?: OnAskAiFeedback;\n streamError?: Error;\n memoryEnabled?: boolean;\n tools?: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\ntype ConversationnExchangeProps = {\n exchange: Exchange;\n isLastExchange: boolean;\n status: ConversationScreenProps['status'];\n conversations: ConversationScreenProps['conversations'];\n translations?: ConversationScreenTranslations;\n onFeedback?: ConversationScreenProps['handleFeedback'];\n streamError?: ConversationScreenProps['streamError'];\n memoryEnabled?: boolean;\n tools: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\nconst ConversationExchange = React.forwardRef<\n HTMLDivElement,\n ConversationnExchangeProps\n>(\n (\n {\n exchange,\n translations = {},\n isLastExchange,\n conversations,\n onFeedback,\n status,\n streamError,\n memoryEnabled,\n tools,\n onSelectPromptSuggestion,\n },\n conversationRef\n ): JSX.Element => {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n reasoningText = 'Reasoning...',\n thinkingText = 'Thinking...',\n searchingText = 'Searching...',\n relatedSourcesText,\n relatedSourcesTextPlural,\n stoppedStreamingText = 'You stopped this response',\n preToolCallText = 'Searching...',\n toolCallResultText = 'Searched for',\n copyButtonText = 'Copy',\n copyButtonCopiedText = 'Copied!',\n errorTitleText = 'Chat error',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const assistantParts = useMemo(\n () => groupConsecutiveToolResults(assistantMessage?.parts || []),\n [assistantMessage]\n );\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n const suggestedPrompts = React.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 const isThinking =\n ['submitted', 'streaming'].includes(status) &&\n !assistantParts.some((part) => part.type !== 'step-start');\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange && status === 'ready' && Boolean(assistantMessage)));\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div\n className=\"DocSearch-AskAiScreen-Response-Container\"\n ref={conversationRef}\n >\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 {status === 'error' && streamError && isLastExchange && (\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={streamError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n\n {assistantParts.map((part, idx) => {\n const index = idx;\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\">{reasoningText}</span>\n </div>\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock key={index} queries={part.queries} />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n part={part}\n translations={{\n preToolCallText,\n searchingText,\n toolCallResultText,\n savedMemoryToolResultText,\n memoryToolResultText,\n }}\n tools={tools}\n memoryEnabled={memoryEnabled}\n />\n );\n }\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={false}\n />\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n return null;\n })}\n\n {isThinking && isLastExchange && assistantParts.length === 0 && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"DocSearch-shimmer\">{thinkingText}</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 </div>\n\n {wasStopped && (\n <p className=\"DocSearch-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n pluralTitleText={relatedSourcesTextPlural}\n />\n <FeedbackActions\n isSidepanel={true}\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {suggestedPrompts.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={suggestedPrompts}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n }\n);\n\nexport const ConversationScreen = memo(\n ({\n exchanges,\n translations = {},\n handleFeedback,\n tools = EMPTY_TOOLS,\n status,\n conversations,\n streamError,\n memoryEnabled,\n onSelectPromptSuggestion,\n }: ConversationScreenProps): JSX.Element => {\n const {\n conversationDisclaimer = 'Answers are generated with AI which can make mistakes. Verify responses.',\n } = translations;\n\n const mostRecentExchangeRef = React.useRef<HTMLDivElement>(null);\n const totalExchanges = exchanges.length;\n\n // Only scroll the most recent exchange into view when needed\n React.useEffect(() => {\n if (mostRecentExchangeRef.current) {\n mostRecentExchangeRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [totalExchanges]);\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationScreen\">\n <p className=\"DocSearch-Sidepanel-ConversationScreen-disclaimer\">\n {conversationDisclaimer}\n </p>\n\n {exchanges.slice().map((exchange, idx) => {\n const isLastExchange = idx === exchanges.length - 1;\n return (\n <ConversationExchange\n key={exchange.id}\n exchange={exchange}\n translations={translations}\n isLastExchange={isLastExchange}\n ref={isLastExchange ? mostRecentExchangeRef : null}\n tools={tools}\n status={status}\n conversations={conversations}\n streamError={streamError}\n memoryEnabled={memoryEnabled}\n onFeedback={handleFeedback}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n );\n })}\n </div>\n );\n }\n);\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { SuggestedQuestionHit } from '../types';\n\nexport type NewConversationScreenTranslations = Partial<{\n /** Title to be shown on the new conversation/starting screen. */\n titleText: string;\n /** Introduction text displayed on the new conversation/starting screen. */\n introductionText: string;\n}>;\n\ntype NewConversationScreenProps = {\n suggestedQuestions: SuggestedQuestionHit[];\n onSelectQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationScreenTranslations;\n};\n\nexport const NewConversationScreen = ({\n suggestedQuestions,\n onSelectQuestion,\n translations = {},\n}: NewConversationScreenProps): JSX.Element => {\n const {\n titleText = 'How can I help you today?',\n introductionText = '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-Sidepanel-NewConversationScreen\">\n <h4 className=\"DocSearch-Sidepanel-Screen--title\">{titleText}</h4>\n <p className=\"DocSearch-Sidepanel-Screen--introduction\">\n {introductionText}\n </p>\n\n <div className=\"DocSearch-Sidepanel-List\">\n {suggestedQuestions.map((q) => (\n <button\n key={q.objectID}\n type=\"button\"\n className=\"DocSearch-Sidepanel-SuggestedQuestion\"\n title=\"View conversation\"\n onClick={() => {\n onSelectQuestion(q);\n }}\n >\n <span>{q.question}</span>\n </button>\n ))}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport { SendIcon, StopIcon } from '../icons';\nimport { useIsMobile } from '../useIsMobile';\n\nexport type PromptFormTranslations = Partial<{\n /** Initial placeholder for the prompt input. */\n promptPlaceholderText: string;\n /** Placeholder text for wile a conversation is streaming. */\n promptAnsweringText: string;\n /** Placeholder text for after a question has already been asked. */\n promptAskAnotherQuestionText: string;\n /** Disclaimer text displayed beneath the prompt form. */\n promptDisclaimerText: string;\n promptLabelText: string;\n promptAriaLabelText: string;\n}>;\n\ntype Props = {\n exchanges: Exchange[];\n isStreaming: boolean;\n translations?: PromptFormTranslations;\n onSend: (prompt: string) => void;\n onStopStreaming: () => void;\n};\n\nconst MAX_PROMPT_ROWS = 8;\n\nexport const PromptForm = React.forwardRef<HTMLTextAreaElement, Props>(\n (\n { exchanges, isStreaming, translations = {}, onSend, onStopStreaming },\n ref\n ): JSX.Element => {\n const isMobile = useIsMobile();\n const [userPrompt, setUserPrompt] = React.useState('');\n const promptRef = React.useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(\n ref,\n () => promptRef.current as HTMLTextAreaElement\n );\n\n const {\n promptPlaceholderText = 'Ask a question',\n promptAnsweringText = 'Answering...',\n promptAskAnotherQuestionText = 'Ask another question',\n promptDisclaimerText = 'Answers are generated with AI which can make mistakes.',\n promptLabelText = 'Press Enter to send, or Shift and Enter for new line.',\n promptAriaLabelText = 'Prompt input',\n } = translations;\n\n const managePromptHeight = (): void => {\n if (!promptRef.current) return;\n\n const textArea = promptRef.current;\n const styles = getComputedStyle(textArea);\n\n const lineHeight = parseFloat(styles.lineHeight);\n const paddingTop = parseFloat(styles.paddingTop);\n const paddingBottom = parseFloat(styles.paddingBottom);\n const padding = paddingTop + paddingBottom;\n\n textArea.style.height = 'auto';\n\n const fullHeight = textArea.scrollHeight;\n const maxHeight = MAX_PROMPT_ROWS * lineHeight + padding;\n\n textArea.style.overflowY = fullHeight > maxHeight ? 'auto' : 'hidden';\n textArea.style.height = `${Math.min(fullHeight, maxHeight)}px`;\n };\n\n const handleSend = (): void => {\n if (isStreaming) return;\n\n const prompt = userPrompt.trim();\n\n if (prompt === '') return;\n\n onSend(prompt);\n\n setUserPrompt('');\n\n requestAnimationFrame(() => {\n promptRef.current?.focus();\n\n managePromptHeight();\n });\n };\n\n const handleKeyDown = (\n e: React.KeyboardEvent<HTMLTextAreaElement>\n ): void => {\n // Allow Enter to work normally (new line) when streaming\n if (isStreaming) return;\n\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n\n handleSend();\n }\n };\n\n React.useLayoutEffect(() => {\n managePromptHeight();\n }, [isMobile]);\n\n let promptPlaceholder = promptPlaceholderText;\n\n if (isStreaming) {\n promptPlaceholder = promptAnsweringText;\n } else if (exchanges.length > 0) {\n promptPlaceholder = promptAskAnotherQuestionText;\n }\n\n return (\n <div className=\"DocSearch-Sidepanel-Prompt\">\n <form\n className=\"DocSearch-Sidepanel-Prompt--form\"\n onSubmit={(e) => {\n e.preventDefault();\n\n if (isStreaming) return;\n\n handleSend();\n }}\n >\n <textarea\n ref={promptRef}\n placeholder={promptPlaceholder}\n className=\"DocSearch-Sidepanel-Prompt--textarea\"\n value={userPrompt}\n aria-label={promptAriaLabelText}\n aria-labelledby=\"prompt-label\"\n autoComplete=\"off\"\n translate=\"no\"\n rows={isMobile ? 1 : 2}\n onKeyDown={handleKeyDown}\n onInput={managePromptHeight}\n onChange={(e) => setUserPrompt(e.target.value)}\n />\n <span id=\"prompt-label\" className=\"sr-only\">\n {promptLabelText}\n </span>\n <div className=\"DocSearch-Sidepanel-Prompt--actions\">\n {isStreaming && (\n <button\n type=\"button\"\n title=\"Stop streaming\"\n className=\"DocSearch-Sidepanel-Prompt--stop\"\n onClick={onStopStreaming}\n >\n <StopIcon />\n </button>\n )}\n {!isStreaming && (\n <button\n type=\"submit\"\n aria-label=\"Send question\"\n title=\"Send question\"\n className=\"DocSearch-Sidepanel-Prompt--submit\"\n aria-disabled={userPrompt === ''}\n >\n <SendIcon />\n </button>\n )}\n </div>\n </form>\n <p className=\"DocSearch-Sidepanel-Prompt--disclaimer\">\n {promptDisclaimerText}\n </p>\n </div>\n );\n }\n);\n","import type { DocSearchTransformClient } from '..';\nimport { version } from '../version';\n\nexport const setSidepanelSearchClient = (\n client: DocSearchTransformClient\n): DocSearchTransformClient => {\n if (\n /docsearch-sidepanel.js \\(.*\\)/.test(\n client.transporter.algoliaAgent.value\n ) === false\n ) {\n client.addAlgoliaAgent('docsearch-sidepanel', version);\n }\n\n return client;\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport {\n CloseIcon,\n ConversationHistoryIcon,\n EditIcon,\n ExpandIcon,\n FolderIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n SparklesIcon,\n} from '../icons';\nimport { BackIcon } from '../icons/BackIcon';\nimport { Menu } from '../Menu';\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { SidepanelState } from './types';\n\ntype BackButtonProps = {\n mobile?: boolean;\n onBack: () => void;\n disabled?: boolean;\n};\n\nconst BackButton = ({\n onBack,\n mobile = false,\n disabled = false,\n}: BackButtonProps): JSX.Element => {\n return (\n <button\n type=\"button\"\n className={`DocSearch-Action DocSearch-Sidepanel-Action-back${mobile ? ' mobile' : ''}`}\n title=\"Go back to previous screen\"\n aria-disabled={disabled}\n onClick={disabled ? undefined : onBack}\n >\n <BackIcon />\n </button>\n );\n};\n\nexport type HeaderTranslations = Partial<{\n /** The main title text shown on the header. */\n title: string;\n /** The title text shown on the conversation history screen. */\n conversationHistoryTitle: string;\n /** The text shown on the start a conversation button. */\n newConversationText: string;\n /** The text shown on the view conversation history button. */\n viewConversationHistoryText: string;\n}>;\n\ntype SidepanelHeaderProps = {\n sidepanelState: SidepanelState;\n exchanges: Exchange[];\n setSidepanelState: (state: SidepanelState) => void;\n onNewConversation: () => void;\n onToggleExpanded: () => void;\n onClose: () => void;\n translations?: HeaderTranslations;\n hasConversations: boolean;\n isStreaming: boolean;\n};\n\nexport const SidepanelHeader = React.memo(\n ({\n sidepanelState,\n exchanges,\n setSidepanelState,\n onNewConversation,\n onToggleExpanded,\n onClose,\n translations = {},\n hasConversations,\n isStreaming,\n }: SidepanelHeaderProps): JSX.Element => {\n const {\n title = 'Ask AI',\n conversationHistoryTitle = 'My conversation history',\n newConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n } = translations;\n\n const isMobile = useIsMobile();\n\n const goToConversationHistory = (): void => {\n setSidepanelState('conversation-history');\n };\n\n const onBack = React.useCallback((): void => {\n if (exchanges.length > 0) {\n setSidepanelState('conversation');\n } else {\n setSidepanelState('new-conversation');\n }\n }, [exchanges, setSidepanelState]);\n\n const newConversationDisabled =\n sidepanelState === 'new-conversation' && exchanges.length < 1;\n\n let header = title;\n\n if (sidepanelState === 'conversation-history') {\n header = conversationHistoryTitle;\n }\n\n if (isMobile) {\n header = title;\n }\n\n return (\n <header className=\"DocSearch-Sidepanel-Header\">\n <div className=\"DocSearch-Sidepanel-Header--left\">\n <BackButton mobile={true} disabled={isStreaming} onBack={onBack} />\n\n {sidepanelState === 'conversation-history' && (\n <div className=\"DocSearch-Divider\" />\n )}\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={newConversationText}\n onClick={onNewConversation}\n >\n <EditIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={viewConversationHistoryText}\n onClick={goToConversationHistory}\n >\n <FolderIcon />\n </button>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--center\">\n <BackButton disabled={isStreaming} onBack={onBack} />\n <SparklesIcon className=\"DocSearch-Sidepanel-Header-TitleIcon\" />\n <h2 className=\"DocSearch-Sidepanel-Title\">{header}</h2>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--right\">\n {sidepanelState !== 'conversation-history' &&\n (!newConversationDisabled || hasConversations) && (\n <Menu>\n <Menu.Trigger\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-menu\"\n disabled={isStreaming}\n >\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n {!newConversationDisabled && (\n <Menu.Item onClick={onNewConversation}>\n <NewConversationIcon />\n {newConversationText}\n </Menu.Item>\n )}\n {hasConversations && (\n <Menu.Item onClick={goToConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n )}\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-expand\"\n title=\"Expand or collapse Sidepanel\"\n onClick={onToggleExpanded}\n >\n <ExpandIcon />\n </button>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-close\"\n title=\"Close Sidepanel\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n </div>\n </header>\n );\n }\n);\n","import { useLayoutEffect, useRef } from 'react';\n\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { PanelSide, PanelVariant } from './types';\n\ntype UseManageSidepanelLayoutProps = {\n variant: PanelVariant;\n side: PanelSide;\n selectors: string;\n isOpen: boolean;\n expectedWidth: string;\n};\n\nexport function useManageSidepanelLayout({\n variant,\n selectors,\n isOpen,\n expectedWidth,\n side,\n}: UseManageSidepanelLayoutProps): void {\n const targetRef = useRef<HTMLElement | null>(null);\n const lastSelectorRef = useRef<string | null>(null);\n const isMobile = useIsMobile();\n\n useLayoutEffect(() => {\n if (variant === 'floating' || isMobile) return;\n\n if (lastSelectorRef.current !== selectors) {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n\n const candidates = Array.from(document.querySelectorAll(selectors));\n const nextTarget: HTMLElement | null =\n (candidates[0] as HTMLElement) || document.body;\n targetRef.current = nextTarget;\n lastSelectorRef.current = selectors;\n\n if (targetRef.current) {\n targetRef.current.style.transition = `margin-${side} 280ms cubic-bezier(0.22, 1, 0.36, 1)`;\n }\n }\n\n const target = targetRef.current;\n if (!target) return;\n\n const offset = isOpen ? expectedWidth : '0px';\n\n if (side === 'left') {\n target.style.marginLeft = offset;\n } else {\n target.style.marginRight = offset;\n }\n }, [isOpen, expectedWidth, variant, selectors, side, isMobile]);\n\n useLayoutEffect(() => {\n return (): void => {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n };\n }, [side]);\n}\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport { useEffect } from 'react';\n\ntype UseSidepanelKeyboardEventsProps = {\n onClose: () => void;\n onOpen: () => void;\n isOpen: boolean;\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\nexport function useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n}: UseSidepanelKeyboardEventsProps): void {\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent): void {\n if (isOpen && e.code === 'Escape') {\n onClose();\n return;\n }\n\n const cmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n\n if (!cmdIEnabled) return;\n\n const isCmdI = e.key?.toLowerCase() === 'i' && (e.metaKey || e.ctrlKey);\n\n if (isCmdI) {\n e.preventDefault();\n\n if (isOpen) {\n onClose();\n } else {\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [isOpen, onClose, onOpen, keyboardShortcuts]);\n}\n","import React from 'react';\n\nconst BASE_WIDTH = 360;\nconst EXPANDED_WIDTH = 580;\n\ntype UseSidepanelWidthProps = {\n isExpanded: boolean;\n width?: number | string;\n expandedWidth?: number | string;\n};\n\nexport const useSidepanelWidth = ({\n isExpanded,\n width,\n expandedWidth,\n}: UseSidepanelWidthProps): string => {\n const baseWidth = React.useMemo(() => {\n return typeof width === 'number'\n ? `${width}px`\n : (width ?? `${BASE_WIDTH}px`);\n }, [width]);\n\n const resolvedExpandedWidth = React.useMemo(() => {\n return typeof expandedWidth === 'number'\n ? `${expandedWidth}px`\n : (expandedWidth ?? `${EXPANDED_WIDTH}px`);\n }, [expandedWidth]);\n\n const expectedWidth = isExpanded ? resolvedExpandedWidth : baseWidth;\n\n return expectedWidth;\n};\n","import type { SidepanelShortcuts, InitialAskAiMessage } from '@docsearch/core';\nimport React, { useCallback } from 'react';\nimport type { JSX } from 'react';\n\nimport { AlgoliaLogo, type AlgoliaLogoTranslations } from '../AlgoliaLogo';\nimport type {\n DocSearchSidepanelProps,\n SidepanelSearchParameters,\n} from '../Sidepanel';\nimport type { StoredAskAiState, SuggestedQuestionHit } from '../types';\nimport { useAskAi } from '../useAskAi';\nimport { useIsMobile } from '../useIsMobile';\nimport { useSearchClient } from '../useSearchClient';\nimport { useSuggestedQuestions } from '../useSuggestedQuestions';\nimport { EMPTY_TOOLS, buildDummyAskAiHit } from '../utils/ai';\n\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { ConversationScreenTranslations } from './ConversationScreen';\nimport { ConversationScreen } from './ConversationScreen';\nimport type { NewConversationScreenTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport { PromptForm, type PromptFormTranslations } from './PromptForm';\nimport { setSidepanelSearchClient } from './setSidepanelSearchClient';\nimport type { HeaderTranslations } from './SidepanelHeader';\nimport { SidepanelHeader } from './SidepanelHeader';\nimport type { PanelSide, PanelVariant, SidepanelState } from './types';\nimport { useManageSidepanelLayout } from './useManageSidepanelLayout';\nimport { useSidepanelKeyboardEvents } from './useSidepanelKeyboardEvents';\nimport { useSidepanelWidth } from './useSidepanelWidth';\n\n/**\n * Imperative handle exposed by the Sidepanel component for programmatic\n * control.\n */\nexport interface SidepanelRef {\n /** Opens the sidepanel. */\n open: () => void;\n /** Closes the sidepanel. */\n close: () => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isOpen: boolean;\n}\n\nexport type SidepanelTranslations = Partial<{\n /** Translation texts for the Sidepanel header. */\n header: HeaderTranslations;\n /** Translation texts for the prompt form. */\n promptForm: PromptFormTranslations;\n /** Translation texts for the conversation screen. */\n conversationScreen: ConversationScreenTranslations;\n /** Translation texts for the new conversation/starting screen. */\n newConversationScreen: NewConversationScreenTranslations;\n /** Translation text for the Algolia logo. */\n logo: AlgoliaLogoTranslations;\n}>;\n\nexport type SidepanelProps = Pick<\n DocSearchSidepanelProps,\n 'indices' | 'memory' | 'tools'\n> & {\n /**\n * Variant of the Sidepanel positioning.\n *\n * - `inline` pushes page content when opened\n * - `floating` is positioned above all other content on page.\n *\n * @default 'floating'\n */\n variant?: PanelVariant;\n /**\n * Side of the page which the panel will originate from.\n *\n * @default 'right'\n */\n side?: PanelSide;\n /**\n * The selector of the element to push when Sidepanel opens with `inline`\n * variant.\n *\n * @default `'#root, main, .app, body'`\n */\n pushSelector?: string;\n /**\n * Width of the Sidepanel (px or any CSS width).\n *\n * @default `360px`\n */\n width?: number | string;\n /**\n * Width when expanded (px or any CSS width).\n *\n * @default `580px`\n */\n expandedWidth?: number | string;\n /**\n * The container element where the panel should be portaled to.\n *\n * @default `document.body`\n */\n portalContainer?: DocumentFragment | Element | null;\n /**\n * Enables displaying suggested questions on new conversation screen.\n *\n * @default false\n */\n suggestedQuestions?: boolean;\n /** Translations specific to the Sidepanel panel. */\n translations?: SidepanelTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = Omit<\n DocSearchSidepanelProps,\n 'button' | 'indices' | 'memory' | 'panel' | 'tools'\n> &\n SidepanelProps &\n SidepanelSearchParameters & {\n isOpen?: boolean;\n onOpen: () => void;\n onClose: () => void;\n initialMessage?: InitialAskAiMessage;\n };\n\nfunction SidepanelInner(\n {\n isOpen = false,\n onOpen,\n onClose,\n agentId,\n apiKey,\n appId,\n variant = 'floating',\n searchParameters,\n pushSelector,\n width,\n expandedWidth,\n suggestedQuestions: suggestedQuestionsEnabled = false,\n translations = {},\n keyboardShortcuts,\n side = 'right',\n initialMessage,\n tools = EMPTY_TOOLS,\n memory,\n indices,\n }: Props,\n ref: React.ForwardedRef<SidepanelRef>\n): JSX.Element {\n const [isExpanded, setIsExpanded] = React.useState(false);\n const [sidepanelState, setSidepanelState] =\n React.useState<SidepanelState>('new-conversation');\n const [stoppedStreaming, setStoppedStreaming] = React.useState(false);\n const sidepanelContainerRef = React.useRef<HTMLDivElement>(null);\n const promptInputRef = React.useRef<HTMLTextAreaElement>(null);\n const isMobile = useIsMobile();\n\n const expectedWidth = useSidepanelWidth({\n isExpanded,\n width,\n expandedWidth,\n });\n\n const selectors = React.useMemo(\n () => pushSelector ?? '#root, main, .app, body',\n [pushSelector]\n );\n\n const toggleIsExpanded = useCallback((): void => {\n setIsExpanded(!isExpanded);\n }, [isExpanded]);\n\n const searchClient = useSearchClient(appId, apiKey, setSidepanelSearchClient);\n\n const {\n chatId,\n status,\n sendMessage,\n stopAskAiStreaming,\n isStreaming,\n exchanges,\n conversations,\n messages,\n sendFeedback,\n askAiError,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n appId,\n agentId,\n apiKey,\n searchParameters,\n tools,\n memory,\n indices,\n });\n\n const suggestedQuestions = useSuggestedQuestions({\n agentId,\n suggestedQuestionsEnabled,\n searchClient,\n });\n\n const prevStatus = React.useRef(status);\n\n const handleSend = React.useCallback(\n (prompt: string): void => {\n setStoppedStreaming(false);\n\n sendMessage({ text: prompt });\n setSidepanelState('conversation');\n },\n [sendMessage]\n );\n\n const handleStartNewConversation = (): void => {\n startNewConversation();\n setSidepanelState('new-conversation');\n };\n\n const handleSelectQuestion = (question: SuggestedQuestionHit): void => {\n setStoppedStreaming(false);\n startNewConversation();\n sendMessage(\n { text: question.question },\n {\n body: {\n suggestedQuestionId: question.objectID,\n },\n }\n );\n setSidepanelState('conversation');\n };\n\n const handleStopStreaming = (): void => {\n setStoppedStreaming(true);\n stopAskAiStreaming();\n };\n\n const handleSelectConversation = React.useCallback(\n (conversation: StoredAskAiState): void => {\n if (conversation.messages) {\n restoreConversation(conversation.messages, conversation.chatId);\n } else if (conversation.query) {\n sendMessage({ text: conversation.query });\n }\n\n setSidepanelState('conversation');\n },\n [sendMessage, restoreConversation]\n );\n\n useManageSidepanelLayout({\n variant,\n expectedWidth,\n selectors,\n isOpen,\n side,\n });\n\n useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n });\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: onOpen,\n close: onClose,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isOpen;\n },\n }),\n [onOpen, onClose, isOpen]\n );\n\n React.useEffect(() => {\n if (prevStatus.current === 'streaming' && status === 'ready') {\n if (stoppedStreaming && 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\n prevStatus.current = status;\n }, [conversations, status, messages, stoppedStreaming, chatId]);\n\n React.useEffect(() => {\n function setFullViewportHeight(): void {\n if (sidepanelContainerRef.current) {\n const vh = window.innerHeight * 0.01;\n sidepanelContainerRef.current.style.setProperty('--sp-vh', `${vh}px`);\n }\n }\n\n setFullViewportHeight();\n\n window.addEventListener('resize', setFullViewportHeight);\n\n return (): void => {\n window.removeEventListener('resize', setFullViewportHeight);\n };\n }, []);\n\n React.useEffect(() => {\n if (!initialMessage) return;\n\n let selectedConversation: StoredAskAiState | undefined;\n\n if (initialMessage.messageId) {\n selectedConversation = conversations.getConversation?.(\n initialMessage.messageId\n );\n }\n\n if (selectedConversation) {\n handleSelectConversation(selectedConversation);\n } else {\n startNewConversation();\n sendMessage(\n {\n text: initialMessage.query,\n },\n initialMessage.suggestedQuestionId\n ? {\n body: {\n suggestedQuestionId: initialMessage.suggestedQuestionId,\n },\n }\n : {}\n );\n setSidepanelState('conversation');\n }\n }, [\n initialMessage,\n sendMessage,\n conversations,\n handleSelectConversation,\n startNewConversation,\n ]);\n\n // Autofocus the prompt input when the sidepanel opens and blur it when\n // it closes. Disabled on mobile because focusing the textarea triggers the\n // virtual keyboard which disrupts the layout — this is a known issue that\n // has not been resolved yet.\n React.useEffect(() => {\n if (isOpen && !isMobile) {\n promptInputRef.current?.focus();\n }\n\n if (!isOpen) {\n promptInputRef.current?.blur();\n }\n }, [isOpen, isMobile]);\n\n return (\n <div\n className={`DocSearch-Sidepanel-Container ${variant} side-${side}${isOpen ? ' is-open' : ''}${isExpanded ? ' is-expanded' : ''}`}\n style={\n {\n '--sp-width': expectedWidth,\n } as React.CSSProperties\n }\n role=\"dialog\"\n tabIndex={-1}\n ref={sidepanelContainerRef}\n >\n <aside\n id=\"docsearch-sidepanel\"\n className={`DocSearch-Sidepanel ${sidepanelState}`}\n >\n <SidepanelHeader\n sidepanelState={sidepanelState}\n exchanges={exchanges}\n setSidepanelState={setSidepanelState}\n hasConversations={conversations.getAll().length > 0}\n isStreaming={isStreaming}\n onNewConversation={handleStartNewConversation}\n onToggleExpanded={toggleIsExpanded}\n onClose={onClose}\n />\n <div className=\"DocSearch-Sidepanel-Content\">\n {sidepanelState === 'new-conversation' && (\n <NewConversationScreen\n suggestedQuestions={suggestedQuestions}\n translations={translations.newConversationScreen}\n onSelectQuestion={handleSelectQuestion}\n />\n )}\n {sidepanelState === 'conversation' && (\n <ConversationScreen\n exchanges={exchanges}\n status={status}\n conversations={conversations}\n handleFeedback={sendFeedback}\n translations={translations.conversationScreen}\n streamError={askAiError}\n memoryEnabled={memory?.enabled ?? false}\n tools={tools}\n onSelectPromptSuggestion={handleSend}\n />\n )}\n {sidepanelState === 'conversation-history' && (\n <ConversationHistoryScreen\n conversations={conversations}\n selectConversation={handleSelectConversation}\n />\n )}\n </div>\n <PromptForm\n ref={promptInputRef}\n exchanges={exchanges}\n isStreaming={isStreaming}\n translations={translations.promptForm}\n onSend={handleSend}\n onStopStreaming={handleStopStreaming}\n />\n <footer className=\"DocSearch-Sidepanel-Footer\">\n <span className=\"DocSearch-Logo DocSearch-Sidepanel--powered-by\">\n <AlgoliaLogo translations={translations.logo} />\n </span>\n </footer>\n </aside>\n </div>\n );\n}\n\nexport const Sidepanel = React.forwardRef(SidepanelInner);\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport React, { useEffect, useState } from 'react';\nimport type { JSX } from 'react';\n\nimport { SparklesIcon } from '../icons';\nimport { ACTION_KEY_APPLE, ACTION_KEY_DEFAULT, isAppleDevice } from '../utils';\n\nexport type SidepanelButtonTranslations = Partial<{\n /**\n * Text to be displayed when button has variant: `inline`.\n *\n * @default 'Ask AI'\n */\n buttonText: string;\n /**\n * Aria label text for the button.\n *\n * @default 'Ask AI'\n */\n buttonAriaLabel: string;\n}>;\n\nexport type ButtonVariant = 'floating' | 'inline';\n\nexport type SidepanelButtonProps = {\n /**\n * Variant of the button positioning and styling.\n *\n * - `inline` displays the button inline where rendered, with extra text\n * - `floating` displays the button floating in bottom right of screen with just\n * icon.\n *\n * @default 'floating'\n */\n variant?: ButtonVariant;\n /** Translations specific to the Sidepanel button. */\n translations?: SidepanelButtonTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = React.ComponentProps<'button'> & SidepanelButtonProps;\n\nexport const SidepanelButton = ({\n variant = 'floating',\n keyboardShortcuts,\n translations = {},\n ...props\n}: Props): JSX.Element => {\n const { buttonText = 'Ask AI', buttonAriaLabel = 'Ask AI' } = translations;\n const [key, setKey] = useState<\n typeof ACTION_KEY_APPLE | typeof ACTION_KEY_DEFAULT | null\n >(null);\n\n useEffect(() => {\n if (typeof navigator !== 'undefined') {\n isAppleDevice() ? setKey(ACTION_KEY_APPLE) : setKey(ACTION_KEY_DEFAULT);\n }\n }, []);\n\n const actionKeyAltText = key === ACTION_KEY_DEFAULT ? 'Control' : 'Meta';\n const isCtrlCmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n const shortcut = `${actionKeyAltText}+i`;\n\n return (\n <button\n className={`DocSearch-SidepanelButton ${variant}`}\n type=\"button\"\n aria-label={\n isCtrlCmdIEnabled ? `${buttonAriaLabel} (${shortcut})` : buttonAriaLabel\n }\n aria-keyshortcuts={isCtrlCmdIEnabled ? shortcut : undefined}\n {...(variant === 'floating' ? { tabIndex: -1 } : {})}\n {...props}\n >\n <SparklesIcon />\n {variant !== 'floating' && buttonText}\n </button>\n );\n};\n","import { DocSearch, useDocSearch } from '@docsearch/core';\nimport type {\n DocSearchCallbacks,\n DocSearchRef,\n DocSearchTheme,\n SidepanelShortcuts,\n} from '@docsearch/core';\nimport type { JSX } from 'react';\nimport React from 'react';\nimport { createPortal } from 'react-dom';\n\nimport type {\n AgentStudioIndices,\n AgentStudioSearchParameters,\n Memory,\n} from './DocSearchAI';\nimport type {\n SidepanelButtonProps,\n SidepanelProps as SidepanelPanelProps,\n} from './Sidepanel/index';\nimport { SidepanelButton, Sidepanel } from './Sidepanel/index';\nimport type { ToolCalls } from './types/AskiAi';\n\nexport type { DocSearchRef, DocSearchCallbacks } from '@docsearch/core';\n\nexport type SidepanelSearchParameters = {\n /**\n * The search parameters to use for the ask AI feature. Keyed by the index\n * name.\n *\n * @example\n * {\n * \"INDEX_NAME\": { distinct: false }\n * }\n */\n searchParameters?: AgentStudioSearchParameters;\n};\n\nexport type DocSearchSidepanelProps = DocSearchCallbacks & {\n /** The Agent Studio agent ID to use for Ask AI. */\n agentId: string;\n /** Search only API key. */\n apiKey: string;\n /** Algolia application ID that hosts the Agent Studio agent. */\n appId: string;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n /**\n * Theme overrides applied to the Sidepanel button and panel.\n *\n * @default 'light'\n */\n theme?: DocSearchTheme;\n /** Props specific to the Sidepanel button. */\n button?: Omit<SidepanelButtonProps, 'keyboardShortcuts'>;\n /** Props specific to the Sidepanel panel. */\n panel?: Omit<SidepanelPanelProps, 'keyboardShortcuts'>;\n /**\n * Use custom tools driven by Agent Studio.\n *\n * For best performance, memoize this object with `useMemo` or define it\n * outside the component. Inline object literals will be recreated every\n * render but will not affect correctness.\n */\n tools?: ToolCalls;\n /**\n * Configuration for the Agent Studio memory feature.\n *\n * @example\n * { enabled: true, userToken: '{{SERVER_GENERATED_JWT_TOKEN}}' }\n *\n * @see https://www.algolia.com/doc/guides/algolia-ai/agent-studio/how-to/memory/overview\n */\n memory?: Memory;\n /** List of dynamic indices for the Agent Studio search tool to use. */\n indices?: AgentStudioIndices[];\n};\n\ntype SidepanelProps = DocSearchSidepanelProps & SidepanelSearchParameters;\n\nfunction DocSearchSidepanelComponent(\n {\n keyboardShortcuts,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: SidepanelProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n return (\n <DocSearch\n appId={props.appId}\n apiKey={props.apiKey}\n keyboardShortcuts={keyboardShortcuts}\n theme={theme}\n ref={ref}\n onReady={onReady}\n onOpen={onOpen}\n onClose={onClose}\n onSidepanelOpen={onSidepanelOpen}\n onSidepanelClose={onSidepanelClose}\n >\n <DocSearchSidepanelComp {...props} />\n </DocSearch>\n );\n}\n\nexport const DocSearchSidepanel = React.forwardRef(DocSearchSidepanelComponent);\n\nfunction DocSearchSidepanelComp({\n button: buttonProps = {},\n panel: { portalContainer, ...panelProps } = {},\n ...rootProps\n}: DocSearchSidepanelProps): JSX.Element {\n const {\n docsearchState,\n setDocsearchState,\n keyboardShortcuts,\n registerView,\n initialAskAiMessage,\n appId,\n apiKey,\n } = useDocSearch();\n\n if (!appId || !apiKey) {\n throw new Error(\n '`Sidepanel` requires `appId` and `apiKey` props or values configured on the `DocSearch` provider.'\n );\n }\n\n const toggleSidepanelState = React.useCallback(() => {\n setDocsearchState(docsearchState === 'sidepanel' ? 'ready' : 'sidepanel');\n }, [docsearchState, setDocsearchState]);\n\n const handleClose = (): void => {\n setDocsearchState('ready');\n };\n\n const handleOpen = (): void => {\n setDocsearchState('sidepanel');\n };\n\n const containerElement = React.useMemo(\n () => portalContainer ?? document.body,\n [portalContainer]\n );\n\n React.useEffect(() => {\n registerView('sidepanel');\n }, [registerView]);\n\n const ButtonComp = React.useMemo(\n () => (\n <SidepanelButton\n keyboardShortcuts={keyboardShortcuts}\n onClick={toggleSidepanelState}\n {...buttonProps}\n />\n ),\n [keyboardShortcuts, toggleSidepanelState, buttonProps]\n );\n\n return (\n <>\n {buttonProps.variant === 'inline'\n ? ButtonComp\n : createPortal(ButtonComp, containerElement)}\n {createPortal(\n <Sidepanel\n initialMessage={initialAskAiMessage}\n isOpen={docsearchState === 'sidepanel'}\n onClose={handleClose}\n onOpen={handleOpen}\n {...rootProps}\n {...panelProps}\n keyboardShortcuts={keyboardShortcuts}\n />,\n containerElement\n )}\n </>\n );\n}\n\nexport * from './Sidepanel/index';\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import "./index-Dl8FMlR5.js";
1
+ import "./index-Bqqv4HmN.js";
2
2
  import React from "react";
3
3
  //#region src/types/KeyboardShortcuts.d.ts
4
4
  interface KeyboardShortcuts {
@@ -40,4 +40,4 @@ interface UseDocSearchKeyboardEventsProps {
40
40
  declare function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, isAskAiActive, onAskAiToggle, keyboardShortcuts }: UseDocSearchKeyboardEventsProps): void;
41
41
  //#endregion
42
42
  export { useDocSearchKeyboardEvents as n, KeyboardShortcuts as r, UseDocSearchKeyboardEventsProps as t };
43
- //# sourceMappingURL=useDocSearchKeyboardEvents-68G8dw6c.d.ts.map
43
+ //# sourceMappingURL=useDocSearchKeyboardEvents-u23fFhR9.d.ts.map
@@ -1,2 +1,2 @@
1
- import { n as useDocSearchKeyboardEvents, t as UseDocSearchKeyboardEventsProps } from "./useDocSearchKeyboardEvents-68G8dw6c.js";
1
+ import { n as useDocSearchKeyboardEvents, t as UseDocSearchKeyboardEventsProps } from "./useDocSearchKeyboardEvents-u23fFhR9.js";
2
2
  export { UseDocSearchKeyboardEventsProps, useDocSearchKeyboardEvents };