UNPKG

react-instantsearch

Version:
228 lines (225 loc) 12.1 kB
import { _ } from '@swc/helpers/esm/_define_property.js'; import { _ as _$4 } from '@swc/helpers/esm/_object_spread.js'; import { _ as _$5 } from '@swc/helpers/esm/_object_spread_props.js'; import { _ as _$2 } from '@swc/helpers/esm/_object_without_properties.js'; import { _ as _$3 } from '@swc/helpers/esm/_sliced_to_array.js'; import { _ as _$1 } from '@swc/helpers/esm/_to_array.js'; import { createChatComponent } from 'instantsearch-ui-components'; import { SearchIndexToolType, RecommendToolType, DisplayResultsToolType, MemorizeToolType, MemorySearchToolType, PonderToolType } from 'instantsearch.js/es/lib/chat/index.js'; export { DisplayResultsToolType, MemorizeToolType, MemorySearchToolType, PonderToolType, RecommendToolType, SearchIndexToolType } from 'instantsearch.js/es/lib/chat/index.js'; import React, { createElement, Fragment, memo, useState, useRef, useMemo, useImperativeHandle, useEffect } from 'react'; import { useInstantSearch, useChat } from 'react-instantsearch-core'; import { useStickToBottom } from '../lib/useStickToBottom.js'; import { createDisplayResultsTool } from './chat/tools/DisplayResultsTool.js'; import { createCarouselTool } from './chat/tools/SearchIndexTool.js'; var ChatUiComponent = createChatComponent({ createElement: createElement, Fragment: Fragment, memo: memo }); function createDefaultTools(itemComponent, getSearchPageURL) { var _obj; return _obj = {}, _(_obj, SearchIndexToolType, createCarouselTool(true, itemComponent, getSearchPageURL)), _(_obj, RecommendToolType, createCarouselTool(false, itemComponent, getSearchPageURL)), _(_obj, DisplayResultsToolType, createDisplayResultsTool(itemComponent)), _(_obj, MemorizeToolType, {}), _(_obj, MemorySearchToolType, {}), _(_obj, PonderToolType, {}), _obj; } function ChatInner(_0, _1) { var _ref = [ _0, _1 ], _ref1 = _$1(_ref), _ref2 = _ref1[0], _rest = _ref1.slice(1), userTools = _ref2.tools, headerProps = _ref2.headerProps, messagesProps = _ref2.messagesProps, promptProps = _ref2.promptProps, itemComponent = _ref2.itemComponent, layoutComponent = _ref2.layoutComponent, headerComponent = _ref2.headerComponent, headerTitleIconComponent = _ref2.headerTitleIconComponent, headerCloseIconComponent = _ref2.headerCloseIconComponent, headerMinimizeIconComponent = _ref2.headerMinimizeIconComponent, headerMaximizeIconComponent = _ref2.headerMaximizeIconComponent, loaderComponent = _ref2.loaderComponent, messagesErrorComponent = _ref2.messagesErrorComponent, promptComponent = _ref2.promptComponent, promptHeaderComponent = _ref2.promptHeaderComponent, promptFooterComponent = _ref2.promptFooterComponent, assistantMessageLeadingComponent = _ref2.assistantMessageLeadingComponent, assistantMessageFooterComponent = _ref2.assistantMessageFooterComponent, userMessageLeadingComponent = _ref2.userMessageLeadingComponent, userMessageFooterComponent = _ref2.userMessageFooterComponent, emptyComponent = _ref2.emptyComponent, actionsComponent = _ref2.actionsComponent, suggestionsComponent = _ref2.suggestionsComponent, classNames = _ref2.classNames, _ref_translations = _ref2.translations, translations = _ref_translations === void 0 ? {} : _ref_translations, title = _ref2.title, getSearchPageURL = _ref2.getSearchPageURL, _ref_disableTriggerValidation = _ref2.disableTriggerValidation, disableTriggerValidation = _ref_disableTriggerValidation === void 0 ? false : _ref_disableTriggerValidation, props = _$2(_ref2, [ "tools", "headerProps", "messagesProps", "promptProps", "itemComponent", "layoutComponent", "headerComponent", "headerTitleIconComponent", "headerCloseIconComponent", "headerMinimizeIconComponent", "headerMaximizeIconComponent", "loaderComponent", "messagesErrorComponent", "promptComponent", "promptHeaderComponent", "promptFooterComponent", "assistantMessageLeadingComponent", "assistantMessageFooterComponent", "userMessageLeadingComponent", "userMessageFooterComponent", "emptyComponent", "actionsComponent", "suggestionsComponent", "classNames", "translations", "title", "getSearchPageURL", "disableTriggerValidation" ]), _rest1 = _$3(_rest, 1), ref = _rest1[0]; var promptTranslations = translations.prompt, headerTranslations = translations.header, messageTranslations = translations.message, messagesTranslations = translations.messages; var _useInstantSearch = useInstantSearch(), indexUiState = _useInstantSearch.indexUiState, setIndexUiState = _useInstantSearch.setIndexUiState; var _useState = _$3(useState(false), 2), maximized = _useState[0], setMaximized = _useState[1]; var promptRef = useRef(null); var _useStickToBottom = useStickToBottom({ initial: 'smooth', resize: 'smooth' }), scrollRef = _useStickToBottom.scrollRef, contentRef = _useStickToBottom.contentRef, scrollToBottom = _useStickToBottom.scrollToBottom, isAtBottom = _useStickToBottom.isAtBottom; var tools = useMemo(function() { var defaults = createDefaultTools(itemComponent, getSearchPageURL); return _$4({}, defaults, userTools); }, [ getSearchPageURL, itemComponent, userTools ]); // Inline layouts are always visible, so they don't require a `<ChatTrigger />` // (or AI mode) to be present. We detect this via a `$$inlineLayout` marker // set on the layout component, which is consistent across flavors. var isInlineLayoutComponent = typeof layoutComponent === 'function' && layoutComponent.$$inlineLayout === true; var effectiveDisableTriggerValidation = disableTriggerValidation || isInlineLayoutComponent; var chatState = useChat(_$5(_$4({}, props), { tools: tools, disableTriggerValidation: effectiveDisableTriggerValidation })); var messages = chatState.messages, sendMessage = chatState.sendMessage, status = chatState.status, regenerate = chatState.regenerate, stop = chatState.stop, error = chatState.error, input = chatState.input, setInput = chatState.setInput, open = chatState.open, setOpen = chatState.setOpen, isClearing = chatState.isClearing, clearMessages = chatState.clearMessages, onClearTransitionEnd = chatState.onClearTransitionEnd, toolsFromConnector = chatState.tools, suggestions = chatState.suggestions, onFeedback = chatState.sendChatMessageFeedback, feedbackState = chatState.feedbackState; useImperativeHandle(ref, function() { return { setOpen: setOpen, sendMessage: function sendMessage1(params) { return sendMessage(params); }, setInput: setInput }; }); var wasOpenRef = useRef(false); useEffect(function() { var shouldFocusPrompt = !wasOpenRef.current && open; if (shouldFocusPrompt) { window.requestAnimationFrame(function() { var _promptRef_current; (_promptRef_current = promptRef.current) === null || _promptRef_current === void 0 ? void 0 : _promptRef_current.focus(); }); } wasOpenRef.current = open; }, [ open ]); // Keep the conversation pinned to the bottom while streaming. The stick-to- // bottom ResizeObserver only reacts to content *height* changes, but tool // results such as a horizontally-growing carousel stream in without changing // height — so we also re-pin on every message/status update. Passing // `preserveScrollPosition` reuses the existing "only if already at the // bottom" gate, so this never fights a user who has scrolled up to read. useEffect(function() { if (status === 'streaming' || status === 'submitted') { scrollToBottom({ preserveScrollPosition: true }); } }, [ messages, status, scrollToBottom ]); return /*#__PURE__*/ React.createElement(ChatUiComponent, { title: title, open: open, maximized: maximized, sendMessage: sendMessage, regenerate: regenerate, stop: stop, error: error, layoutComponent: layoutComponent, headerComponent: headerComponent, promptComponent: promptComponent, suggestionsComponent: suggestionsComponent, headerProps: _$4({ onClose: function onClose() { return setOpen(false); }, maximized: maximized, onToggleMaximize: function onToggleMaximize() { return setMaximized(!maximized); }, onClear: clearMessages, canClear: Boolean(messages === null || messages === void 0 ? void 0 : messages.length) && !isClearing, titleIconComponent: headerTitleIconComponent, closeIconComponent: headerCloseIconComponent, minimizeIconComponent: headerMinimizeIconComponent, maximizeIconComponent: headerMaximizeIconComponent, translations: headerTranslations }, headerProps), messagesProps: _$5(_$4({ status: status, onReload: function onReload(messageId) { return regenerate({ messageId: messageId }); }, onNewConversation: clearMessages, onClose: function onClose() { return setOpen(false); }, sendMessage: sendMessage, setInput: setInput, onFeedback: onFeedback, feedbackState: feedbackState, messages: messages, tools: toolsFromConnector, indexUiState: indexUiState, setIndexUiState: setIndexUiState, isClearing: isClearing, onClearTransitionEnd: onClearTransitionEnd, isScrollAtBottom: isAtBottom, scrollRef: scrollRef, contentRef: contentRef, onScrollToBottom: scrollToBottom, loaderComponent: loaderComponent, errorComponent: messagesErrorComponent, emptyComponent: emptyComponent, actionsComponent: actionsComponent, assistantMessageProps: _$4({ leadingComponent: assistantMessageLeadingComponent, footerComponent: assistantMessageFooterComponent }, messagesProps === null || messagesProps === void 0 ? void 0 : messagesProps.assistantMessageProps), userMessageProps: _$4({ leadingComponent: userMessageLeadingComponent, footerComponent: userMessageFooterComponent }, messagesProps === null || messagesProps === void 0 ? void 0 : messagesProps.userMessageProps), translations: messagesTranslations, messageTranslations: messageTranslations }, messagesProps), { error: error }), promptProps: _$4({ promptRef: promptRef, status: status, value: input, translations: promptTranslations, onInput: function onInput(event) { setInput(event.currentTarget.value); }, onSubmit: function onSubmit() { sendMessage({ text: input }); setInput(''); }, onStop: function onStop() { stop(); }, headerComponent: promptHeaderComponent, footerComponent: promptFooterComponent }, promptProps), suggestionsProps: { suggestions: suggestions, onSuggestionClick: function onSuggestionClick(suggestion) { sendMessage({ text: suggestion }); } }, classNames: classNames }); } var Chat = /*#__PURE__*/ React.forwardRef(ChatInner); export { Chat, createDefaultTools };