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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/esm/{AskAiScreenState-Bw2WIgv_.d.ts → AskAiScreenState-Sqbn60f2.d.ts} +2 -2
  2. package/dist/esm/{DocSearch-CVj6U-nI.d.ts → DocSearch-BVqxFxTw.d.ts} +18 -27
  3. package/dist/esm/{DocSearchAskAiModal-BczGFkvR.js → DocSearchAskAiModal-C_sH1j8Y.js} +9 -9
  4. package/dist/esm/{DocSearchAskAiModal-BczGFkvR.js.map → DocSearchAskAiModal-C_sH1j8Y.js.map} +1 -1
  5. package/dist/esm/{DocSearchAskAiModal-MF2py4NM.d.ts → DocSearchAskAiModal-DpB7pLCC.d.ts} +4 -4
  6. package/dist/esm/{DocSearchModal-D_tfhoN1.js → DocSearchModal-CITTG0fe.js} +10 -8
  7. package/dist/esm/DocSearchModal-CITTG0fe.js.map +1 -0
  8. package/dist/esm/askaiModal.d.ts +1 -1
  9. package/dist/esm/askaiModal.js +1 -1
  10. package/dist/esm/docsearchAi.d.ts +10 -102
  11. package/dist/esm/docsearchAi.js +1 -1
  12. package/dist/esm/docsearchAi.js.map +1 -1
  13. package/dist/esm/index.d.ts +4 -4
  14. package/dist/esm/index.js +2 -2
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/modal.d.ts +1 -1
  17. package/dist/esm/modal.js +1 -1
  18. package/dist/esm/{normalizeDocSearchIndexes-D8P3VEXa.js → normalizeDocSearchIndexes-ChnVvoVt.js} +16 -20
  19. package/dist/esm/normalizeDocSearchIndexes-ChnVvoVt.js.map +1 -0
  20. package/dist/esm/sidepanel.d.ts +19 -7
  21. package/dist/esm/sidepanel.js +1 -1
  22. package/dist/esm/sidepanel.js.map +1 -1
  23. package/dist/esm/useDocSearchKeyboardEvents.js +1 -1
  24. package/dist/esm/useDocSearchKeyboardEvents.js.map +1 -1
  25. package/dist/esm/useSearchClient-mIHVB6ga.js.map +1 -1
  26. package/dist/esm/{useSuggestedQuestions-Ds7H1JCr.js → useSuggestedQuestions-DwcUPOf_.js} +72 -25
  27. package/dist/esm/useSuggestedQuestions-DwcUPOf_.js.map +1 -0
  28. package/dist/esm/version.d.ts +1 -1
  29. package/dist/esm/version.js +1 -1
  30. package/dist/esm/version.js.map +1 -1
  31. package/dist/umd/index.js +33 -33
  32. package/dist/umd/index.js.map +1 -1
  33. package/package.json +4 -4
  34. package/dist/esm/DocSearchModal-D_tfhoN1.js.map +0 -1
  35. package/dist/esm/normalizeDocSearchIndexes-D8P3VEXa.js.map +0 -1
  36. package/dist/esm/useSuggestedQuestions-Ds7H1JCr.js.map +0 -1
@@ -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 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
+ {"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 { AgentStudioSearchParameters, Memory } 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 /**\n * Index names for the Agent Studio search tool on this request.\n *\n * Agent Studio expects names only. Put descriptions and tool defaults on the\n * agent configuration. Put per-index runtime overrides in\n * `searchParameters`.\n */\n indices?: string[];\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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"}
@@ -5,7 +5,7 @@ import React from "react";
5
5
  function isEditingContent(event) {
6
6
  const element = event.composedPath()[0];
7
7
  const tagName = element.tagName;
8
- return element.isContentEditable || tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA";
8
+ return element.isContentEditable || tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA" || tagName === "BUTTON";
9
9
  }
10
10
  function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, isAskAiActive, onAskAiToggle, keyboardShortcuts }) {
11
11
  const resolvedShortcuts = getKeyboardShortcuts(keyboardShortcuts);
@@ -1 +1 @@
1
- {"version":3,"file":"useDocSearchKeyboardEvents.js","names":[],"sources":["../../src/useDocSearchKeyboardEvents.ts"],"sourcesContent":["import React from 'react';\n\nimport { getKeyboardShortcuts } from './constants/keyboardShortcuts';\nimport type { KeyboardShortcuts } from './types';\n\nexport interface UseDocSearchKeyboardEventsProps {\n isOpen: boolean;\n onOpen: () => void;\n onClose: () => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n onInput?: (event: KeyboardEvent) => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n searchButtonRef?: React.RefObject<HTMLButtonElement | null>;\n isAskAiActive: boolean;\n onAskAiToggle: (toggle: boolean) => void;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nfunction isEditingContent(event: KeyboardEvent): boolean {\n const element = event.composedPath()[0] as HTMLElement;\n const tagName = element.tagName;\n\n return (\n element.isContentEditable ||\n tagName === 'INPUT' ||\n tagName === 'SELECT' ||\n tagName === 'TEXTAREA'\n );\n}\n\nexport function useDocSearchKeyboardEvents({\n isOpen,\n onOpen,\n onClose,\n isAskAiActive,\n onAskAiToggle,\n keyboardShortcuts,\n}: UseDocSearchKeyboardEventsProps): void {\n const resolvedShortcuts = getKeyboardShortcuts(keyboardShortcuts);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent): void {\n if (isOpen && event.code === 'Escape' && isAskAiActive) {\n onAskAiToggle(false);\n return;\n }\n\n const isCmdK =\n resolvedShortcuts['Ctrl/Cmd+K'] &&\n event.key?.toLowerCase() === 'k' &&\n (event.metaKey || event.ctrlKey);\n const isSlash = resolvedShortcuts['/'] && event.key === '/';\n\n if (\n (event.code === 'Escape' && isOpen) ||\n // The `Cmd+K` shortcut both opens and closes the modal.\n // We need to check for `event.key` because it can be `undefined` with\n // Chrome's autofill feature.\n // See https://github.com/paperjs/paper.js/issues/1398\n isCmdK ||\n // The `/` shortcut opens but doesn't close the modal because it's\n // a character.\n (!isEditingContent(event) && isSlash && !isOpen)\n ) {\n event.preventDefault();\n\n if (isOpen) {\n onClose();\n } else if (!document.body.classList.contains('DocSearch--active')) {\n // We check that no other DocSearch modal is showing before opening\n // another one.\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [\n isOpen,\n onOpen,\n onClose,\n isAskAiActive,\n onAskAiToggle,\n resolvedShortcuts,\n ]);\n}\n"],"mappings":";;;;AA0BA,SAAS,iBAAiB,OAA+B;CACvD,MAAM,UAAU,MAAM,aAAa,CAAC,CAAC;CACrC,MAAM,UAAU,QAAQ;CAExB,OACE,QAAQ,qBACR,YAAY,WACZ,YAAY,YACZ,YAAY;AAEhB;AAEA,SAAgB,2BAA2B,EACzC,QACA,QACA,SACA,eACA,eACA,qBACwC;CACxC,MAAM,oBAAoB,qBAAqB,iBAAiB;CAEhE,MAAM,gBAAgB;EACpB,SAAS,UAAU,OAA4B;;GAC7C,IAAI,UAAU,MAAM,SAAS,YAAY,eAAe;IACtD,cAAc,KAAK;IACnB;GACF;GAEA,MAAM,SACJ,kBAAkB,gCAClB,MAAM,6DAAK,YAAY,OAAM,QAC5B,MAAM,WAAW,MAAM;GAC1B,MAAM,UAAU,kBAAkB,QAAQ,MAAM,QAAQ;GAExD,IACG,MAAM,SAAS,YAAY,UAK5B,UAGC,CAAC,iBAAiB,KAAK,KAAK,WAAW,CAAC,QACzC;IACA,MAAM,eAAe;IAErB,IAAI,QACF,QAAQ;SACH,IAAI,CAAC,SAAS,KAAK,UAAU,SAAS,mBAAmB,GAG9D,OAAO;GAEX;EACF;EAEA,OAAO,iBAAiB,WAAW,SAAS;EAE5C,aAAmB;GACjB,OAAO,oBAAoB,WAAW,SAAS;EACjD;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"useDocSearchKeyboardEvents.js","names":[],"sources":["../../src/useDocSearchKeyboardEvents.ts"],"sourcesContent":["import React from 'react';\n\nimport { getKeyboardShortcuts } from './constants/keyboardShortcuts';\nimport type { KeyboardShortcuts } from './types';\n\nexport interface UseDocSearchKeyboardEventsProps {\n isOpen: boolean;\n onOpen: () => void;\n onClose: () => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n onInput?: (event: KeyboardEvent) => void;\n /**\n * Deprecated: Still here for backwards compat.\n *\n * @deprecated\n */\n searchButtonRef?: React.RefObject<HTMLButtonElement | null>;\n isAskAiActive: boolean;\n onAskAiToggle: (toggle: boolean) => void;\n keyboardShortcuts?: KeyboardShortcuts;\n}\n\nfunction isEditingContent(event: KeyboardEvent): boolean {\n const element = event.composedPath()[0] as HTMLElement;\n const tagName = element.tagName;\n\n return (\n element.isContentEditable ||\n tagName === 'INPUT' ||\n tagName === 'SELECT' ||\n tagName === 'TEXTAREA' ||\n tagName === 'BUTTON'\n );\n}\n\nexport function useDocSearchKeyboardEvents({\n isOpen,\n onOpen,\n onClose,\n isAskAiActive,\n onAskAiToggle,\n keyboardShortcuts,\n}: UseDocSearchKeyboardEventsProps): void {\n const resolvedShortcuts = getKeyboardShortcuts(keyboardShortcuts);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent): void {\n if (isOpen && event.code === 'Escape' && isAskAiActive) {\n onAskAiToggle(false);\n return;\n }\n\n const isCmdK =\n resolvedShortcuts['Ctrl/Cmd+K'] &&\n event.key?.toLowerCase() === 'k' &&\n (event.metaKey || event.ctrlKey);\n const isSlash = resolvedShortcuts['/'] && event.key === '/';\n\n if (\n (event.code === 'Escape' && isOpen) ||\n // The `Cmd+K` shortcut both opens and closes the modal.\n // We need to check for `event.key` because it can be `undefined` with\n // Chrome's autofill feature.\n // See https://github.com/paperjs/paper.js/issues/1398\n isCmdK ||\n // The `/` shortcut opens but doesn't close the modal because it's\n // a character.\n (!isEditingContent(event) && isSlash && !isOpen)\n ) {\n event.preventDefault();\n\n if (isOpen) {\n onClose();\n } else if (!document.body.classList.contains('DocSearch--active')) {\n // We check that no other DocSearch modal is showing before opening\n // another one.\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [\n isOpen,\n onOpen,\n onClose,\n isAskAiActive,\n onAskAiToggle,\n resolvedShortcuts,\n ]);\n}\n"],"mappings":";;;;AA0BA,SAAS,iBAAiB,OAA+B;CACvD,MAAM,UAAU,MAAM,aAAa,CAAC,CAAC;CACrC,MAAM,UAAU,QAAQ;CAExB,OACE,QAAQ,qBACR,YAAY,WACZ,YAAY,YACZ,YAAY,cACZ,YAAY;AAEhB;AAEA,SAAgB,2BAA2B,EACzC,QACA,QACA,SACA,eACA,eACA,qBACwC;CACxC,MAAM,oBAAoB,qBAAqB,iBAAiB;CAEhE,MAAM,gBAAgB;EACpB,SAAS,UAAU,OAA4B;;GAC7C,IAAI,UAAU,MAAM,SAAS,YAAY,eAAe;IACtD,cAAc,KAAK;IACnB;GACF;GAEA,MAAM,SACJ,kBAAkB,gCAClB,MAAM,6DAAK,YAAY,OAAM,QAC5B,MAAM,WAAW,MAAM;GAC1B,MAAM,UAAU,kBAAkB,QAAQ,MAAM,QAAQ;GAExD,IACG,MAAM,SAAS,YAAY,UAK5B,UAGC,CAAC,iBAAiB,KAAK,KAAK,WAAW,CAAC,QACzC;IACA,MAAM,eAAe;IAErB,IAAI,QACF,QAAQ;SACH,IAAI,CAAC,SAAS,KAAK,UAAU,SAAS,mBAAmB,GAG9D,OAAO;GAEX;EACF;EAEA,OAAO,iBAAiB,WAAW,SAAS;EAE5C,aAAmB;GACjB,OAAO,oBAAoB,WAAW,SAAS;EACjD;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSearchClient-mIHVB6ga.js","names":[],"sources":["../../src/icons/LoadingIcon.tsx","../../src/icons/SparklesIcon.tsx","../../src/icons/RecentIcon.tsx","../../src/icons/CloseIcon.tsx","../../src/icons/SourceIcon.tsx","../../src/constants.ts","../../src/AlgoliaLogo.tsx","../../src/utils/storage.ts","../../src/stored-searches.ts","../../src/useSearchClient.ts"],"sourcesContent":["import React, { type JSX } from 'react';\n\nexport function LoadingIcon({\n className,\n}: {\n className?: string;\n}): JSX.Element {\n return (\n <svg\n viewBox=\"0 0 38 38\"\n className={className}\n stroke=\"currentColor\"\n strokeOpacity=\".5\"\n >\n <g fill=\"none\" fillRule=\"evenodd\">\n <g transform=\"translate(1 1)\" strokeWidth=\"2\">\n <circle strokeOpacity=\".3\" cx=\"18\" cy=\"18\" r=\"18\" />\n <path d=\"M36 18c0-9.94-8.06-18-18-18\">\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 18 18\"\n to=\"360 18 18\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </g>\n </g>\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\ntype Props = {\n className?: string;\n};\n\nexport function SparklesIcon({ className = '' }: Props): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={`DocSearch-Hit-icon-sparkles ${className}`}\n aria-hidden=\"true\"\n >\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n <path d=\"M20 3v4\" />\n <path d=\"M22 5h-4\" />\n <path d=\"M4 17v2\" />\n <path d=\"M5 18H3\" />\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nexport function RecentIcon(): JSX.Element {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\">\n <g\n stroke=\"currentColor\"\n fill=\"none\"\n fillRule=\"evenodd\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0\" />\n <path d=\"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13\" />\n </g>\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nexport function CloseIcon({\n ...props\n}: React.ComponentProps<'svg'>): JSX.Element {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" {...props}>\n <path\n d=\"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z\"\n stroke=\"currentColor\"\n fill=\"none\"\n fillRule=\"evenodd\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nconst LvlIcon: React.FC = () => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n};\n\nexport function SourceIcon(props: { type: string }): JSX.Element {\n switch (props.type) {\n case 'lvl1':\n return <LvlIcon />;\n case 'content':\n return <ContentIcon />;\n default:\n return <AnchorIcon />;\n }\n}\n\nfunction AnchorIcon(): JSX.Element {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"4\" x2=\"20\" y1=\"9\" y2=\"9\" />\n <line x1=\"4\" x2=\"20\" y1=\"15\" y2=\"15\" />\n <line x1=\"10\" x2=\"8\" y1=\"3\" y2=\"21\" />\n <line x1=\"16\" x2=\"14\" y1=\"3\" y2=\"21\" />\n </svg>\n );\n}\n\nexport function ContentIcon(): 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 strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n );\n}\n","export const MAX_QUERY_SIZE = 512;\nexport const SUGGESTED_QUETIONS_INDEX_NAME =\n 'algolia_ask_ai_suggested_questions';\n","import React, { type JSX } from 'react';\n\nexport type AlgoliaLogoTranslations = Partial<{\n poweredByText: string;\n}>;\n\ntype AlgoliaLogoProps = {\n translations?: AlgoliaLogoTranslations;\n};\n\nexport function AlgoliaLogo({\n translations = {},\n}: AlgoliaLogoProps): JSX.Element {\n const { poweredByText = 'Powered by' } = translations;\n\n return (\n <a\n href={`https://www.algolia.com/ref/docsearch/?utm_source=${window.location.hostname}&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <span className=\"DocSearch-Label\">{poweredByText}</span>\n <svg\n width=\"80\"\n height=\"24\"\n aria-label=\"Algolia\"\n role=\"img\"\n id=\"Layer_1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 2196.2 500\"\n >\n <defs>\n <style>\n {'.cls-1,.cls-2{fill:#003dff;}.cls-2{fill-rule:evenodd;}'}\n </style>\n </defs>\n <path\n className=\"cls-2\"\n d=\"M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z\"\n />\n <rect\n className=\"cls-1\"\n x=\"1845.88\"\n y=\"104.73\"\n width=\"62.58\"\n height=\"277.9\"\n rx=\"5.9\"\n ry=\"5.9\"\n />\n <path\n className=\"cls-2\"\n d=\"M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z\"\n />\n <path\n className=\"cls-1\"\n d=\"M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z\"\n />\n </svg>\n </a>\n );\n}\n","/** Estimates the size of localStorage usage in bytes. */\nexport function getLocalStorageSize(): number {\n if (typeof window === 'undefined' || !window.localStorage) {\n return 0;\n }\n\n let total = 0;\n for (const key in window.localStorage) {\n if (window.localStorage.hasOwnProperty(key)) {\n total += window.localStorage[key].length + key.length;\n }\n }\n return total;\n}\n\n/**\n * Attempts to free up localStorage space by removing DocSearch-related items\n * starting with the oldest/largest ones.\n */\nfunction cleanupDocSearchStorage(): void {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n\n const docSearchKeys: Array<{ key: string; size: number }> = [];\n\n // Find all DocSearch-related keys and their sizes\n for (const key in window.localStorage) {\n if (key.includes('__DOCSEARCH_')) {\n const value = window.localStorage[key];\n docSearchKeys.push({ key, size: value.length + key.length });\n }\n }\n\n // Sort by size (largest first) to remove the most impactful items\n docSearchKeys.sort((a, b) => b.size - a.size);\n\n // Remove up to half of the DocSearch items, starting with the largest\n const itemsToRemove = Math.ceil(docSearchKeys.length / 2);\n for (let i = 0; i < itemsToRemove && i < docSearchKeys.length; i++) {\n try {\n window.localStorage.removeItem(docSearchKeys[i].key);\n } catch {\n // Silently ignore cleanup errors to prevent crashes\n }\n }\n}\n\n/**\n * Safely sets an item in localStorage with quota exceeded error handling.\n *\n * @param key - The localStorage key.\n * @param value - The value to store (will be JSON.stringified).\n */\nfunction safeSetLocalStorageItem(key: string, value: any): void {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n // Handle quota exceeded error by clearing old data and retrying\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n try {\n // First, try comprehensive cleanup of DocSearch storage\n cleanupDocSearchStorage();\n // Retry with original data\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // If still failing, silently fail to prevent crashes\n }\n } else {\n // For other localStorage errors, silently fail to prevent crashes\n }\n }\n}\n\n/**\n * Proactively manages localStorage quota by cleaning up when usage is high\n * Should be called periodically to prevent quota exceeded errors.\n */\nexport function manageLocalStorageQuota(): void {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n\n const currentSize = getLocalStorageSize();\n // Typical localStorage limit is 5-10MB, start cleanup at 4MB to be safe\n const CLEANUP_THRESHOLD = 4 * 1024 * 1024; // 4MB\n\n if (currentSize > CLEANUP_THRESHOLD) {\n cleanupDocSearchStorage();\n }\n}\n\n/** Checks if local storage is available and usable. */\nexport function isLocalStorageSupported(): boolean {\n // guard against ssr and browsers where localstorage is disabled\n if (typeof window === 'undefined' || !('localStorage' in window)) {\n return false;\n }\n\n const key = '__TEST_KEY__';\n try {\n window.localStorage.setItem(key, '');\n window.localStorage.removeItem(key);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Creates a simple storage interface for arrays using localstorage. Provides\n * basic getitem and setitem functionality. Falls back to a no-op implementation\n * if localstorage is not supported..\n *\n * @template titem The type of items to store.\n * @param key - The localstorage key to use.\n * @returns An object with setitem and getitem methods.\n */\nexport function createStorage<TItem>(key: string) {\n if (isLocalStorageSupported() === false) {\n return {\n setItem(): void {},\n getItem(): TItem[] {\n return [];\n },\n };\n }\n\n return {\n setItem(item: TItem[]): void {\n safeSetLocalStorageItem(key, item);\n },\n getItem(): TItem[] {\n const item = window.localStorage.getItem(key);\n if (item === null) return [];\n try {\n const parsed = JSON.parse(item);\n return Array.isArray(parsed) ? (parsed as TItem[]) : [];\n } catch {\n // clear corrupted data and return empty list\n window.localStorage.removeItem(key);\n return [];\n }\n },\n };\n}\n\n/**\n * Creates a simple storage interface for a single object using localstorage.\n * Provides basic getitem, setitem, and removeitem functionality. Falls back to\n * a no-op implementation if localstorage is not supported.\n *\n * @template titem The type of the object to store.\n * @param key - The localstorage key to use.\n * @returns An object with setitem, getitem, and removeitem methods.\n */\nexport function createObjectStorage<TItem>(key: string) {\n if (isLocalStorageSupported() === false) {\n return {\n setItem(_item: TItem | null): void {},\n getItem(): TItem | null {\n return null;\n },\n removeItem(): void {},\n };\n }\n\n return {\n setItem(item: TItem | null): void {\n if (item === null) {\n window.localStorage.removeItem(key);\n } else {\n safeSetLocalStorageItem(key, item);\n }\n },\n getItem(): TItem | null {\n const item = window.localStorage.getItem(key);\n try {\n return item ? (JSON.parse(item) as TItem) : null;\n } catch {\n // handle potential JSON parsing errors, e.g., corrupted data\n window.localStorage.removeItem(key); // clear corrupted data\n return null;\n }\n },\n removeItem(): void {\n window.localStorage.removeItem(key);\n },\n };\n}\n","import type {\n AskAiFeedbackReason,\n DocSearchHit,\n StoredAskAiState,\n StoredDocSearchHit,\n StoredAskAiMessage,\n} from './types';\nimport { createStorage } from './utils/storage';\n\nexport type StoredFeedbackDetails = {\n tags?: AskAiFeedbackReason[];\n notes?: string;\n};\n\ntype CreateStoredSearchesOptions = {\n key: string;\n limit?: number;\n};\n\nexport type StoredSearchPlugin<TItem> = {\n add: (item: TItem) => void;\n remove: (item: TItem) => void;\n getAll: () => TItem[];\n addFeedback?: (\n messageId: string,\n feedback: 'dislike' | 'like',\n details?: StoredFeedbackDetails\n ) => void;\n getOne?: (messageId: string) => StoredAskAiMessage | undefined;\n getConversation?: (messageId: string) => TItem | undefined;\n};\n\nexport function createStoredSearches<TItem extends StoredDocSearchHit>({\n key,\n limit = 5,\n}: CreateStoredSearchesOptions): StoredSearchPlugin<TItem> {\n const storage = createStorage<TItem>(key);\n let items = storage.getItem().slice(0, limit);\n\n return {\n add(item: TItem): void {\n const { _highlightResult, _snippetResult, ...hit } =\n item as unknown as DocSearchHit;\n\n const isQueryAlreadySaved = items.findIndex(\n (x) => x.objectID === hit.objectID\n );\n\n if (isQueryAlreadySaved > -1) {\n items.splice(isQueryAlreadySaved, 1);\n }\n\n items.unshift(hit as TItem);\n items = items.slice(0, limit);\n\n storage.setItem(items);\n },\n remove(item: TItem): void {\n items = items.filter((x) => x.objectID !== item.objectID);\n\n storage.setItem(items);\n },\n getAll(): TItem[] {\n return items;\n },\n };\n}\n\nexport function createStoredConversations<TItem extends StoredAskAiState>({\n key,\n limit = 5,\n}: CreateStoredSearchesOptions): StoredSearchPlugin<TItem> {\n const storage = createStorage<TItem>(key);\n let items = storage.getItem().slice(0, limit);\n\n return {\n add(item: TItem): void {\n const { objectID, query } = item;\n\n // check if this query is already saved\n const isQueryAlreadySaved = items.findIndex(\n (x) => x.objectID === objectID || x.query === query\n );\n\n if (isQueryAlreadySaved > -1) {\n items[isQueryAlreadySaved] = item;\n } else {\n items.unshift(item);\n items = items.slice(0, limit);\n }\n\n storage.setItem(items);\n },\n /**\n * Record feedback (like/dislike) for a given message id within stored\n * conversations.\n */\n addFeedback(\n messageId: string,\n feedback: 'dislike' | 'like',\n details?: StoredFeedbackDetails\n ): void {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n if (!conv || !conv.messages) return;\n\n const msg = conv.messages.find((m) => m.id === messageId) as\n | StoredAskAiMessage\n | undefined;\n if (!msg) return;\n\n msg.feedback = feedback;\n msg.feedbackTags = details?.tags;\n msg.feedbackNotes = details?.notes;\n\n storage.setItem(items);\n },\n getOne(messageId: string): StoredAskAiMessage | undefined {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n return conv?.messages?.find((m) => m.id === messageId);\n },\n getAll(): TItem[] {\n return items;\n },\n remove(item: TItem): void {\n items = items.filter((x) => x.objectID !== item.objectID);\n\n storage.setItem(items);\n },\n getConversation(messageId: string): TItem | undefined {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n\n if (!conv || !conv.messages) return undefined;\n\n return conv;\n },\n };\n}\n","import { liteClient } from 'algoliasearch/lite';\nimport React from 'react';\n\nimport type { DocSearchTransformClient } from './DocSearch';\nimport { version } from './version';\n\nexport function useSearchClient(\n appId: string,\n apiKey: string,\n transformSearchClient: (\n searchClient: DocSearchTransformClient\n ) => DocSearchTransformClient\n): DocSearchTransformClient {\n const searchClient = React.useMemo(() => {\n const client = liteClient(appId, apiKey);\n client.addAlgoliaAgent('docsearch', version);\n\n // Since DocSearch.js relies on DocSearch React with an alias to Preact,\n // we cannot add the `docsearch-react` user agent by default, otherwise\n // it would also be sent on a DocSearch.js integration.\n // We therefore only add the `docsearch-react` user agent if `docsearch.js`\n // is not present.\n if (\n /docsearch.js \\(.*\\)/.test(client.transporter.algoliaAgent.value) ===\n false\n ) {\n client.addAlgoliaAgent('docsearch-react', version);\n }\n\n return transformSearchClient(client);\n }, [appId, apiKey, transformSearchClient]);\n\n return searchClient;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useSearchClient-mIHVB6ga.js","names":[],"sources":["../../src/icons/LoadingIcon.tsx","../../src/icons/SparklesIcon.tsx","../../src/icons/RecentIcon.tsx","../../src/icons/CloseIcon.tsx","../../src/icons/SourceIcon.tsx","../../src/constants.ts","../../src/AlgoliaLogo.tsx","../../src/utils/storage.ts","../../src/stored-searches.ts","../../src/useSearchClient.ts"],"sourcesContent":["import React, { type JSX } from 'react';\n\nexport function LoadingIcon({\n className,\n}: {\n className?: string;\n}): JSX.Element {\n return (\n <svg\n viewBox=\"0 0 38 38\"\n className={className}\n stroke=\"currentColor\"\n strokeOpacity=\".5\"\n >\n <g fill=\"none\" fillRule=\"evenodd\">\n <g transform=\"translate(1 1)\" strokeWidth=\"2\">\n <circle strokeOpacity=\".3\" cx=\"18\" cy=\"18\" r=\"18\" />\n <path d=\"M36 18c0-9.94-8.06-18-18-18\">\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 18 18\"\n to=\"360 18 18\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </path>\n </g>\n </g>\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\ntype Props = {\n className?: string;\n};\n\nexport function SparklesIcon({ className = '' }: Props): JSX.Element {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={`DocSearch-Hit-icon-sparkles ${className}`}\n aria-hidden=\"true\"\n >\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n <path d=\"M20 3v4\" />\n <path d=\"M22 5h-4\" />\n <path d=\"M4 17v2\" />\n <path d=\"M5 18H3\" />\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nexport function RecentIcon(): JSX.Element {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\">\n <g\n stroke=\"currentColor\"\n fill=\"none\"\n fillRule=\"evenodd\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M3.18 6.6a8.23 8.23 0 1112.93 9.94h0a8.23 8.23 0 01-11.63 0\" />\n <path d=\"M6.44 7.25H2.55V3.36M10.45 6v5.6M10.45 11.6L13 13\" />\n </g>\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nexport function CloseIcon({\n ...props\n}: React.ComponentProps<'svg'>): JSX.Element {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" {...props}>\n <path\n d=\"M10 10l5.09-5.09L10 10l5.09 5.09L10 10zm0 0L4.91 4.91 10 10l-5.09 5.09L10 10z\"\n stroke=\"currentColor\"\n fill=\"none\"\n fillRule=\"evenodd\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n","import React, { type JSX } from 'react';\n\nconst LvlIcon: React.FC = () => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </svg>\n );\n};\n\nexport function SourceIcon(props: { type: string }): JSX.Element {\n switch (props.type) {\n case 'lvl1':\n return <LvlIcon />;\n case 'content':\n return <ContentIcon />;\n default:\n return <AnchorIcon />;\n }\n}\n\nfunction AnchorIcon(): JSX.Element {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"4\" x2=\"20\" y1=\"9\" y2=\"9\" />\n <line x1=\"4\" x2=\"20\" y1=\"15\" y2=\"15\" />\n <line x1=\"10\" x2=\"8\" y1=\"3\" y2=\"21\" />\n <line x1=\"16\" x2=\"14\" y1=\"3\" y2=\"21\" />\n </svg>\n );\n}\n\nexport function ContentIcon(): 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 strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n );\n}\n","export const MAX_QUERY_SIZE = 512;\nexport const SNIPPET_LENGTH = 15;\nexport const SUGGESTED_QUETIONS_INDEX_NAME =\n 'algolia_ask_ai_suggested_questions';\n","import React, { type JSX } from 'react';\n\nexport type AlgoliaLogoTranslations = Partial<{\n poweredByText: string;\n}>;\n\ntype AlgoliaLogoProps = {\n translations?: AlgoliaLogoTranslations;\n};\n\nexport function AlgoliaLogo({\n translations = {},\n}: AlgoliaLogoProps): JSX.Element {\n const { poweredByText = 'Powered by' } = translations;\n\n return (\n <a\n href={`https://www.algolia.com/ref/docsearch/?utm_source=${window.location.hostname}&utm_medium=referral&utm_content=powered_by&utm_campaign=docsearch`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <span className=\"DocSearch-Label\">{poweredByText}</span>\n <svg\n width=\"80\"\n height=\"24\"\n aria-label=\"Algolia\"\n role=\"img\"\n id=\"Layer_1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 2196.2 500\"\n >\n <defs>\n <style>\n {'.cls-1,.cls-2{fill:#003dff;}.cls-2{fill-rule:evenodd;}'}\n </style>\n </defs>\n <path\n className=\"cls-2\"\n d=\"M1070.38,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z\"\n />\n <rect\n className=\"cls-1\"\n x=\"1845.88\"\n y=\"104.73\"\n width=\"62.58\"\n height=\"277.9\"\n rx=\"5.9\"\n ry=\"5.9\"\n />\n <path\n className=\"cls-2\"\n d=\"M1851.78,71.38h50.77c3.26,0,5.9-2.64,5.9-5.9V5.9c0-3.62-3.24-6.39-6.82-5.83l-50.77,7.95c-2.87,.45-4.99,2.92-4.99,5.83v51.62c0,3.26,2.64,5.9,5.9,5.9Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1764.03,275.3V5.91c0-3.63-3.24-6.39-6.82-5.83l-50.46,7.94c-2.87,.45-4.99,2.93-4.99,5.84l.17,273.22c0,12.92,0,92.7,95.97,95.49,3.33,.1,6.09-2.58,6.09-5.91v-40.78c0-2.96-2.19-5.51-5.12-5.84-34.85-4.01-34.85-47.57-34.85-54.72Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1631.95,142.72c-11.14-12.25-24.83-21.65-40.78-28.31-15.92-6.53-33.26-9.85-52.07-9.85-18.78,0-36.15,3.17-51.92,9.85-15.59,6.66-29.29,16.05-40.76,28.31-11.47,12.23-20.38,26.87-26.76,44.03-6.38,17.17-9.24,37.37-9.24,58.36,0,20.99,3.19,36.87,9.55,54.21,6.38,17.32,15.14,32.11,26.45,44.36,11.29,12.23,24.83,21.62,40.6,28.46,15.77,6.83,40.12,10.33,52.4,10.48,12.25,0,36.78-3.82,52.7-10.48,15.92-6.68,29.46-16.23,40.78-28.46,11.29-12.25,20.05-27.04,26.25-44.36,6.22-17.34,9.24-33.22,9.24-54.21,0-20.99-3.34-41.19-10.03-58.36-6.38-17.17-15.14-31.8-26.43-44.03Zm-44.43,163.75c-11.47,15.75-27.56,23.7-48.09,23.7-20.55,0-36.63-7.8-48.1-23.7-11.47-15.75-17.21-34.01-17.21-61.2,0-26.89,5.59-49.14,17.06-64.87,11.45-15.75,27.54-23.52,48.07-23.52,20.55,0,36.63,7.78,48.09,23.52,11.47,15.57,17.36,37.98,17.36,64.87,0,27.19-5.72,45.3-17.19,61.2Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M894.42,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M2133.97,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-14.52,22.58-22.99,49.63-22.99,78.73,0,44.89,20.13,84.92,51.59,111.1,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47,1.23,0,2.46-.03,3.68-.09,.36-.02,.71-.05,1.07-.07,.87-.05,1.75-.11,2.62-.2,.34-.03,.68-.08,1.02-.12,.91-.1,1.82-.21,2.73-.34,.21-.03,.42-.07,.63-.1,32.89-5.07,61.56-30.82,70.9-62.81v57.83c0,3.26,2.64,5.9,5.9,5.9h50.42c3.26,0,5.9-2.64,5.9-5.9V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,206.92c-12.2,10.16-27.97,13.98-44.84,15.12-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-42.24,0-77.12-35.89-77.12-79.37,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33v142.83Z\"\n />\n <path\n className=\"cls-2\"\n d=\"M1314.05,104.73h-49.33c-48.36,0-90.91,25.48-115.75,64.1-11.79,18.34-19.6,39.64-22.11,62.59-.58,5.3-.88,10.68-.88,16.14s.31,11.15,.93,16.59c4.28,38.09,23.14,71.61,50.66,94.52,2.93,2.6,6.05,4.98,9.31,7.14,12.86,8.49,28.11,13.47,44.52,13.47h0c17.99,0,34.61-5.93,48.16-15.97,16.29-11.58,28.88-28.54,34.48-47.75v50.26h-.11v11.08c0,21.84-5.71,38.27-17.34,49.36-11.61,11.08-31.04,16.63-58.25,16.63-11.12,0-28.79-.59-46.6-2.41-2.83-.29-5.46,1.5-6.27,4.22l-12.78,43.11c-1.02,3.46,1.27,7.02,4.83,7.53,21.52,3.08,42.52,4.68,54.65,4.68,48.91,0,85.16-10.75,108.89-32.21,21.48-19.41,33.15-48.89,35.2-88.52V110.63c0-3.26-2.64-5.9-5.9-5.9h-56.32Zm0,64.1s.65,139.13,0,143.36c-12.08,9.77-27.11,13.59-43.49,14.7-.16,.01-.33,.03-.49,.04-1.12,.07-2.24,.1-3.36,.1-1.32,0-2.63-.03-3.94-.1-40.41-2.11-74.52-37.26-74.52-79.38,0-10.25,1.96-20.01,5.42-28.98,11.22-29.12,38.77-49.74,71.06-49.74h49.33Z\"\n />\n <path\n className=\"cls-1\"\n d=\"M249.83,0C113.3,0,2,110.09,.03,246.16c-2,138.19,110.12,252.7,248.33,253.5,42.68,.25,83.79-10.19,120.3-30.03,3.56-1.93,4.11-6.83,1.08-9.51l-23.38-20.72c-4.75-4.21-11.51-5.4-17.36-2.92-25.48,10.84-53.17,16.38-81.71,16.03-111.68-1.37-201.91-94.29-200.13-205.96,1.76-110.26,92-199.41,202.67-199.41h202.69V407.41l-115-102.18c-3.72-3.31-9.42-2.66-12.42,1.31-18.46,24.44-48.53,39.64-81.93,37.34-46.33-3.2-83.87-40.5-87.34-86.81-4.15-55.24,39.63-101.52,94-101.52,49.18,0,89.68,37.85,93.91,85.95,.38,4.28,2.31,8.27,5.52,11.12l29.95,26.55c3.4,3.01,8.79,1.17,9.63-3.3,2.16-11.55,2.92-23.58,2.07-35.92-4.82-70.34-61.8-126.93-132.17-131.26-80.68-4.97-148.13,58.14-150.27,137.25-2.09,77.1,61.08,143.56,138.19,145.26,32.19,.71,62.03-9.41,86.14-26.95l150.26,133.2c6.44,5.71,16.61,1.14,16.61-7.47V9.48C499.66,4.25,495.42,0,490.18,0H249.83Z\"\n />\n </svg>\n </a>\n );\n}\n","/** Estimates the size of localStorage usage in bytes. */\nexport function getLocalStorageSize(): number {\n if (typeof window === 'undefined' || !window.localStorage) {\n return 0;\n }\n\n let total = 0;\n for (const key in window.localStorage) {\n if (window.localStorage.hasOwnProperty(key)) {\n total += window.localStorage[key].length + key.length;\n }\n }\n return total;\n}\n\n/**\n * Attempts to free up localStorage space by removing DocSearch-related items\n * starting with the oldest/largest ones.\n */\nfunction cleanupDocSearchStorage(): void {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n\n const docSearchKeys: Array<{ key: string; size: number }> = [];\n\n // Find all DocSearch-related keys and their sizes\n for (const key in window.localStorage) {\n if (key.includes('__DOCSEARCH_')) {\n const value = window.localStorage[key];\n docSearchKeys.push({ key, size: value.length + key.length });\n }\n }\n\n // Sort by size (largest first) to remove the most impactful items\n docSearchKeys.sort((a, b) => b.size - a.size);\n\n // Remove up to half of the DocSearch items, starting with the largest\n const itemsToRemove = Math.ceil(docSearchKeys.length / 2);\n for (let i = 0; i < itemsToRemove && i < docSearchKeys.length; i++) {\n try {\n window.localStorage.removeItem(docSearchKeys[i].key);\n } catch {\n // Silently ignore cleanup errors to prevent crashes\n }\n }\n}\n\n/**\n * Safely sets an item in localStorage with quota exceeded error handling.\n *\n * @param key - The localStorage key.\n * @param value - The value to store (will be JSON.stringified).\n */\nfunction safeSetLocalStorageItem(key: string, value: any): void {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n // Handle quota exceeded error by clearing old data and retrying\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n try {\n // First, try comprehensive cleanup of DocSearch storage\n cleanupDocSearchStorage();\n // Retry with original data\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n // If still failing, silently fail to prevent crashes\n }\n } else {\n // For other localStorage errors, silently fail to prevent crashes\n }\n }\n}\n\n/**\n * Proactively manages localStorage quota by cleaning up when usage is high\n * Should be called periodically to prevent quota exceeded errors.\n */\nexport function manageLocalStorageQuota(): void {\n if (typeof window === 'undefined' || !window.localStorage) {\n return;\n }\n\n const currentSize = getLocalStorageSize();\n // Typical localStorage limit is 5-10MB, start cleanup at 4MB to be safe\n const CLEANUP_THRESHOLD = 4 * 1024 * 1024; // 4MB\n\n if (currentSize > CLEANUP_THRESHOLD) {\n cleanupDocSearchStorage();\n }\n}\n\n/** Checks if local storage is available and usable. */\nexport function isLocalStorageSupported(): boolean {\n // guard against ssr and browsers where localstorage is disabled\n if (typeof window === 'undefined' || !('localStorage' in window)) {\n return false;\n }\n\n const key = '__TEST_KEY__';\n try {\n window.localStorage.setItem(key, '');\n window.localStorage.removeItem(key);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Creates a simple storage interface for arrays using localstorage. Provides\n * basic getitem and setitem functionality. Falls back to a no-op implementation\n * if localstorage is not supported..\n *\n * @template titem The type of items to store.\n * @param key - The localstorage key to use.\n * @returns An object with setitem and getitem methods.\n */\nexport function createStorage<TItem>(key: string) {\n if (isLocalStorageSupported() === false) {\n return {\n setItem(): void {},\n getItem(): TItem[] {\n return [];\n },\n };\n }\n\n return {\n setItem(item: TItem[]): void {\n safeSetLocalStorageItem(key, item);\n },\n getItem(): TItem[] {\n const item = window.localStorage.getItem(key);\n if (item === null) return [];\n try {\n const parsed = JSON.parse(item);\n return Array.isArray(parsed) ? (parsed as TItem[]) : [];\n } catch {\n // clear corrupted data and return empty list\n window.localStorage.removeItem(key);\n return [];\n }\n },\n };\n}\n\n/**\n * Creates a simple storage interface for a single object using localstorage.\n * Provides basic getitem, setitem, and removeitem functionality. Falls back to\n * a no-op implementation if localstorage is not supported.\n *\n * @template titem The type of the object to store.\n * @param key - The localstorage key to use.\n * @returns An object with setitem, getitem, and removeitem methods.\n */\nexport function createObjectStorage<TItem>(key: string) {\n if (isLocalStorageSupported() === false) {\n return {\n setItem(_item: TItem | null): void {},\n getItem(): TItem | null {\n return null;\n },\n removeItem(): void {},\n };\n }\n\n return {\n setItem(item: TItem | null): void {\n if (item === null) {\n window.localStorage.removeItem(key);\n } else {\n safeSetLocalStorageItem(key, item);\n }\n },\n getItem(): TItem | null {\n const item = window.localStorage.getItem(key);\n try {\n return item ? (JSON.parse(item) as TItem) : null;\n } catch {\n // handle potential JSON parsing errors, e.g., corrupted data\n window.localStorage.removeItem(key); // clear corrupted data\n return null;\n }\n },\n removeItem(): void {\n window.localStorage.removeItem(key);\n },\n };\n}\n","import type {\n AskAiFeedbackReason,\n DocSearchHit,\n StoredAskAiState,\n StoredDocSearchHit,\n StoredAskAiMessage,\n} from './types';\nimport { createStorage } from './utils/storage';\n\nexport type StoredFeedbackDetails = {\n tags?: AskAiFeedbackReason[];\n notes?: string;\n};\n\ntype CreateStoredSearchesOptions = {\n key: string;\n limit?: number;\n};\n\nexport type StoredSearchPlugin<TItem> = {\n add: (item: TItem) => void;\n remove: (item: TItem) => void;\n getAll: () => TItem[];\n addFeedback?: (\n messageId: string,\n feedback: 'dislike' | 'like',\n details?: StoredFeedbackDetails\n ) => void;\n getOne?: (messageId: string) => StoredAskAiMessage | undefined;\n getConversation?: (messageId: string) => TItem | undefined;\n};\n\nexport function createStoredSearches<TItem extends StoredDocSearchHit>({\n key,\n limit = 5,\n}: CreateStoredSearchesOptions): StoredSearchPlugin<TItem> {\n const storage = createStorage<TItem>(key);\n let items = storage.getItem().slice(0, limit);\n\n return {\n add(item: TItem): void {\n const { _highlightResult, _snippetResult, ...hit } =\n item as unknown as DocSearchHit;\n\n const isQueryAlreadySaved = items.findIndex(\n (x) => x.objectID === hit.objectID\n );\n\n if (isQueryAlreadySaved > -1) {\n items.splice(isQueryAlreadySaved, 1);\n }\n\n items.unshift(hit as TItem);\n items = items.slice(0, limit);\n\n storage.setItem(items);\n },\n remove(item: TItem): void {\n items = items.filter((x) => x.objectID !== item.objectID);\n\n storage.setItem(items);\n },\n getAll(): TItem[] {\n return items;\n },\n };\n}\n\nexport function createStoredConversations<TItem extends StoredAskAiState>({\n key,\n limit = 5,\n}: CreateStoredSearchesOptions): StoredSearchPlugin<TItem> {\n const storage = createStorage<TItem>(key);\n let items = storage.getItem().slice(0, limit);\n\n return {\n add(item: TItem): void {\n const { objectID, query } = item;\n\n // check if this query is already saved\n const isQueryAlreadySaved = items.findIndex(\n (x) => x.objectID === objectID || x.query === query\n );\n\n if (isQueryAlreadySaved > -1) {\n items[isQueryAlreadySaved] = item;\n } else {\n items.unshift(item);\n items = items.slice(0, limit);\n }\n\n storage.setItem(items);\n },\n /**\n * Record feedback (like/dislike) for a given message id within stored\n * conversations.\n */\n addFeedback(\n messageId: string,\n feedback: 'dislike' | 'like',\n details?: StoredFeedbackDetails\n ): void {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n if (!conv || !conv.messages) return;\n\n const msg = conv.messages.find((m) => m.id === messageId) as\n | StoredAskAiMessage\n | undefined;\n if (!msg) return;\n\n msg.feedback = feedback;\n msg.feedbackTags = details?.tags;\n msg.feedbackNotes = details?.notes;\n\n storage.setItem(items);\n },\n getOne(messageId: string): StoredAskAiMessage | undefined {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n return conv?.messages?.find((m) => m.id === messageId);\n },\n getAll(): TItem[] {\n return items;\n },\n remove(item: TItem): void {\n items = items.filter((x) => x.objectID !== item.objectID);\n\n storage.setItem(items);\n },\n getConversation(messageId: string): TItem | undefined {\n const conv = items.find((c) =>\n c.messages?.some((m) => m.id === messageId)\n );\n\n if (!conv || !conv.messages) return undefined;\n\n return conv;\n },\n };\n}\n","import { liteClient } from 'algoliasearch/lite';\nimport React from 'react';\n\nimport type { DocSearchTransformClient } from './DocSearch';\nimport { version } from './version';\n\nexport function useSearchClient(\n appId: string,\n apiKey: string,\n transformSearchClient: (\n searchClient: DocSearchTransformClient\n ) => DocSearchTransformClient\n): DocSearchTransformClient {\n const searchClient = React.useMemo(() => {\n const client = liteClient(appId, apiKey);\n client.addAlgoliaAgent('docsearch', version);\n\n // Since DocSearch.js relies on DocSearch React with an alias to Preact,\n // we cannot add the `docsearch-react` user agent by default, otherwise\n // it would also be sent on a DocSearch.js integration.\n // We therefore only add the `docsearch-react` user agent if `docsearch.js`\n // is not present.\n if (\n /docsearch.js \\(.*\\)/.test(client.transporter.algoliaAgent.value) ===\n false\n ) {\n client.addAlgoliaAgent('docsearch-react', version);\n }\n\n return transformSearchClient(client);\n }, [appId, apiKey, transformSearchClient]);\n\n return searchClient;\n}\n"],"mappings":"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"}