@docsearch/react 4.6.3 → 5.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +0 -2
  2. package/dist/esm/AskAiScreenState-D0IZsCMJ.d.ts +106 -0
  3. package/dist/esm/DocSearch-Dq5Utfyb.d.ts +295 -0
  4. package/dist/esm/DocSearchAskAiModal-BwbMrrHv.d.ts +48 -0
  5. package/dist/esm/DocSearchAskAiModal-CCrk6YLb.js +954 -0
  6. package/dist/esm/DocSearchAskAiModal-CCrk6YLb.js.map +1 -0
  7. package/dist/esm/DocSearchButton-CRlNPf5k.d.ts +18 -0
  8. package/dist/esm/DocSearchButton-CaxxOzQU.js +71 -0
  9. package/dist/esm/DocSearchButton-CaxxOzQU.js.map +1 -0
  10. package/dist/esm/DocSearchModal-CpvDjo1O.js +250 -0
  11. package/dist/esm/DocSearchModal-CpvDjo1O.js.map +1 -0
  12. package/dist/esm/DocSearchTheme-DvL4mf0D.d.ts +5 -0
  13. package/dist/esm/askaiModal.d.ts +2 -0
  14. package/dist/esm/askaiModal.js +3 -0
  15. package/dist/esm/button.d.ts +2 -0
  16. package/dist/esm/button.js +3 -0
  17. package/dist/esm/docsearchAi.d.ts +220 -0
  18. package/dist/esm/docsearchAi.js +34 -0
  19. package/dist/esm/docsearchAi.js.map +1 -0
  20. package/dist/esm/index-Dl8FMlR5.d.ts +223 -0
  21. package/dist/esm/index.d.ts +9 -655
  22. package/dist/esm/index.js +35 -3
  23. package/dist/esm/index.js.map +1 -0
  24. package/dist/esm/keyboard-BkSdCzTU.js +9 -0
  25. package/dist/esm/keyboard-BkSdCzTU.js.map +1 -0
  26. package/dist/esm/keyboardShortcuts-C-lx6Xt7.js +25 -0
  27. package/dist/esm/keyboardShortcuts-C-lx6Xt7.js.map +1 -0
  28. package/dist/esm/modal.d.ts +2 -0
  29. package/dist/esm/modal.js +3 -0
  30. package/dist/esm/normalizeDocSearchIndexes-DAzlMybx.js +1240 -0
  31. package/dist/esm/normalizeDocSearchIndexes-DAzlMybx.js.map +1 -0
  32. package/dist/esm/objectSpread2-BNmiQYyW.js +67 -0
  33. package/dist/esm/objectWithoutProperties-phqYxDS0.js +53 -0
  34. package/dist/esm/objectWithoutProperties-phqYxDS0.js.map +1 -0
  35. package/dist/esm/sidepanel.d.ts +395 -0
  36. package/dist/esm/sidepanel.js +773 -0
  37. package/dist/esm/sidepanel.js.map +1 -0
  38. package/dist/esm/useDocSearchKeyboardEvents-68G8dw6c.d.ts +43 -0
  39. package/dist/esm/useDocSearchKeyboardEvents.d.ts +2 -41
  40. package/dist/esm/useDocSearchKeyboardEvents.js +43 -1
  41. package/dist/esm/useDocSearchKeyboardEvents.js.map +1 -0
  42. package/dist/esm/useSearchClient-mIHVB6ga.js +433 -0
  43. package/dist/esm/useSearchClient-mIHVB6ga.js.map +1 -0
  44. package/dist/esm/useSuggestedQuestions-D2TGVPsI.js +1112 -0
  45. package/dist/esm/useSuggestedQuestions-D2TGVPsI.js.map +1 -0
  46. package/dist/esm/useTheme.d.ts +7 -6
  47. package/dist/esm/useTheme.js +21 -1
  48. package/dist/esm/useTheme.js.map +1 -0
  49. package/dist/esm/version.d.ts +4 -2
  50. package/dist/esm/version.js +6 -1
  51. package/dist/esm/version.js.map +1 -0
  52. package/dist/umd/index.js +175 -5
  53. package/dist/umd/index.js.map +1 -1
  54. package/package.json +31 -34
  55. package/style/askai.js +1 -0
  56. package/button.js +0 -1
  57. package/dist/esm/DocSearchButton.d.ts +0 -18
  58. package/dist/esm/DocSearchButton.js +0 -1
  59. package/dist/esm/DocSearchModal.d.ts +0 -444
  60. package/dist/esm/DocSearchModal.js +0 -3
  61. package/dist/esm/Sidepanel.d.ts +0 -371
  62. package/dist/esm/Sidepanel.js +0 -3
  63. package/dist/umd/DocSearchModal.js +0 -5
  64. package/dist/umd/DocSearchModal.js.map +0 -1
  65. package/dist/umd/DocsearchButton.js +0 -3
  66. package/dist/umd/DocsearchButton.js.map +0 -1
  67. package/dist/umd/Sidepanel.js +0 -5
  68. package/dist/umd/Sidepanel.js.map +0 -1
  69. package/dist/umd/useDocSearchKeyboardEvents.js +0 -3
  70. package/dist/umd/useDocSearchKeyboardEvents.js.map +0 -1
  71. package/dist/umd/useTheme.js +0 -3
  72. package/dist/umd/useTheme.js.map +0 -1
  73. package/dist/umd/version.js +0 -3
  74. package/dist/umd/version.js.map +0 -1
  75. package/modal.js +0 -1
  76. package/sidepanel.js +0 -1
  77. package/useDocSearchKeyboardEvents.js +0 -1
  78. package/useTheme.js +0 -1
  79. package/version.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidepanel.js","names":[],"sources":["../../src/icons/SendIcon.tsx","../../src/icons/ExpandIcon.tsx","../../src/icons/FolderIcon.tsx","../../src/icons/EditIcon.tsx","../../src/useIsMobile.ts","../../src/Sidepanel/ConversationHistoryScreen.tsx","../../src/Sidepanel/AggregatedSearchBlock.tsx","../../src/Sidepanel/ConversationScreen.tsx","../../src/Sidepanel/NewConversationScreen.tsx","../../src/Sidepanel/PromptForm.tsx","../../src/Sidepanel/setSidepanelSearchClient.ts","../../src/Sidepanel/SidepanelHeader.tsx","../../src/Sidepanel/useManageSidepanelLayout.ts","../../src/Sidepanel/useSidepanelKeyboardEvents.ts","../../src/Sidepanel/useSidepanelWidth.ts","../../src/Sidepanel/Sidepanel.tsx","../../src/Sidepanel/SidepanelButton.tsx","../../src/Sidepanel.tsx"],"sourcesContent":["import type { JSX } from 'react';\nimport React from 'react';\n\nexport const SendIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m5 12 7-7 7 7\" />\n <path d=\"M12 19V5\" />\n </svg>\n );\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nexport const ExpandIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 13 13\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M8 0.5C8 0.223858 8.22386 0 8.5 0H12.5C12.7761 0 13 0.223858 13 0.5V4.5C13 4.77614 12.7761 5 12.5 5C12.2239 5 12 4.77614 12 4.5V1.70711L8.18689 5.52022C7.99162 5.71548 7.67504 5.71548 7.47978 5.52022C7.28452 5.32496 7.28452 5.00838 7.47978 4.81311L11.2929 1H8.5C8.22386 1 8 0.776142 8 0.5ZM5.52022 7.47978C5.71548 7.67504 5.71548 7.99162 5.52022 8.18689L1.70711 12H4.5C4.77614 12 5 12.2239 5 12.5C5 12.7761 4.77614 13 4.5 13H0.5C0.223858 13 0 12.7761 0 12.5V8.5C0 8.22386 0.223858 8 0.5 8C0.776142 8 1 8.22386 1 8.5V11.2929L4.81311 7.47978C5.00838 7.28452 5.32496 7.28452 5.52022 7.47978Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const FolderIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\" />\n </svg>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nexport const EditIcon = (): JSX.Element => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\" />\n <path d=\"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\" />\n </svg>\n );\n};\n","import React from 'react';\n\nexport const useIsMobile = (): boolean => {\n const [isMobile, setIsMobile] = React.useState(false);\n\n React.useEffect(() => {\n const checkForMobile = (): void => {\n const isMobileMediaQuery = window.matchMedia('(max-width: 768px)');\n\n setIsMobile(isMobileMediaQuery.matches);\n };\n\n checkForMobile();\n\n window.addEventListener('resize', checkForMobile);\n\n return (): void => {\n window.removeEventListener('resize', checkForMobile);\n };\n }, []);\n\n return isMobile;\n};\n","/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */\nimport React from 'react';\nimport type { JSX } from 'react';\n\nimport { CloseIcon, RecentIcon } from '../icons';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { StoredAskAiState } from '../types';\n\ntype ConversationHistoryScreenProps = {\n conversations: StoredSearchPlugin<StoredAskAiState>;\n selectConversation: (conversation: StoredAskAiState) => void;\n};\n\nexport const ConversationHistoryScreen = ({\n conversations,\n selectConversation,\n}: ConversationHistoryScreenProps): JSX.Element => {\n const [items, setItems] = React.useState(() => conversations.getAll());\n\n const handleRemoveConversation = (item: StoredAskAiState): void => {\n conversations.remove(item);\n setItems(conversations.getAll());\n };\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationHistoryScreen\">\n <ul>\n {items.map((item) => (\n <li\n key={item.objectID}\n className=\"DocSearch-Sidepanel-RecentConversation\"\n >\n <a\n href={item.url}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n\n selectConversation(item);\n }}\n >\n <div className=\"DocSearch-Sidepanel-RecentConversation-container\">\n <div className=\"DocSearch-Sidepanel-RecentConversation-icon\">\n <RecentIcon />\n </div>\n\n <div className=\"DocSearch-Sidepanel-RecentConversation-content\">\n <span className=\"DocSearch-Sidepanel-RecentConversation-title\">\n {item.hierarchy.lvl1}\n </span>\n </div>\n\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n type=\"button\"\n title=\"Remove conversation from history\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleRemoveConversation(item);\n }}\n >\n <CloseIcon />\n </button>\n </div>\n </div>\n </a>\n </li>\n ))}\n </ul>\n </div>\n );\n};\n","import React, { Fragment } from 'react';\nimport type { JSX } from 'react';\n\nimport { SearchIcon } from '../icons';\n\ntype AggregatedSearchBlockProps = {\n queries: string[];\n};\n\nconst before = 'Searched for ';\nconst separator = ', ';\nconst lastSeparator = ' and ';\nconst after = '';\n\nexport function AggregatedSearchBlock({\n queries,\n}: AggregatedSearchBlockProps): JSX.Element {\n return (\n <div className=\"DocSearch-AskAiScreen-MessageContent-Tool Tool--AggregatedResult\">\n <SearchIcon size={18} />\n <span>\n {before && <span>{before}</span>}\n {queries.map((q, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={q + idx}>\n <span className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\">\n &quot;{q}&quot;\n </span>\n {idx < queries.length - 2 && separator}\n {idx === queries.length - 2 && lastSeparator}\n </Fragment>\n ))}\n {after && <span>{after}</span>}\n </span>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type { JSX } from 'react';\nimport React, { memo, useMemo } from 'react';\n\nimport { type Exchange } from '../AskAiScreen';\nimport { ConversationPromptSuggestions } from '../components/ConversationPromptSuggestions';\nimport { FeedbackActions } from '../components/FeedbackActions';\nimport { SourcesPanel } from '../components/SourcesPanel';\nimport { ToolCall, type ToolCallTranslations } from '../components/ToolCall';\nimport { AlertIcon, LoadingIcon } from '../icons';\nimport { MemoizedMarkdown } from '../MemoizedMarkdown';\nimport type { StoredSearchPlugin } from '../stored-searches';\nimport type { OnAskAiFeedback, StoredAskAiState } from '../types';\nimport { type AIMessage, type ToolCalls } from '../types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n EMPTY_TOOLS,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from '../utils/ai';\nimport { groupConsecutiveToolResults } from '../utils/groupConsecutiveToolResults';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\n\nexport type ConversationScreenTranslations = Partial<\n ToolCallTranslations & {\n /** Text shown as an LLM disclaimer. */\n conversationDisclaimer: string;\n /** Text shown while assistant is reasoning. */\n reasoningText: string;\n /** Text show while assistant is thinking. */\n thinkingText: string;\n /** Text shown describing related sources. */\n relatedSourcesText: string;\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Text shown for copy button on code snippets. */\n copyButtonText: string;\n /** Message shown after clicking copy. */\n copyButtonCopiedText: string;\n /** Title for thumbs up feedback icon. */\n likeButtonTitle: string;\n /** Title for thumbs down feedback icon. */\n dislikeButtonTitle: string;\n /** Message displayed after feedback action. */\n thanksForFeedbackText: string;\n /** Title shown at the top of the negative feedback note panel. */\n feedbackPanelTitle: string;\n /** Placeholder for the negative feedback details textarea. */\n feedbackDetailsPlaceholder: string;\n /** Disclaimer shown inside the negative feedback note panel. */\n feedbackDisclaimerText: string;\n /** Submit button text for the negative feedback note panel. */\n feedbackSubmitButtonText: string;\n /** Accessible title for the negative feedback note panel close button. */\n feedbackCloseButtonTitle: string;\n /** Reason chip labels for the negative feedback note panel. */\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText;\n suggestedPromptsTitleText: string;\n }\n>;\n\nexport type ConversationScreenProps = {\n exchanges: Exchange[];\n conversations: StoredSearchPlugin<StoredAskAiState>;\n translations?: ConversationScreenTranslations;\n status: UseChatHelpers<AIMessage>['status'];\n handleFeedback?: OnAskAiFeedback;\n streamError?: Error;\n memoryEnabled?: boolean;\n tools?: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\ntype ConversationnExchangeProps = {\n exchange: Exchange;\n isLastExchange: boolean;\n status: ConversationScreenProps['status'];\n conversations: ConversationScreenProps['conversations'];\n translations?: ConversationScreenTranslations;\n onFeedback?: ConversationScreenProps['handleFeedback'];\n streamError?: ConversationScreenProps['streamError'];\n memoryEnabled?: boolean;\n tools: ToolCalls;\n onSelectPromptSuggestion: (prompt: string) => void;\n};\n\nconst ConversationExchange = React.forwardRef<\n HTMLDivElement,\n ConversationnExchangeProps\n>(\n (\n {\n exchange,\n translations = {},\n isLastExchange,\n conversations,\n onFeedback,\n status,\n streamError,\n memoryEnabled,\n tools,\n onSelectPromptSuggestion,\n },\n conversationRef\n ): JSX.Element => {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n reasoningText = 'Reasoning...',\n thinkingText = 'Thinking...',\n searchingText = 'Searching...',\n relatedSourcesText,\n stoppedStreamingText = 'You stopped this response',\n preToolCallText = 'Searching...',\n toolCallResultText = 'Searched for',\n copyButtonText = 'Copy',\n copyButtonCopiedText = 'Copied!',\n errorTitleText = 'Chat error',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const assistantParts = useMemo(\n () => groupConsecutiveToolResults(assistantMessage?.parts || []),\n [assistantMessage]\n );\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n const suggestedPrompts = React.useMemo(() => {\n if (!isLastExchange) return [];\n return getAgentPromptSuggestions(assistantMessage?.parts || []);\n }, [assistantMessage, isLastExchange]);\n\n const wasStopped =\n userMessage.metadata?.stopped || assistantMessage?.metadata?.stopped;\n const isThinking =\n ['submitted', 'streaming'].includes(status) &&\n !assistantParts.some((part) => part.type !== 'step-start');\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange && status === 'ready' && Boolean(assistantMessage)));\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div\n className=\"DocSearch-AskAiScreen-Response-Container\"\n ref={conversationRef}\n >\n <div className=\"DocSearch-AskAiScreen-Response\">\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user\">\n <p className=\"DocSearch-AskAiScreen-Query\">\n {userContent?.text ?? ''}\n </p>\n </div>\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant\">\n <div className=\"DocSearch-AskAiScreen-MessageContent\">\n {status === 'error' && streamError && isLastExchange && (\n <div className=\"DocSearch-AskAiScreen-Error\" role=\"alert\">\n <AlertIcon aria-hidden=\"true\" />\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <h4 className=\"DocSearch-AskAiScreen-Error-Title\">\n {errorTitleText}\n </h4>\n <MemoizedMarkdown\n content={streamError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n\n {assistantParts.map((part, idx) => {\n const index = idx;\n\n if (part.type === 'reasoning' && part.state === 'streaming') {\n return (\n <div\n key={index}\n className=\"DocSearch-AskAiScreen-MessageContent-Reasoning shimmer\"\n >\n <LoadingIcon className=\"DocSearch-AskAiScreen-SmallerLoadingIcon\" />\n <span className=\"shimmer\">{reasoningText}</span>\n </div>\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock key={index} queries={part.queries} />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n part={part}\n translations={{\n preToolCallText,\n searchingText,\n toolCallResultText,\n savedMemoryToolResultText,\n memoryToolResultText,\n }}\n tools={tools}\n memoryEnabled={memoryEnabled}\n />\n );\n }\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={false}\n />\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={copyButtonText}\n copyButtonCopiedText={copyButtonCopiedText}\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n return null;\n })}\n\n {isThinking && isLastExchange && assistantParts.length === 0 && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"shimmer\">{thinkingText}</span>\n <span className=\"DocSearch-AskAi-Thinking-Skeleton shimmer\" />\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short shimmer\" />\n </div>\n )}\n </div>\n\n {wasStopped && (\n <p className=\"DocSearck-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n />\n <FeedbackActions\n isSidepanel={true}\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent?.text || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {suggestedPrompts.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={suggestedPrompts}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n }\n);\n\nexport const ConversationScreen = memo(\n ({\n exchanges,\n translations = {},\n handleFeedback,\n tools = EMPTY_TOOLS,\n status,\n conversations,\n streamError,\n memoryEnabled,\n onSelectPromptSuggestion,\n }: ConversationScreenProps): JSX.Element => {\n const {\n conversationDisclaimer = 'Answers are generated with AI which can make mistakes. Verify responses.',\n } = translations;\n\n const mostRecentExchangeRef = React.useRef<HTMLDivElement>(null);\n const totalExchanges = exchanges.length;\n\n // Only scroll the most recent exchange into view when needed\n React.useEffect(() => {\n if (mostRecentExchangeRef.current) {\n mostRecentExchangeRef.current.scrollIntoView({\n behavior: 'smooth',\n block: 'start',\n });\n }\n }, [totalExchanges]);\n\n return (\n <div className=\"DocSearch-Sidepanel-ConversationScreen\">\n <p className=\"DocSearch-Sidepanel-ConversationScreen-disclaimer\">\n {conversationDisclaimer}\n </p>\n\n {exchanges.slice().map((exchange, idx) => {\n const isLastExchange = idx === exchanges.length - 1;\n return (\n <ConversationExchange\n key={exchange.id}\n exchange={exchange}\n translations={translations}\n isLastExchange={isLastExchange}\n ref={isLastExchange ? mostRecentExchangeRef : null}\n tools={tools}\n status={status}\n conversations={conversations}\n streamError={streamError}\n memoryEnabled={memoryEnabled}\n onFeedback={handleFeedback}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n );\n })}\n </div>\n );\n }\n);\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { SuggestedQuestionHit } from '../types';\n\nexport type NewConversationScreenTranslations = Partial<{\n /** Title to be shown on the new conversation/starting screen. */\n titleText: string;\n /** Introduction text displayed on the new conversation/starting screen. */\n introductionText: string;\n}>;\n\ntype NewConversationScreenProps = {\n suggestedQuestions: SuggestedQuestionHit[];\n onSelectQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationScreenTranslations;\n};\n\nexport const NewConversationScreen = ({\n suggestedQuestions,\n onSelectQuestion,\n translations = {},\n}: NewConversationScreenProps): JSX.Element => {\n const {\n titleText = 'How can I help you today?',\n introductionText = 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.',\n } = translations;\n\n return (\n <div className=\"DocSearch-Sidepanel-NewConversationScreen\">\n <h4 className=\"DocSearch-Sidepanel-Screen--title\">{titleText}</h4>\n <p className=\"DocSearch-Sidepanel-Screen--introduction\">\n {introductionText}\n </p>\n\n <div className=\"DocSearch-Sidepanel-List\">\n {suggestedQuestions.map((q) => (\n <button\n key={q.objectID}\n type=\"button\"\n className=\"DocSearch-Sidepanel-SuggestedQuestion\"\n title=\"View conversation\"\n onClick={() => {\n onSelectQuestion(q);\n }}\n >\n <span>{q.question}</span>\n </button>\n ))}\n </div>\n </div>\n );\n};\n","import React from 'react';\nimport type { JSX } from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport { SendIcon, StopIcon } from '../icons';\nimport { useIsMobile } from '../useIsMobile';\n\nexport type PromptFormTranslations = Partial<{\n /** Initial placeholder for the prompt input. */\n promptPlaceholderText: string;\n /** Placeholder text for wile a conversation is streaming. */\n promptAnsweringText: string;\n /** Placeholder text for after a question has already been asked. */\n promptAskAnotherQuestionText: string;\n /** Disclaimer text displayed beneath the prompt form. */\n promptDisclaimerText: string;\n promptLabelText: string;\n promptAriaLabelText: string;\n}>;\n\ntype Props = {\n exchanges: Exchange[];\n isStreaming: boolean;\n translations?: PromptFormTranslations;\n onSend: (prompt: string) => void;\n onStopStreaming: () => void;\n};\n\nconst MAX_PROMPT_ROWS = 8;\n\nexport const PromptForm = React.forwardRef<HTMLTextAreaElement, Props>(\n (\n { exchanges, isStreaming, translations = {}, onSend, onStopStreaming },\n ref\n ): JSX.Element => {\n const isMobile = useIsMobile();\n const [userPrompt, setUserPrompt] = React.useState('');\n const promptRef = React.useRef<HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(\n ref,\n () => promptRef.current as HTMLTextAreaElement\n );\n\n const {\n promptPlaceholderText = 'Ask a question',\n promptAnsweringText = 'Answering...',\n promptAskAnotherQuestionText = 'Ask another question',\n promptDisclaimerText = 'Answers are generated with AI which can make mistakes.',\n promptLabelText = 'Press Enter to send, or Shift and Enter for new line.',\n promptAriaLabelText = 'Prompt input',\n } = translations;\n\n const managePromptHeight = (): void => {\n if (!promptRef.current) return;\n\n const textArea = promptRef.current;\n const styles = getComputedStyle(textArea);\n\n const lineHeight = parseFloat(styles.lineHeight);\n const paddingTop = parseFloat(styles.paddingTop);\n const paddingBottom = parseFloat(styles.paddingBottom);\n const padding = paddingTop + paddingBottom;\n\n textArea.style.height = 'auto';\n\n const fullHeight = textArea.scrollHeight;\n const maxHeight = MAX_PROMPT_ROWS * lineHeight + padding;\n\n textArea.style.overflowY = fullHeight > maxHeight ? 'auto' : 'hidden';\n textArea.style.height = `${Math.min(fullHeight, maxHeight)}px`;\n };\n\n const handleSend = (): void => {\n if (isStreaming) return;\n\n const prompt = userPrompt.trim();\n\n if (prompt === '') return;\n\n onSend(prompt);\n\n setUserPrompt('');\n\n requestAnimationFrame(() => {\n promptRef.current?.focus();\n\n managePromptHeight();\n });\n };\n\n const handleKeyDown = (\n e: React.KeyboardEvent<HTMLTextAreaElement>\n ): void => {\n // Allow Enter to work normally (new line) when streaming\n if (isStreaming) return;\n\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n\n handleSend();\n }\n };\n\n React.useLayoutEffect(() => {\n managePromptHeight();\n }, [isMobile]);\n\n let promptPlaceholder = promptPlaceholderText;\n\n if (isStreaming) {\n promptPlaceholder = promptAnsweringText;\n } else if (exchanges.length > 0) {\n promptPlaceholder = promptAskAnotherQuestionText;\n }\n\n return (\n <div className=\"DocSearch-Sidepanel-Prompt\">\n <form\n className=\"DocSearch-Sidepanel-Prompt--form\"\n onSubmit={(e) => {\n e.preventDefault();\n\n if (isStreaming) return;\n\n handleSend();\n }}\n >\n <textarea\n ref={promptRef}\n placeholder={promptPlaceholder}\n className=\"DocSearch-Sidepanel-Prompt--textarea\"\n value={userPrompt}\n aria-label={promptAriaLabelText}\n aria-labelledby=\"prompt-label\"\n autoComplete=\"off\"\n translate=\"no\"\n rows={isMobile ? 1 : 2}\n onKeyDown={handleKeyDown}\n onInput={managePromptHeight}\n onChange={(e) => setUserPrompt(e.target.value)}\n />\n <span id=\"prompt-label\" className=\"sr-only\">\n {promptLabelText}\n </span>\n <div className=\"DocSearch-Sidepanel-Prompt--actions\">\n {isStreaming && (\n <button\n type=\"button\"\n title=\"Stop streaming\"\n className=\"DocSearch-Sidepanel-Prompt--stop\"\n onClick={onStopStreaming}\n >\n <StopIcon />\n </button>\n )}\n {!isStreaming && (\n <button\n type=\"submit\"\n aria-label=\"Send question\"\n title=\"Send question\"\n className=\"DocSearch-Sidepanel-Prompt--submit\"\n aria-disabled={userPrompt === ''}\n >\n <SendIcon />\n </button>\n )}\n </div>\n </form>\n <p className=\"DocSearch-Sidepanel-Prompt--disclaimer\">\n {promptDisclaimerText}\n </p>\n </div>\n );\n }\n);\n","import type { DocSearchTransformClient } from '..';\nimport { version } from '../version';\n\nexport const setSidepanelSearchClient = (\n client: DocSearchTransformClient\n): DocSearchTransformClient => {\n if (\n /docsearch-sidepanel.js \\(.*\\)/.test(\n client.transporter.algoliaAgent.value\n ) === false\n ) {\n client.addAlgoliaAgent('docsearch-sidepanel', version);\n }\n\n return client;\n};\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { Exchange } from '../AskAiScreen';\nimport {\n CloseIcon,\n ConversationHistoryIcon,\n EditIcon,\n ExpandIcon,\n FolderIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n SparklesIcon,\n} from '../icons';\nimport { BackIcon } from '../icons/BackIcon';\nimport { Menu } from '../Menu';\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { SidepanelState } from './types';\n\ntype BackButtonProps = {\n mobile?: boolean;\n onBack: () => void;\n disabled?: boolean;\n};\n\nconst BackButton = ({\n onBack,\n mobile = false,\n disabled = false,\n}: BackButtonProps): JSX.Element => {\n return (\n <button\n type=\"button\"\n className={`DocSearch-Action DocSearch-Sidepanel-Action-back${mobile ? ' mobile' : ''}`}\n title=\"Go back to previous screen\"\n aria-disabled={disabled}\n onClick={disabled ? undefined : onBack}\n >\n <BackIcon />\n </button>\n );\n};\n\nexport type HeaderTranslations = Partial<{\n /** The main title text shown on the header. */\n title: string;\n /** The title text shown on the conversation history screen. */\n conversationHistoryTitle: string;\n /** The text shown on the start a conversation button. */\n newConversationText: string;\n /** The text shown on the view conversation history button. */\n viewConversationHistoryText: string;\n}>;\n\ntype SidepanelHeaderProps = {\n sidepanelState: SidepanelState;\n exchanges: Exchange[];\n setSidepanelState: (state: SidepanelState) => void;\n onNewConversation: () => void;\n onToggleExpanded: () => void;\n onClose: () => void;\n translations?: HeaderTranslations;\n hasConversations: boolean;\n isStreaming: boolean;\n};\n\nexport const SidepanelHeader = React.memo(\n ({\n sidepanelState,\n exchanges,\n setSidepanelState,\n onNewConversation,\n onToggleExpanded,\n onClose,\n translations = {},\n hasConversations,\n isStreaming,\n }: SidepanelHeaderProps): JSX.Element => {\n const {\n title = 'Ask AI',\n conversationHistoryTitle = 'My conversation history',\n newConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n } = translations;\n\n const isMobile = useIsMobile();\n\n const goToConversationHistory = (): void => {\n setSidepanelState('conversation-history');\n };\n\n const onBack = React.useCallback((): void => {\n if (exchanges.length > 0) {\n setSidepanelState('conversation');\n } else {\n setSidepanelState('new-conversation');\n }\n }, [exchanges, setSidepanelState]);\n\n const newConversationDisabled =\n sidepanelState === 'new-conversation' && exchanges.length < 1;\n\n let header = title;\n\n if (sidepanelState === 'conversation-history') {\n header = conversationHistoryTitle;\n }\n\n if (isMobile) {\n header = title;\n }\n\n return (\n <header className=\"DocSearch-Sidepanel-Header\">\n <div className=\"DocSearch-Sidepanel-Header--left\">\n <BackButton mobile={true} disabled={isStreaming} onBack={onBack} />\n\n {sidepanelState === 'conversation-history' && (\n <div className=\"DocSearch-Divider\" />\n )}\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={newConversationText}\n onClick={onNewConversation}\n >\n <EditIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n\n <button\n type=\"button\"\n className=\"DocSearch-Action\"\n title={viewConversationHistoryText}\n onClick={goToConversationHistory}\n >\n <FolderIcon />\n </button>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--center\">\n <BackButton disabled={isStreaming} onBack={onBack} />\n <SparklesIcon className=\"DocSearch-Sidepanel-Header-TitleIcon\" />\n <h2 className=\"DocSearch-Sidepanel-Title\">{header}</h2>\n </div>\n <div className=\"DocSearch-Sidepanel-Header--right\">\n {sidepanelState !== 'conversation-history' &&\n (!newConversationDisabled || hasConversations) && (\n <Menu>\n <Menu.Trigger\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-menu\"\n disabled={isStreaming}\n >\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n {!newConversationDisabled && (\n <Menu.Item onClick={onNewConversation}>\n <NewConversationIcon />\n {newConversationText}\n </Menu.Item>\n )}\n {hasConversations && (\n <Menu.Item onClick={goToConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n )}\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-expand\"\n title=\"Expand or collapse Sidepanel\"\n onClick={onToggleExpanded}\n >\n <ExpandIcon />\n </button>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-Sidepanel-Action-close\"\n title=\"Close Sidepanel\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n </div>\n </header>\n );\n }\n);\n","import { useLayoutEffect, useRef } from 'react';\n\nimport { useIsMobile } from '../useIsMobile';\n\nimport type { PanelSide, PanelVariant } from './types';\n\ntype UseManageSidepanelLayoutProps = {\n variant: PanelVariant;\n side: PanelSide;\n selectors: string;\n isOpen: boolean;\n expectedWidth: string;\n};\n\nexport function useManageSidepanelLayout({\n variant,\n selectors,\n isOpen,\n expectedWidth,\n side,\n}: UseManageSidepanelLayoutProps): void {\n const targetRef = useRef<HTMLElement | null>(null);\n const lastSelectorRef = useRef<string | null>(null);\n const isMobile = useIsMobile();\n\n useLayoutEffect(() => {\n if (variant === 'floating' || isMobile) return;\n\n if (lastSelectorRef.current !== selectors) {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n\n const candidates = Array.from(document.querySelectorAll(selectors));\n const nextTarget: HTMLElement | null =\n (candidates[0] as HTMLElement) || document.body;\n targetRef.current = nextTarget;\n lastSelectorRef.current = selectors;\n\n if (targetRef.current) {\n targetRef.current.style.transition = `margin-${side} 280ms cubic-bezier(0.22, 1, 0.36, 1)`;\n }\n }\n\n const target = targetRef.current;\n if (!target) return;\n\n const offset = isOpen ? expectedWidth : '0px';\n\n if (side === 'left') {\n target.style.marginLeft = offset;\n } else {\n target.style.marginRight = offset;\n }\n }, [isOpen, expectedWidth, variant, selectors, side, isMobile]);\n\n useLayoutEffect(() => {\n return (): void => {\n if (targetRef.current) {\n if (side === 'left') {\n targetRef.current.style.marginLeft = '';\n } else {\n targetRef.current.style.marginRight = '';\n }\n targetRef.current.style.transition = '';\n }\n };\n }, [side]);\n}\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport { useEffect } from 'react';\n\ntype UseSidepanelKeyboardEventsProps = {\n onClose: () => void;\n onOpen: () => void;\n isOpen: boolean;\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\nexport function useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n}: UseSidepanelKeyboardEventsProps): void {\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent): void {\n if (isOpen && e.code === 'Escape') {\n onClose();\n return;\n }\n\n const cmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n\n if (!cmdIEnabled) return;\n\n const isCmdI = e.key?.toLowerCase() === 'i' && (e.metaKey || e.ctrlKey);\n\n if (isCmdI) {\n e.preventDefault();\n\n if (isOpen) {\n onClose();\n } else {\n onOpen();\n }\n }\n }\n\n window.addEventListener('keydown', onKeyDown);\n\n return (): void => {\n window.removeEventListener('keydown', onKeyDown);\n };\n }, [isOpen, onClose, onOpen, keyboardShortcuts]);\n}\n","import React from 'react';\n\nconst BASE_WIDTH = 360;\nconst EXPANDED_WIDTH = 580;\n\ntype UseSidepanelWidthProps = {\n isExpanded: boolean;\n width?: number | string;\n expandedWidth?: number | string;\n};\n\nexport const useSidepanelWidth = ({\n isExpanded,\n width,\n expandedWidth,\n}: UseSidepanelWidthProps): string => {\n const baseWidth = React.useMemo(() => {\n return typeof width === 'number'\n ? `${width}px`\n : (width ?? `${BASE_WIDTH}px`);\n }, [width]);\n\n const resolvedExpandedWidth = React.useMemo(() => {\n return typeof expandedWidth === 'number'\n ? `${expandedWidth}px`\n : (expandedWidth ?? `${EXPANDED_WIDTH}px`);\n }, [expandedWidth]);\n\n const expectedWidth = isExpanded ? resolvedExpandedWidth : baseWidth;\n\n return expectedWidth;\n};\n","import type { SidepanelShortcuts, InitialAskAiMessage } from '@docsearch/core';\nimport React, { useCallback } from 'react';\nimport type { JSX } from 'react';\n\nimport { AlgoliaLogo, type AlgoliaLogoTranslations } from '../AlgoliaLogo';\nimport type {\n DocSearchSidepanelProps,\n SidepanelSearchParameters,\n} from '../Sidepanel';\nimport type { StoredAskAiState, SuggestedQuestionHit } from '../types';\nimport { useAskAi } from '../useAskAi';\nimport { useIsMobile } from '../useIsMobile';\nimport { useSearchClient } from '../useSearchClient';\nimport { useSuggestedQuestions } from '../useSuggestedQuestions';\nimport { EMPTY_TOOLS, buildDummyAskAiHit } from '../utils/ai';\n\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { ConversationScreenTranslations } from './ConversationScreen';\nimport { ConversationScreen } from './ConversationScreen';\nimport type { NewConversationScreenTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport { PromptForm, type PromptFormTranslations } from './PromptForm';\nimport { setSidepanelSearchClient } from './setSidepanelSearchClient';\nimport type { HeaderTranslations } from './SidepanelHeader';\nimport { SidepanelHeader } from './SidepanelHeader';\nimport type { PanelSide, PanelVariant, SidepanelState } from './types';\nimport { useManageSidepanelLayout } from './useManageSidepanelLayout';\nimport { useSidepanelKeyboardEvents } from './useSidepanelKeyboardEvents';\nimport { useSidepanelWidth } from './useSidepanelWidth';\n\n/**\n * Imperative handle exposed by the Sidepanel component for programmatic\n * control.\n */\nexport interface SidepanelRef {\n /** Opens the sidepanel. */\n open: () => void;\n /** Closes the sidepanel. */\n close: () => void;\n /** Returns true once the component is mounted and ready. */\n readonly isReady: boolean;\n /** Returns true if the sidepanel is currently open. */\n readonly isOpen: boolean;\n}\n\nexport type SidepanelTranslations = Partial<{\n /** Translation texts for the Sidepanel header. */\n header: HeaderTranslations;\n /** Translation texts for the prompt form. */\n promptForm: PromptFormTranslations;\n /** Translation texts for the conversation screen. */\n conversationScreen: ConversationScreenTranslations;\n /** Translation texts for the new conversation/starting screen. */\n newConversationScreen: NewConversationScreenTranslations;\n /** Translation text for the Algolia logo. */\n logo: AlgoliaLogoTranslations;\n}>;\n\nexport type SidepanelProps = Pick<\n DocSearchSidepanelProps,\n 'indices' | 'memory' | 'tools'\n> & {\n /**\n * Variant of the Sidepanel positioning.\n *\n * - `inline` pushes page content when opened\n * - `floating` is positioned above all other content on page.\n *\n * @default 'floating'\n */\n variant?: PanelVariant;\n /**\n * Side of the page which the panel will originate from.\n *\n * @default 'right'\n */\n side?: PanelSide;\n /**\n * The selector of the element to push when Sidepanel opens with `inline`\n * variant.\n *\n * @default `'#root, main, .app, body'`\n */\n pushSelector?: string;\n /**\n * Width of the Sidepanel (px or any CSS width).\n *\n * @default `360px`\n */\n width?: number | string;\n /**\n * Width when expanded (px or any CSS width).\n *\n * @default `580px`\n */\n expandedWidth?: number | string;\n /**\n * The container element where the panel should be portaled to.\n *\n * @default `document.body`\n */\n portalContainer?: DocumentFragment | Element | null;\n /**\n * Enables displaying suggested questions on new conversation screen.\n *\n * @default false\n */\n suggestedQuestions?: boolean;\n /** Translations specific to the Sidepanel panel. */\n translations?: SidepanelTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = Omit<\n DocSearchSidepanelProps,\n 'button' | 'indices' | 'memory' | 'panel' | 'tools'\n> &\n SidepanelProps &\n SidepanelSearchParameters & {\n isOpen?: boolean;\n onOpen: () => void;\n onClose: () => void;\n initialMessage?: InitialAskAiMessage;\n };\n\nfunction SidepanelInner(\n {\n isOpen = false,\n onOpen,\n onClose,\n assistantId,\n apiKey,\n appId,\n indexName,\n variant = 'floating',\n searchParameters,\n pushSelector,\n width,\n expandedWidth,\n suggestedQuestions: suggestedQuestionsEnabled = false,\n translations = {},\n keyboardShortcuts,\n side = 'right',\n initialMessage,\n tools = EMPTY_TOOLS,\n memory,\n indices,\n }: Props,\n ref: React.ForwardedRef<SidepanelRef>\n): JSX.Element {\n const [isExpanded, setIsExpanded] = React.useState(false);\n const [sidepanelState, setSidepanelState] =\n React.useState<SidepanelState>('new-conversation');\n const [stoppedStreaming, setStoppedStreaming] = React.useState(false);\n const sidepanelContainerRef = React.useRef<HTMLDivElement>(null);\n const promptInputRef = React.useRef<HTMLTextAreaElement>(null);\n const isMobile = useIsMobile();\n\n const expectedWidth = useSidepanelWidth({\n isExpanded,\n width,\n expandedWidth,\n });\n\n const selectors = React.useMemo(\n () => pushSelector ?? '#root, main, .app, body',\n [pushSelector]\n );\n\n const toggleIsExpanded = useCallback((): void => {\n setIsExpanded(!isExpanded);\n }, [isExpanded]);\n\n const searchClient = useSearchClient(appId, apiKey, setSidepanelSearchClient);\n\n const {\n chatId,\n status,\n sendMessage,\n stopAskAiStreaming,\n isStreaming,\n exchanges,\n conversations,\n messages,\n sendFeedback,\n askAiError,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n appId,\n indexName,\n assistantId,\n apiKey,\n searchParameters,\n tools,\n memory,\n indices,\n });\n\n const suggestedQuestions = useSuggestedQuestions({\n assistantId,\n suggestedQuestionsEnabled,\n searchClient,\n });\n\n const prevStatus = React.useRef(status);\n\n const handleSend = React.useCallback(\n (prompt: string): void => {\n setStoppedStreaming(false);\n\n sendMessage({ text: prompt });\n setSidepanelState('conversation');\n },\n [sendMessage]\n );\n\n const handleStartNewConversation = (): void => {\n startNewConversation();\n setSidepanelState('new-conversation');\n };\n\n const handleSelectQuestion = (question: SuggestedQuestionHit): void => {\n setStoppedStreaming(false);\n startNewConversation();\n sendMessage(\n { text: question.question },\n {\n body: {\n suggestedQuestionId: question.objectID,\n },\n }\n );\n setSidepanelState('conversation');\n };\n\n const handleStopStreaming = (): void => {\n setStoppedStreaming(true);\n stopAskAiStreaming();\n };\n\n const handleSelectConversation = React.useCallback(\n (conversation: StoredAskAiState): void => {\n if (conversation.messages) {\n restoreConversation(conversation.messages, conversation.chatId);\n } else if (conversation.query) {\n sendMessage({ text: conversation.query });\n }\n\n setSidepanelState('conversation');\n },\n [sendMessage, restoreConversation]\n );\n\n useManageSidepanelLayout({\n variant,\n expectedWidth,\n selectors,\n isOpen,\n side,\n });\n\n useSidepanelKeyboardEvents({\n onClose,\n onOpen,\n isOpen,\n keyboardShortcuts,\n });\n\n // Expose imperative handle for programmatic control\n React.useImperativeHandle(\n ref,\n () => ({\n open: onOpen,\n close: onClose,\n get isReady(): boolean {\n return true;\n },\n get isOpen(): boolean {\n return isOpen;\n },\n }),\n [onOpen, onClose, isOpen]\n );\n\n React.useEffect(() => {\n if (prevStatus.current === 'streaming' && status === 'ready') {\n if (stoppedStreaming && messages.at(-1)) {\n messages.at(-1)!.metadata = {\n stopped: true,\n };\n }\n\n for (const part of messages[0].parts) {\n if (part.type === 'text') {\n conversations.add(buildDummyAskAiHit(part.text, messages, chatId));\n }\n }\n }\n\n prevStatus.current = status;\n }, [conversations, status, messages, stoppedStreaming, chatId]);\n\n React.useEffect(() => {\n function setFullViewportHeight(): void {\n if (sidepanelContainerRef.current) {\n const vh = window.innerHeight * 0.01;\n sidepanelContainerRef.current.style.setProperty('--sp-vh', `${vh}px`);\n }\n }\n\n setFullViewportHeight();\n\n window.addEventListener('resize', setFullViewportHeight);\n\n return (): void => {\n window.removeEventListener('resize', setFullViewportHeight);\n };\n }, []);\n\n React.useEffect(() => {\n if (!initialMessage) return;\n\n let selectedConversation: StoredAskAiState | undefined;\n\n if (initialMessage.messageId) {\n selectedConversation = conversations.getConversation?.(\n initialMessage.messageId\n );\n }\n\n if (selectedConversation) {\n handleSelectConversation(selectedConversation);\n } else {\n startNewConversation();\n sendMessage(\n {\n text: initialMessage.query,\n },\n initialMessage.suggestedQuestionId\n ? {\n body: {\n suggestedQuestionId: initialMessage.suggestedQuestionId,\n },\n }\n : {}\n );\n setSidepanelState('conversation');\n }\n }, [\n initialMessage,\n sendMessage,\n conversations,\n handleSelectConversation,\n startNewConversation,\n ]);\n\n // Autofocus the prompt input when the sidepanel opens and blur it when\n // it closes. Disabled on mobile because focusing the textarea triggers the\n // virtual keyboard which disrupts the layout — this is a known issue that\n // has not been resolved yet.\n React.useEffect(() => {\n if (isOpen && !isMobile) {\n promptInputRef.current?.focus();\n }\n\n if (!isOpen) {\n promptInputRef.current?.blur();\n }\n }, [isOpen, isMobile]);\n\n return (\n <div\n className={`DocSearch-Sidepanel-Container ${variant} side-${side}${isOpen ? ' is-open' : ''}${isExpanded ? ' is-expanded' : ''}`}\n style={\n {\n '--sp-width': expectedWidth,\n } as React.CSSProperties\n }\n role=\"dialog\"\n tabIndex={-1}\n ref={sidepanelContainerRef}\n >\n <aside\n id=\"docsearch-sidepanel\"\n className={`DocSearch-Sidepanel ${sidepanelState}`}\n >\n <SidepanelHeader\n sidepanelState={sidepanelState}\n exchanges={exchanges}\n setSidepanelState={setSidepanelState}\n hasConversations={conversations.getAll().length > 0}\n isStreaming={isStreaming}\n onNewConversation={handleStartNewConversation}\n onToggleExpanded={toggleIsExpanded}\n onClose={onClose}\n />\n <div className=\"DocSearch-Sidepanel-Content\">\n {sidepanelState === 'new-conversation' && (\n <NewConversationScreen\n suggestedQuestions={suggestedQuestions}\n translations={translations.newConversationScreen}\n onSelectQuestion={handleSelectQuestion}\n />\n )}\n {sidepanelState === 'conversation' && (\n <ConversationScreen\n exchanges={exchanges}\n status={status}\n conversations={conversations}\n handleFeedback={sendFeedback}\n translations={translations.conversationScreen}\n streamError={askAiError}\n memoryEnabled={memory?.enabled ?? false}\n tools={tools}\n onSelectPromptSuggestion={handleSend}\n />\n )}\n {sidepanelState === 'conversation-history' && (\n <ConversationHistoryScreen\n conversations={conversations}\n selectConversation={handleSelectConversation}\n />\n )}\n </div>\n <PromptForm\n ref={promptInputRef}\n exchanges={exchanges}\n isStreaming={isStreaming}\n translations={translations.promptForm}\n onSend={handleSend}\n onStopStreaming={handleStopStreaming}\n />\n <footer className=\"DocSearch-Sidepanel-Footer\">\n <span className=\"DocSearch-Logo DocSearch-Sidepanel--powered-by\">\n <AlgoliaLogo translations={translations.logo} />\n </span>\n </footer>\n </aside>\n </div>\n );\n}\n\nexport const Sidepanel = React.forwardRef(SidepanelInner);\n","import type { SidepanelShortcuts } from '@docsearch/core';\nimport React, { useEffect, useState } from 'react';\nimport type { JSX } from 'react';\n\nimport { SparklesIcon } from '../icons';\nimport { ACTION_KEY_APPLE, ACTION_KEY_DEFAULT, isAppleDevice } from '../utils';\n\nexport type SidepanelButtonTranslations = Partial<{\n /**\n * Text to be displayed when button has variant: `inline`.\n *\n * @default 'Ask AI'\n */\n buttonText: string;\n /**\n * Aria label text for the button.\n *\n * @default 'Ask AI'\n */\n buttonAriaLabel: string;\n}>;\n\nexport type ButtonVariant = 'floating' | 'inline';\n\nexport type SidepanelButtonProps = {\n /**\n * Variant of the button positioning and styling.\n *\n * - `inline` displays the button inline where rendered, with extra text\n * - `floating` displays the button floating in bottom right of screen with just\n * icon.\n *\n * @default 'floating'\n */\n variant?: ButtonVariant;\n /** Translations specific to the Sidepanel button. */\n translations?: SidepanelButtonTranslations;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n};\n\ntype Props = React.ComponentProps<'button'> & SidepanelButtonProps;\n\nexport const SidepanelButton = ({\n variant = 'floating',\n keyboardShortcuts,\n translations = {},\n ...props\n}: Props): JSX.Element => {\n const { buttonText = 'Ask AI', buttonAriaLabel = 'Ask AI' } = translations;\n const [key, setKey] = useState<\n typeof ACTION_KEY_APPLE | typeof ACTION_KEY_DEFAULT | null\n >(null);\n\n useEffect(() => {\n if (typeof navigator !== 'undefined') {\n isAppleDevice() ? setKey(ACTION_KEY_APPLE) : setKey(ACTION_KEY_DEFAULT);\n }\n }, []);\n\n const actionKeyAltText = key === ACTION_KEY_DEFAULT ? 'Control' : 'Meta';\n const isCtrlCmdIEnabled = keyboardShortcuts?.['Ctrl/Cmd+I'] !== false;\n const shortcut = `${actionKeyAltText}+i`;\n\n return (\n <button\n className={`DocSearch-SidepanelButton ${variant}`}\n type=\"button\"\n aria-label={\n isCtrlCmdIEnabled ? `${buttonAriaLabel} (${shortcut})` : buttonAriaLabel\n }\n aria-keyshortcuts={isCtrlCmdIEnabled ? shortcut : undefined}\n {...(variant === 'floating' ? { tabIndex: -1 } : {})}\n {...props}\n >\n <SparklesIcon />\n {variant !== 'floating' && buttonText}\n </button>\n );\n};\n","import { DocSearch, useDocSearch } from '@docsearch/core';\nimport type {\n DocSearchCallbacks,\n DocSearchRef,\n DocSearchTheme,\n SidepanelShortcuts,\n} from '@docsearch/core';\nimport type { JSX } from 'react';\nimport React from 'react';\nimport { createPortal } from 'react-dom';\n\nimport type {\n AgentStudioIndices,\n AgentStudioSearchParameters,\n Memory,\n} from './DocSearchAI';\nimport type {\n SidepanelButtonProps,\n SidepanelProps as SidepanelPanelProps,\n} from './Sidepanel/index';\nimport { SidepanelButton, Sidepanel } from './Sidepanel/index';\nimport type { ToolCalls } from './types/AskiAi';\n\nexport type { DocSearchRef, DocSearchCallbacks } from '@docsearch/core';\n\nexport type SidepanelSearchParameters = {\n /**\n * The search parameters to use for the ask AI feature. Keyed by the index\n * name.\n *\n * @example\n * {\n * \"INDEX_NAME\": { distinct: false }\n * }\n */\n searchParameters?: AgentStudioSearchParameters;\n};\n\nexport type DocSearchSidepanelProps = DocSearchCallbacks & {\n /** The assistant ID to use for the ask AI feature. */\n assistantId: string;\n /** Public api key with search permissions for the index. */\n apiKey: string;\n /** Algolia application id used by the search client. */\n appId: string;\n /**\n * The index name to use for the ask AI feature. Your assistant will search\n * this index for relevant documents.\n */\n indexName: string;\n /**\n * Configuration for keyboard shortcuts. Allows enabling/disabling specific\n * shortcuts.\n *\n * @default `{ 'Ctrl/Cmd+I': true }`\n */\n keyboardShortcuts?: SidepanelShortcuts;\n /**\n * Theme overrides applied to the Sidepanel button and panel.\n *\n * @default 'light'\n */\n theme?: DocSearchTheme;\n /** Props specific to the Sidepanel button. */\n button?: Omit<SidepanelButtonProps, 'keyboardShortcuts'>;\n /** Props specific to the Sidepanel panel. */\n panel?: Omit<SidepanelPanelProps, 'keyboardShortcuts'>;\n /**\n * Use custom tools driven by Agent Studio.\n *\n * For best performance, memoize this object with `useMemo` or define it\n * outside the component. Inline object literals will be recreated every\n * render but will not affect correctness.\n */\n tools?: ToolCalls;\n /**\n * Configuration for the Agent Studio memory feature.\n *\n * @example\n * { enabled: true, userToken: '{{SERVER_GENERATED_JWT_TOKEN}}' }\n *\n * @see https://www.algolia.com/doc/guides/algolia-ai/agent-studio/how-to/memory/overview\n */\n memory?: Memory;\n /** List of dynamic indices for the Agent Studio search tool to use. */\n indices?: AgentStudioIndices[];\n};\n\ntype SidepanelProps = DocSearchSidepanelProps & SidepanelSearchParameters;\n\nfunction DocSearchSidepanelComponent(\n {\n keyboardShortcuts,\n theme,\n onReady,\n onOpen,\n onClose,\n onSidepanelOpen,\n onSidepanelClose,\n ...props\n }: SidepanelProps,\n ref: React.ForwardedRef<DocSearchRef>\n): JSX.Element {\n return (\n <DocSearch\n keyboardShortcuts={keyboardShortcuts}\n theme={theme}\n ref={ref}\n onReady={onReady}\n onOpen={onOpen}\n onClose={onClose}\n onSidepanelOpen={onSidepanelOpen}\n onSidepanelClose={onSidepanelClose}\n >\n <DocSearchSidepanelComp {...props} />\n </DocSearch>\n );\n}\n\nexport const DocSearchSidepanel = React.forwardRef(DocSearchSidepanelComponent);\n\nfunction DocSearchSidepanelComp({\n button: buttonProps = {},\n panel: { portalContainer, ...panelProps } = {},\n ...rootProps\n}: DocSearchSidepanelProps): JSX.Element {\n const {\n docsearchState,\n setDocsearchState,\n keyboardShortcuts,\n registerView,\n initialAskAiMessage,\n } = useDocSearch();\n\n const toggleSidepanelState = React.useCallback(() => {\n setDocsearchState(docsearchState === 'sidepanel' ? 'ready' : 'sidepanel');\n }, [docsearchState, setDocsearchState]);\n\n const handleClose = (): void => {\n setDocsearchState('ready');\n };\n\n const handleOpen = (): void => {\n setDocsearchState('sidepanel');\n };\n\n const containerElement = React.useMemo(\n () => portalContainer ?? document.body,\n [portalContainer]\n );\n\n React.useEffect(() => {\n registerView('sidepanel');\n }, [registerView]);\n\n const ButtonComp = React.useMemo(\n () => (\n <SidepanelButton\n keyboardShortcuts={keyboardShortcuts}\n onClick={toggleSidepanelState}\n {...buttonProps}\n />\n ),\n [keyboardShortcuts, toggleSidepanelState, buttonProps]\n );\n\n return (\n <>\n {buttonProps.variant === 'inline'\n ? ButtonComp\n : createPortal(ButtonComp, containerElement)}\n {createPortal(\n <Sidepanel\n initialMessage={initialAskAiMessage}\n isOpen={docsearchState === 'sidepanel'}\n onClose={handleClose}\n onOpen={handleOpen}\n {...rootProps}\n {...panelProps}\n keyboardShortcuts={keyboardShortcuts}\n />,\n containerElement\n )}\n </>\n );\n}\n\nexport * from './Sidepanel/index';\n"],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import "./index-Dl8FMlR5.js";
2
+ import React from "react";
3
+ //#region src/types/KeyboardShortcuts.d.ts
4
+ interface KeyboardShortcuts {
5
+ /**
6
+ * Enable/disable the Ctrl/Cmd+K shortcut to toggle the search modal.
7
+ *
8
+ * @default true
9
+ */
10
+ 'Ctrl/Cmd+K'?: boolean;
11
+ /**
12
+ * Enable/disable the / shortcut to open the search modal.
13
+ *
14
+ * @default true
15
+ */
16
+ '/'?: boolean;
17
+ }
18
+ //#endregion
19
+ //#region src/useDocSearchKeyboardEvents.d.ts
20
+ interface UseDocSearchKeyboardEventsProps {
21
+ isOpen: boolean;
22
+ onOpen: () => void;
23
+ onClose: () => void;
24
+ /**
25
+ * Deprecated: Still here for backwards compat.
26
+ *
27
+ * @deprecated
28
+ */
29
+ onInput?: (event: KeyboardEvent) => void;
30
+ /**
31
+ * Deprecated: Still here for backwards compat.
32
+ *
33
+ * @deprecated
34
+ */
35
+ searchButtonRef?: React.RefObject<HTMLButtonElement | null>;
36
+ isAskAiActive: boolean;
37
+ onAskAiToggle: (toggle: boolean) => void;
38
+ keyboardShortcuts?: KeyboardShortcuts;
39
+ }
40
+ declare function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, isAskAiActive, onAskAiToggle, keyboardShortcuts }: UseDocSearchKeyboardEventsProps): void;
41
+ //#endregion
42
+ export { useDocSearchKeyboardEvents as n, KeyboardShortcuts as r, UseDocSearchKeyboardEventsProps as t };
43
+ //# sourceMappingURL=useDocSearchKeyboardEvents-68G8dw6c.d.ts.map
@@ -1,41 +1,2 @@
1
- import React from 'react';
2
-
3
- interface KeyboardShortcuts {
4
- /**
5
- * Enable/disable the Ctrl/Cmd+K shortcut to toggle the search modal.
6
- *
7
- * @default true
8
- */
9
- 'Ctrl/Cmd+K'?: boolean;
10
- /**
11
- * Enable/disable the / shortcut to open the search modal.
12
- *
13
- * @default true
14
- */
15
- '/'?: boolean;
16
- }
17
-
18
- interface UseDocSearchKeyboardEventsProps {
19
- isOpen: boolean;
20
- onOpen: () => void;
21
- onClose: () => void;
22
- /**
23
- * Deprecated: Still here for backwards compat.
24
- *
25
- * @deprecated
26
- */
27
- onInput?: (event: KeyboardEvent) => void;
28
- /**
29
- * Deprecated: Still here for backwards compat.
30
- *
31
- * @deprecated
32
- */
33
- searchButtonRef?: React.RefObject<HTMLButtonElement | null>;
34
- isAskAiActive: boolean;
35
- onAskAiToggle: (toggle: boolean) => void;
36
- keyboardShortcuts?: KeyboardShortcuts;
37
- }
38
- declare function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, isAskAiActive, onAskAiToggle, keyboardShortcuts, }: UseDocSearchKeyboardEventsProps): void;
39
-
40
- export { useDocSearchKeyboardEvents };
41
- export type { UseDocSearchKeyboardEventsProps };
1
+ import { n as useDocSearchKeyboardEvents, t as UseDocSearchKeyboardEventsProps } from "./useDocSearchKeyboardEvents-68G8dw6c.js";
2
+ export { UseDocSearchKeyboardEventsProps, useDocSearchKeyboardEvents };
@@ -1 +1,43 @@
1
- import e from"react";function t(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t);if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function r(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}function n(e){for(var n=1;n<arguments.length;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?r(Object(o),!0).forEach(function(r){t(e,r,o[r])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(o)):r(Object(o)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(o,t))})}return e}var o={"Ctrl/Cmd+K":!0,"/":!0};function i(t){var r,i=t.isOpen,c=t.onOpen,a=t.onClose,u=t.isAskAiActive,s=t.onAskAiToggle,f=t.keyboardShortcuts,p=(r=f,n(n({},o),r));e.useEffect(function(){function e(e){var t;if(i&&"Escape"===e.code&&u)s(!1);else{var r=p["Ctrl/Cmd+K"]&&"k"===(null===(t=e.key)||void 0===t?void 0:t.toLowerCase())&&(e.metaKey||e.ctrlKey),n=p["/"]&&"/"===e.key;("Escape"===e.code&&i||r||!function(e){var t=e.composedPath()[0],r=t.tagName;return t.isContentEditable||"INPUT"===r||"SELECT"===r||"TEXTAREA"===r}(e)&&n&&!i)&&(e.preventDefault(),i?a():document.body.classList.contains("DocSearch--active")||c())}}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}},[i,c,a,u,s,p])}export{i as useDocSearchKeyboardEvents};
1
+ import { t as getKeyboardShortcuts } from "./keyboardShortcuts-C-lx6Xt7.js";
2
+ import React from "react";
3
+
4
+ //#region src/useDocSearchKeyboardEvents.ts
5
+ function isEditingContent(event) {
6
+ const element = event.composedPath()[0];
7
+ const tagName = element.tagName;
8
+ return element.isContentEditable || tagName === "INPUT" || tagName === "SELECT" || tagName === "TEXTAREA";
9
+ }
10
+ function useDocSearchKeyboardEvents({ isOpen, onOpen, onClose, isAskAiActive, onAskAiToggle, keyboardShortcuts }) {
11
+ const resolvedShortcuts = getKeyboardShortcuts(keyboardShortcuts);
12
+ React.useEffect(() => {
13
+ function onKeyDown(event) {
14
+ var _event$key;
15
+ if (isOpen && event.code === "Escape" && isAskAiActive) {
16
+ onAskAiToggle(false);
17
+ return;
18
+ }
19
+ const isCmdK = resolvedShortcuts["Ctrl/Cmd+K"] && ((_event$key = event.key) === null || _event$key === void 0 ? void 0 : _event$key.toLowerCase()) === "k" && (event.metaKey || event.ctrlKey);
20
+ const isSlash = resolvedShortcuts["/"] && event.key === "/";
21
+ if (event.code === "Escape" && isOpen || isCmdK || !isEditingContent(event) && isSlash && !isOpen) {
22
+ event.preventDefault();
23
+ if (isOpen) onClose();
24
+ else if (!document.body.classList.contains("DocSearch--active")) onOpen();
25
+ }
26
+ }
27
+ window.addEventListener("keydown", onKeyDown);
28
+ return () => {
29
+ window.removeEventListener("keydown", onKeyDown);
30
+ };
31
+ }, [
32
+ isOpen,
33
+ onOpen,
34
+ onClose,
35
+ isAskAiActive,
36
+ onAskAiToggle,
37
+ resolvedShortcuts
38
+ ]);
39
+ }
40
+
41
+ //#endregion
42
+ export { useDocSearchKeyboardEvents };
43
+ //# sourceMappingURL=useDocSearchKeyboardEvents.js.map
@@ -0,0 +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"}