@liveblocks/react-ui 2.25.0-aiprivatebeta8 → 3.0.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.
- package/_private/package.json +2 -2
- package/dist/_private/index.cjs +14 -12
- package/dist/_private/index.cjs.map +1 -1
- package/dist/_private/index.d.cts +146 -113
- package/dist/_private/index.d.ts +146 -113
- package/dist/_private/index.js +10 -5
- package/dist/_private/index.js.map +1 -1
- package/dist/components/AiChat.cjs +85 -121
- package/dist/components/AiChat.cjs.map +1 -1
- package/dist/components/AiChat.js +87 -123
- package/dist/components/AiChat.js.map +1 -1
- package/dist/components/AiTool.cjs +188 -0
- package/dist/components/AiTool.cjs.map +1 -0
- package/dist/components/AiTool.js +186 -0
- package/dist/components/AiTool.js.map +1 -0
- package/dist/components/Comment.cjs +259 -238
- package/dist/components/Comment.cjs.map +1 -1
- package/dist/components/Comment.js +261 -240
- package/dist/components/Comment.js.map +1 -1
- package/dist/components/Composer.cjs +42 -30
- package/dist/components/Composer.cjs.map +1 -1
- package/dist/components/Composer.js +44 -32
- package/dist/components/Composer.js.map +1 -1
- package/dist/components/InboxNotificationList.cjs +11 -3
- package/dist/components/InboxNotificationList.cjs.map +1 -1
- package/dist/components/InboxNotificationList.js +12 -4
- package/dist/components/InboxNotificationList.js.map +1 -1
- package/dist/components/Thread.cjs +7 -1
- package/dist/components/Thread.cjs.map +1 -1
- package/dist/components/Thread.js +8 -2
- package/dist/components/Thread.js.map +1 -1
- package/dist/components/internal/AiChatAssistantMessage.cjs +75 -199
- package/dist/components/internal/AiChatAssistantMessage.cjs.map +1 -1
- package/dist/components/internal/AiChatAssistantMessage.js +77 -201
- package/dist/components/internal/AiChatAssistantMessage.js.map +1 -1
- package/dist/components/internal/AiChatComposer.cjs +1 -1
- package/dist/components/internal/AiChatComposer.cjs.map +1 -1
- package/dist/components/internal/AiChatComposer.js +1 -1
- package/dist/components/internal/AiChatComposer.js.map +1 -1
- package/dist/components/internal/AiChatUserMessage.cjs +17 -10
- package/dist/components/internal/AiChatUserMessage.cjs.map +1 -1
- package/dist/components/internal/AiChatUserMessage.js +17 -10
- package/dist/components/internal/AiChatUserMessage.js.map +1 -1
- package/dist/components/internal/Button.cjs.map +1 -1
- package/dist/components/internal/Button.js.map +1 -1
- package/dist/components/internal/CodeBlock.cjs +75 -0
- package/dist/components/internal/CodeBlock.cjs.map +1 -0
- package/dist/components/internal/CodeBlock.js +73 -0
- package/dist/components/internal/CodeBlock.js.map +1 -0
- package/dist/components/internal/Dropdown.cjs +1 -1
- package/dist/components/internal/Dropdown.cjs.map +1 -1
- package/dist/components/internal/Dropdown.js +2 -2
- package/dist/components/internal/Dropdown.js.map +1 -1
- package/dist/components/internal/Emoji.cjs +12 -4
- package/dist/components/internal/Emoji.cjs.map +1 -1
- package/dist/components/internal/Emoji.js +12 -4
- package/dist/components/internal/Emoji.js.map +1 -1
- package/dist/components/internal/EmojiPicker.cjs +1 -1
- package/dist/components/internal/EmojiPicker.cjs.map +1 -1
- package/dist/components/internal/EmojiPicker.js +2 -2
- package/dist/components/internal/EmojiPicker.js.map +1 -1
- package/dist/components/internal/InboxNotificationThread.cjs +5 -2
- package/dist/components/internal/InboxNotificationThread.cjs.map +1 -1
- package/dist/components/internal/InboxNotificationThread.js +6 -3
- package/dist/components/internal/InboxNotificationThread.js.map +1 -1
- package/dist/components/internal/Prose.cjs +37 -0
- package/dist/components/internal/Prose.cjs.map +1 -0
- package/dist/components/internal/Prose.js +35 -0
- package/dist/components/internal/Prose.js.map +1 -0
- package/dist/components/internal/Tooltip.cjs +1 -1
- package/dist/components/internal/Tooltip.cjs.map +1 -1
- package/dist/components/internal/Tooltip.js +2 -2
- package/dist/components/internal/Tooltip.js.map +1 -1
- package/dist/config.cjs +9 -9
- package/dist/config.cjs.map +1 -1
- package/dist/config.js +8 -8
- package/dist/config.js.map +1 -1
- package/dist/icons/CrossCircleFill.cjs +25 -0
- package/dist/icons/CrossCircleFill.cjs.map +1 -0
- package/dist/icons/CrossCircleFill.js +23 -0
- package/dist/icons/CrossCircleFill.js.map +1 -0
- package/dist/icons/MinusCircle.cjs +23 -0
- package/dist/icons/MinusCircle.cjs.map +1 -0
- package/dist/icons/MinusCircle.js +21 -0
- package/dist/icons/MinusCircle.js.map +1 -0
- package/dist/icons/index.cjs +4 -0
- package/dist/icons/index.cjs.map +1 -1
- package/dist/icons/index.js +2 -0
- package/dist/icons/index.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +270 -22
- package/dist/index.d.ts +270 -22
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/overrides.cjs +6 -4
- package/dist/overrides.cjs.map +1 -1
- package/dist/overrides.js +6 -4
- package/dist/overrides.js.map +1 -1
- package/dist/primitives/AiMessage/contexts.cjs +18 -0
- package/dist/primitives/AiMessage/contexts.cjs.map +1 -0
- package/dist/primitives/AiMessage/contexts.js +15 -0
- package/dist/primitives/AiMessage/contexts.js.map +1 -0
- package/dist/primitives/AiMessage/index.cjs +77 -0
- package/dist/primitives/AiMessage/index.cjs.map +1 -0
- package/dist/primitives/AiMessage/index.js +75 -0
- package/dist/primitives/AiMessage/index.js.map +1 -0
- package/dist/primitives/AiMessage/tool-invocation.cjs +70 -0
- package/dist/primitives/AiMessage/tool-invocation.cjs.map +1 -0
- package/dist/primitives/AiMessage/tool-invocation.js +68 -0
- package/dist/primitives/AiMessage/tool-invocation.js.map +1 -0
- package/dist/primitives/{internal/Collapsible → Collapsible}/index.cjs +39 -17
- package/dist/primitives/Collapsible/index.cjs.map +1 -0
- package/dist/primitives/{internal/Collapsible → Collapsible}/index.js +37 -15
- package/dist/primitives/Collapsible/index.js.map +1 -0
- package/dist/primitives/Comment/index.cjs +5 -4
- package/dist/primitives/Comment/index.cjs.map +1 -1
- package/dist/primitives/Comment/index.js +5 -4
- package/dist/primitives/Comment/index.js.map +1 -1
- package/dist/primitives/Composer/index.cjs +49 -41
- package/dist/primitives/Composer/index.cjs.map +1 -1
- package/dist/primitives/Composer/index.js +50 -42
- package/dist/primitives/Composer/index.js.map +1 -1
- package/dist/primitives/Composer/slate/plugins/mentions.cjs +4 -4
- package/dist/primitives/Composer/slate/plugins/mentions.cjs.map +1 -1
- package/dist/primitives/Composer/slate/plugins/mentions.js +4 -4
- package/dist/primitives/Composer/slate/plugins/mentions.js.map +1 -1
- package/dist/primitives/Composer/utils.cjs +3 -6
- package/dist/primitives/Composer/utils.cjs.map +1 -1
- package/dist/primitives/Composer/utils.js +3 -6
- package/dist/primitives/Composer/utils.js.map +1 -1
- package/dist/primitives/{internal/Markdown.cjs → Markdown.cjs} +105 -65
- package/dist/primitives/Markdown.cjs.map +1 -0
- package/dist/primitives/{internal/Markdown.js → Markdown.js} +106 -65
- package/dist/primitives/Markdown.js.map +1 -0
- package/dist/primitives/index.cjs +4 -6
- package/dist/primitives/index.cjs.map +1 -1
- package/dist/primitives/index.d.cts +20 -93
- package/dist/primitives/index.d.ts +20 -93
- package/dist/primitives/index.js +4 -6
- package/dist/primitives/index.js.map +1 -1
- package/dist/utils/ErrorBoundary.cjs +48 -0
- package/dist/utils/ErrorBoundary.cjs.map +1 -0
- package/dist/utils/ErrorBoundary.js +45 -0
- package/dist/utils/ErrorBoundary.js.map +1 -0
- package/dist/utils/use-controllable-state.cjs +25 -2
- package/dist/utils/use-controllable-state.cjs.map +1 -1
- package/dist/utils/use-controllable-state.js +25 -3
- package/dist/utils/use-controllable-state.js.map +1 -1
- package/dist/utils/use-visible.cjs +65 -45
- package/dist/utils/use-visible.cjs.map +1 -1
- package/dist/utils/use-visible.js +66 -46
- package/dist/utils/use-visible.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +16 -5
- package/primitives/package.json +2 -2
- package/src/styles/constants.css +1 -1
- package/src/styles/dark/index.css +7 -3
- package/src/styles/index.css +572 -252
- package/src/styles/utils.css +1 -1
- package/styles/dark/attributes.css +1 -1
- package/styles/dark/attributes.css.map +1 -1
- package/styles/dark/media-query.css +1 -1
- package/styles/dark/media-query.css.map +1 -1
- package/styles.css +1 -1
- package/styles.css.map +1 -1
- package/dist/components/AiToolDebugger.cjs +0 -74
- package/dist/components/AiToolDebugger.cjs.map +0 -1
- package/dist/components/AiToolDebugger.js +0 -72
- package/dist/components/AiToolDebugger.js.map +0 -1
- package/dist/primitives/internal/Collapsible/index.cjs.map +0 -1
- package/dist/primitives/internal/Collapsible/index.js.map +0 -1
- package/dist/primitives/internal/Emoji.cjs +0 -32
- package/dist/primitives/internal/Emoji.cjs.map +0 -1
- package/dist/primitives/internal/Emoji.js +0 -30
- package/dist/primitives/internal/Emoji.js.map +0 -1
- package/dist/primitives/internal/Markdown.cjs.map +0 -1
- package/dist/primitives/internal/Markdown.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiChat.cjs","sources":["../../src/components/AiChat.tsx"],"sourcesContent":["import type {\n AiKnowledgeSource,\n AiToolDefinition,\n CopilotId,\n MessageId,\n UiChatMessage,\n} from \"@liveblocks/core\";\nimport { kInternal } from \"@liveblocks/core\";\nimport {\n RegisterAiKnowledge,\n useAiChatMessages,\n useClient,\n} from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n type ComponentProps,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport type { GlobalComponents } from \"../components\";\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { SpinnerIcon } from \"../icons/Spinner\";\nimport {\n type AiChatComposerOverrides,\n type AiChatMessageOverrides,\n type AiChatOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { AiChatAssistantMessage } from \"./internal/AiChatAssistantMessage\";\nimport { AiChatComposer } from \"./internal/AiChatComposer\";\nimport { AiChatUserMessage } from \"./internal/AiChatUserMessage\";\n\n/**\n * The number of pixels from the bottom of the messages list to trigger the scroll to bottom.\n */\nconst MIN_DISTANCE_TO_BOTTOM = 50;\n\nexport interface AiChatProps extends ComponentProps<\"div\"> {\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n /**\n * Whether to focus the chat composer on mount.\n */\n autoFocus?: boolean;\n /**\n * The id of the copilot to use to send the message.\n */\n copilotId?: string;\n /**\n * The contextual knowledge to include in the chat. May be used by the assistant when generating responses.\n * Any knowledge you provide via this prop will be added to any already globally registered knowledge via <RegisterAiKnowledge />.\n */\n knowledge?: AiKnowledgeSource[];\n /**\n * Tool definitions to make available within this chat. May be used by the assistant when generating responses.\n */\n tools?: Record<string, AiToolDefinition>;\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides &\n AiChatMessageOverrides &\n AiChatComposerOverrides &\n AiChatOverrides\n >;\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents>; // TODO: Add more slots than the global ones over time (Markdown tags, the empty state, etc)\n}\n\nexport const AiChat = forwardRef<HTMLDivElement, AiChatProps>(\n (\n {\n chatId,\n copilotId,\n autoFocus,\n overrides,\n knowledge,\n tools = {},\n components,\n className,\n ...props\n },\n forwardedRef\n ) => {\n const { messages, isLoading, error } = useAiChatMessages(chatId);\n const $ = useOverrides(overrides);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [distanceToBottom, setDistanceToBottom] = useState<number | null>(\n null\n );\n const client = useClient();\n const ai = client[kInternal].ai;\n\n const [lastSendMessageId, setLastSendMessageId] =\n useState<MessageId | null>(null);\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => containerRef.current,\n []\n );\n\n // Register the provided tools to the chat on mount and unregister them on unmount\n useEffect(() => {\n Object.entries(tools).map(([key, value]) =>\n ai.registerChatTool(chatId, key, value)\n );\n return () => {\n Object.entries(tools).map(([key]) =>\n ai.unregisterChatTool(chatId, key)\n );\n };\n }, [ai, chatId, tools]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n function handleScrollChange() {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }\n container.addEventListener(\"scroll\", handleScrollChange);\n return () => {\n container.removeEventListener(\"scroll\", handleScrollChange);\n };\n }, []);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }, [messages]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }, [lastSendMessageId]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const observer = new ResizeObserver(() => {\n const container = containerRef.current;\n if (container === null) return;\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n });\n observer.observe(container);\n return () => {\n observer.disconnect();\n };\n }, []);\n\n const scrollToBottomCallbackRef = useRef<() => void>(undefined);\n if (scrollToBottomCallbackRef.current === undefined) {\n scrollToBottomCallbackRef.current = function () {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"instant\",\n });\n };\n }\n const isScrollIndicatorVisible =\n distanceToBottom !== null && distanceToBottom > MIN_DISTANCE_TO_BOTTOM;\n\n return (\n <div\n ref={containerRef}\n {...props}\n className={classNames(\"lb-root lb-ai-chat\", className)}\n >\n {knowledge\n ? knowledge.map((source, index) => (\n <RegisterAiKnowledge\n key={index}\n description={source.description}\n value={source.value}\n // knowledgeKey={source.knowledgeKey}\n />\n ))\n : null}\n <div className=\"lb-ai-chat-content\">\n {isLoading ? (\n <div className=\"lb-loading lb-ai-chat-loading\">\n <SpinnerIcon />\n </div>\n ) : error !== undefined ? (\n <div className=\"lb-error lb-ai-chat-error\">\n {$.AI_CHAT_MESSAGES_ERROR(error)}\n </div>\n ) : (\n <div className=\"lb-ai-chat-messages\">\n <Messages\n messages={messages}\n overrides={$}\n components={components}\n onDistanceToBottomChange={scrollToBottomCallbackRef.current}\n />\n </div>\n )}\n </div>\n\n <div className=\"lb-ai-chat-footer\">\n <div className=\"lb-ai-chat-footer-actions\">\n <div\n className=\"lb-elevation lb-ai-chat-scroll-indicator\"\n data-visible={isScrollIndicatorVisible ? \"\" : undefined}\n >\n <button\n className=\"lb-ai-chat-scroll-indicator-button\"\n tabIndex={isScrollIndicatorVisible ? 0 : -1}\n aria-hidden={!isScrollIndicatorVisible}\n disabled={!isScrollIndicatorVisible}\n onClick={() => {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }}\n >\n <span className=\"lb-icon-container\">\n <ArrowDownIcon />\n </span>\n </button>\n </div>\n </div>\n <AiChatComposer\n key={chatId}\n chatId={chatId}\n copilotId={copilotId as CopilotId}\n overrides={$}\n autoFocus={autoFocus}\n onUserMessageCreate={({ id }) => setLastSendMessageId(id)}\n />\n </div>\n </div>\n );\n }\n);\n\nfunction Messages({\n messages,\n overrides,\n components,\n onDistanceToBottomChange,\n}: {\n messages: readonly UiChatMessage[];\n overrides?: Partial<GlobalOverrides & AiChatMessageOverrides>;\n components?: Partial<GlobalComponents>;\n onDistanceToBottomChange: () => void;\n}) {\n useLayoutEffect(() => {\n onDistanceToBottomChange();\n }, [onDistanceToBottomChange]);\n\n return messages.map((message) => {\n if (message.role === \"user\") {\n return (\n <AiChatUserMessage\n key={message.id}\n message={message}\n overrides={overrides}\n />\n );\n } else if (message.role === \"assistant\") {\n return (\n <AiChatAssistantMessage\n key={message.id}\n message={message}\n overrides={overrides}\n components={components}\n />\n );\n } else {\n return null;\n }\n });\n}\n"],"names":["forwardRef","overrides","useAiChatMessages","useOverrides","useRef","useState","useClient","kInternal","useImperativeHandle","useEffect","container","jsxs","classNames","jsx","RegisterAiKnowledge","SpinnerIcon","ArrowDownIcon","AiChatComposer","useLayoutEffect","AiChatUserMessage","AiChatAssistantMessage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AiChat.cjs","sources":["../../src/components/AiChat.tsx"],"sourcesContent":["import type {\n AiKnowledgeSource,\n AiOpaqueToolDefinition,\n CopilotId,\n MessageId,\n} from \"@liveblocks/core\";\nimport {\n RegisterAiKnowledge,\n RegisterAiTool,\n useAiChatMessages,\n} from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n type ComponentProps,\n type ComponentType,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport type { GlobalComponents } from \"../components\";\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { SpinnerIcon } from \"../icons/Spinner\";\nimport {\n type AiChatComposerOverrides,\n type AiChatMessageOverrides,\n type AiChatOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { useVisible } from \"../utils/use-visible\";\nimport { AiChatAssistantMessage } from \"./internal/AiChatAssistantMessage\";\nimport { AiChatComposer } from \"./internal/AiChatComposer\";\nimport { AiChatUserMessage } from \"./internal/AiChatUserMessage\";\n\nexport type AiChatComponentsEmptyProps = {\n /**\n * The chat id provided to the `AiChat` component.\n */\n chatId: string;\n /**\n * The copilot id provided to the `AiChat` component.\n */\n copilotId?: string;\n};\n\nexport type AiChatComponentsLoadingProps = Record<string, never>;\n\n// TODO: Add Markdown components\nexport type AiChatComponents = {\n /**\n * The component used to render the empty state of the chat.\n */\n Empty: ComponentType<AiChatComponentsEmptyProps>;\n /**\n * The component used to render the loading state of the chat.\n */\n Loading: ComponentType<AiChatComponentsLoadingProps>;\n};\n\n/**\n * The minimum number of pixels from the bottom of the scrollable area\n * before showing the scroll to bottom indicator.\n */\nconst MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR = 50;\n\nexport interface AiChatProps extends ComponentProps<\"div\"> {\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n /**\n * Whether to focus the chat composer on mount.\n */\n autoFocus?: boolean;\n /**\n * The id of the copilot to use to send the message.\n */\n copilotId?: string;\n /**\n * The contextual knowledge to include in the chat. May be used by the assistant when generating responses.\n * Any knowledge you provide via this prop will be added to any already globally registered knowledge via <RegisterAiKnowledge />.\n */\n knowledge?: AiKnowledgeSource[];\n /**\n * Tool definitions to make available within this chat. May be used by the assistant when generating responses.\n */\n tools?: Record<string, AiOpaqueToolDefinition>;\n /**\n * The layout of the chat and its composer.\n */\n layout?: \"inset\" | \"compact\";\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides &\n AiChatMessageOverrides &\n AiChatComposerOverrides &\n AiChatOverrides\n >;\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents & AiChatComponents>;\n}\n\nconst defaultComponents: AiChatComponents = {\n Empty: () => null,\n Loading: () => (\n <div className=\"lb-loading lb-ai-chat-loading\">\n <SpinnerIcon />\n </div>\n ),\n};\n\nexport const AiChat = forwardRef<HTMLDivElement, AiChatProps>(\n (\n {\n chatId,\n copilotId,\n autoFocus,\n overrides,\n knowledge,\n tools = {},\n layout = \"inset\",\n components,\n className,\n ...props\n },\n forwardedRef\n ) => {\n const { messages, isLoading, error } = useAiChatMessages(chatId);\n const $ = useOverrides(overrides);\n const Empty = components?.Empty ?? defaultComponents.Empty;\n const Loading = components?.Loading ?? defaultComponents.Loading;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const containerBottomRef = useRef<HTMLDivElement | null>(null);\n const isScrollIndicatorEnabled = !isLoading && !error;\n const isScrollAtBottom = useVisible(containerBottomRef, {\n enabled: isScrollIndicatorEnabled,\n root: containerRef,\n rootMargin: MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR,\n initialValue: null,\n });\n const isScrollIndicatorVisible =\n isScrollIndicatorEnabled && isScrollAtBottom !== null\n ? !isScrollAtBottom\n : false;\n\n const [lastSentMessageId, setLastSentMessageId] =\n useState<MessageId | null>(null);\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => containerRef.current,\n []\n );\n\n const scrollToBottomCallbackRef =\n useRef<(behavior: \"instant\" | \"smooth\") => void>(undefined);\n if (scrollToBottomCallbackRef.current === undefined) {\n scrollToBottomCallbackRef.current = function (\n behavior: \"instant\" | \"smooth\"\n ) {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior,\n });\n };\n }\n const scrollToBottom = scrollToBottomCallbackRef.current;\n\n return (\n <div\n ref={containerRef}\n {...props}\n className={classNames(\n \"lb-root lb-ai-chat\",\n layout === \"compact\"\n ? \"lb-ai-chat:layout-compact\"\n : \"lb-ai-chat:layout-inset\",\n className\n )}\n >\n {knowledge\n ? knowledge.map((source, index) => (\n <RegisterAiKnowledge\n key={index}\n description={source.description}\n value={source.value}\n // knowledgeKey={source.knowledgeKey}\n />\n ))\n : null}\n\n {Object.entries(tools).map(([name, tool]) => (\n <RegisterAiTool key={name} chatId={chatId} name={name} tool={tool} />\n ))}\n\n <div className=\"lb-ai-chat-content\">\n {isLoading ? (\n <Loading />\n ) : error !== undefined ? (\n <div className=\"lb-error lb-ai-chat-error\">\n {$.AI_CHAT_MESSAGES_ERROR(error)}\n </div>\n ) : messages.length === 0 ? (\n <Empty chatId={chatId} copilotId={copilotId} />\n ) : (\n <>\n <AutoScrollHandler\n lastSentMessageId={lastSentMessageId}\n scrollToBottom={scrollToBottom}\n />\n <div className=\"lb-ai-chat-messages\">\n {messages.map((message) => {\n if (message.role === \"user\") {\n return (\n <AiChatUserMessage\n key={message.id}\n message={message}\n overrides={overrides}\n />\n );\n } else if (message.role === \"assistant\") {\n return (\n <AiChatAssistantMessage\n key={message.id}\n message={message}\n overrides={overrides}\n components={components}\n />\n );\n } else {\n return null;\n }\n })}\n </div>\n </>\n )}\n </div>\n\n <div className=\"lb-ai-chat-footer\">\n <div className=\"lb-ai-chat-footer-actions\">\n <div\n className=\"lb-root lb-elevation lb-elevation-moderate lb-ai-chat-scroll-indicator\"\n data-visible={isScrollIndicatorVisible ? \"\" : undefined}\n >\n <button\n className=\"lb-ai-chat-scroll-indicator-button\"\n tabIndex={isScrollIndicatorVisible ? 0 : -1}\n aria-hidden={!isScrollIndicatorVisible}\n onClick={() => scrollToBottom(\"smooth\")}\n >\n <span className=\"lb-icon-container\">\n <ArrowDownIcon />\n </span>\n </button>\n </div>\n </div>\n <AiChatComposer\n key={chatId}\n chatId={chatId}\n copilotId={copilotId as CopilotId}\n overrides={overrides}\n autoFocus={autoFocus}\n onUserMessageCreate={({ id }) => setLastSentMessageId(id)}\n className={\n layout === \"inset\"\n ? \"lb-elevation lb-elevation-moderate\"\n : undefined\n }\n />\n </div>\n {/* This invisible element is a trick which allows us to use IntersectionObserver to detect when the\n * scrollable area is fully scrolled to the bottom instead of manually tracking the scroll position\n * and having to deal with resizes, etc.\n *\n * It's positioned at the bottom of the scrollable area and reliably only becomes \"visible\" to the\n * IntersectionObserver when the scrollable area is fully scrolled.\n */}\n <div\n ref={containerBottomRef}\n style={{ position: \"sticky\", height: 0 }}\n aria-hidden\n data-scroll-at-bottom={isScrollAtBottom ? \"\" : undefined}\n />\n </div>\n );\n }\n);\n\nfunction AutoScrollHandler({\n lastSentMessageId,\n scrollToBottom,\n}: {\n lastSentMessageId: MessageId | null;\n scrollToBottom: (behavior: \"instant\" | \"smooth\") => void;\n}) {\n // Scroll to bottom when the component first mounts\n useLayoutEffect(() => {\n scrollToBottom(\"instant\");\n }, [scrollToBottom]);\n\n // Scroll to bottom when sending a new message\n useEffect(() => {\n scrollToBottom(\"smooth\");\n }, [lastSentMessageId, scrollToBottom]);\n\n return null;\n}\n"],"names":["jsx","SpinnerIcon","forwardRef","overrides","useAiChatMessages","useOverrides","useRef","useVisible","useState","useImperativeHandle","jsxs","classNames","RegisterAiKnowledge","RegisterAiTool","Fragment","AiChatUserMessage","AiChatAssistantMessage","ArrowDownIcon","AiChatComposer","useLayoutEffect","useEffect"],"mappings":"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"}
|
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import { jsxs,
|
|
2
|
-
import {
|
|
3
|
-
import { useAiChatMessages, useClient, RegisterAiKnowledge } from '@liveblocks/react';
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useAiChatMessages, RegisterAiKnowledge, RegisterAiTool } from '@liveblocks/react';
|
|
4
3
|
import { useLayoutEffect } from '@liveblocks/react/_private';
|
|
5
4
|
import { forwardRef, useRef, useState, useImperativeHandle, useEffect } from 'react';
|
|
6
5
|
import { ArrowDownIcon } from '../icons/ArrowDown.js';
|
|
7
6
|
import { SpinnerIcon } from '../icons/Spinner.js';
|
|
8
7
|
import { useOverrides } from '../overrides.js';
|
|
9
8
|
import { classNames } from '../utils/class-names.js';
|
|
9
|
+
import { useVisible } from '../utils/use-visible.js';
|
|
10
10
|
import { AiChatAssistantMessage } from './internal/AiChatAssistantMessage.js';
|
|
11
11
|
import { AiChatComposer } from './internal/AiChatComposer.js';
|
|
12
12
|
import { AiChatUserMessage } from './internal/AiChatUserMessage.js';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR = 50;
|
|
15
|
+
const defaultComponents = {
|
|
16
|
+
Empty: () => null,
|
|
17
|
+
Loading: () => /* @__PURE__ */ jsx("div", {
|
|
18
|
+
className: "lb-loading lb-ai-chat-loading",
|
|
19
|
+
children: /* @__PURE__ */ jsx(SpinnerIcon, {})
|
|
20
|
+
})
|
|
21
|
+
};
|
|
15
22
|
const AiChat = forwardRef(
|
|
16
23
|
({
|
|
17
24
|
chatId,
|
|
@@ -20,123 +27,96 @@ const AiChat = forwardRef(
|
|
|
20
27
|
overrides,
|
|
21
28
|
knowledge,
|
|
22
29
|
tools = {},
|
|
30
|
+
layout = "inset",
|
|
23
31
|
components,
|
|
24
32
|
className,
|
|
25
33
|
...props
|
|
26
34
|
}, forwardedRef) => {
|
|
27
35
|
const { messages, isLoading, error } = useAiChatMessages(chatId);
|
|
28
36
|
const $ = useOverrides(overrides);
|
|
37
|
+
const Empty = components?.Empty ?? defaultComponents.Empty;
|
|
38
|
+
const Loading = components?.Loading ?? defaultComponents.Loading;
|
|
29
39
|
const containerRef = useRef(null);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
const containerBottomRef = useRef(null);
|
|
41
|
+
const isScrollIndicatorEnabled = !isLoading && !error;
|
|
42
|
+
const isScrollAtBottom = useVisible(containerBottomRef, {
|
|
43
|
+
enabled: isScrollIndicatorEnabled,
|
|
44
|
+
root: containerRef,
|
|
45
|
+
rootMargin: MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR,
|
|
46
|
+
initialValue: null
|
|
47
|
+
});
|
|
48
|
+
const isScrollIndicatorVisible = isScrollIndicatorEnabled && isScrollAtBottom !== null ? !isScrollAtBottom : false;
|
|
49
|
+
const [lastSentMessageId, setLastSentMessageId] = useState(null);
|
|
36
50
|
useImperativeHandle(
|
|
37
51
|
forwardedRef,
|
|
38
52
|
() => containerRef.current,
|
|
39
53
|
[]
|
|
40
54
|
);
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
Object.entries(tools).map(
|
|
43
|
-
([key, value]) => ai.registerChatTool(chatId, key, value)
|
|
44
|
-
);
|
|
45
|
-
return () => {
|
|
46
|
-
Object.entries(tools).map(
|
|
47
|
-
([key]) => ai.unregisterChatTool(chatId, key)
|
|
48
|
-
);
|
|
49
|
-
};
|
|
50
|
-
}, [ai, chatId, tools]);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
const container = containerRef.current;
|
|
53
|
-
if (container === null)
|
|
54
|
-
return;
|
|
55
|
-
function handleScrollChange() {
|
|
56
|
-
const container2 = containerRef.current;
|
|
57
|
-
if (container2 === null)
|
|
58
|
-
return;
|
|
59
|
-
setDistanceToBottom(
|
|
60
|
-
container2.scrollHeight - container2.clientHeight - container2.scrollTop
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
container.addEventListener("scroll", handleScrollChange);
|
|
64
|
-
return () => {
|
|
65
|
-
container.removeEventListener("scroll", handleScrollChange);
|
|
66
|
-
};
|
|
67
|
-
}, []);
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
const container = containerRef.current;
|
|
70
|
-
if (container === null)
|
|
71
|
-
return;
|
|
72
|
-
setDistanceToBottom(
|
|
73
|
-
container.scrollHeight - container.clientHeight - container.scrollTop
|
|
74
|
-
);
|
|
75
|
-
}, [messages]);
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
const container = containerRef.current;
|
|
78
|
-
if (container === null)
|
|
79
|
-
return;
|
|
80
|
-
container.scrollTo({
|
|
81
|
-
top: container.scrollHeight,
|
|
82
|
-
behavior: "smooth"
|
|
83
|
-
});
|
|
84
|
-
}, [lastSendMessageId]);
|
|
85
|
-
useEffect(() => {
|
|
86
|
-
const container = containerRef.current;
|
|
87
|
-
if (container === null)
|
|
88
|
-
return;
|
|
89
|
-
const observer = new ResizeObserver(() => {
|
|
90
|
-
const container2 = containerRef.current;
|
|
91
|
-
if (container2 === null)
|
|
92
|
-
return;
|
|
93
|
-
setDistanceToBottom(
|
|
94
|
-
container2.scrollHeight - container2.clientHeight - container2.scrollTop
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
observer.observe(container);
|
|
98
|
-
return () => {
|
|
99
|
-
observer.disconnect();
|
|
100
|
-
};
|
|
101
|
-
}, []);
|
|
102
55
|
const scrollToBottomCallbackRef = useRef(void 0);
|
|
103
56
|
if (scrollToBottomCallbackRef.current === void 0) {
|
|
104
|
-
scrollToBottomCallbackRef.current = function() {
|
|
57
|
+
scrollToBottomCallbackRef.current = function(behavior) {
|
|
105
58
|
const container = containerRef.current;
|
|
106
59
|
if (container === null)
|
|
107
60
|
return;
|
|
108
61
|
container.scrollTo({
|
|
109
62
|
top: container.scrollHeight,
|
|
110
|
-
behavior
|
|
63
|
+
behavior
|
|
111
64
|
});
|
|
112
65
|
};
|
|
113
66
|
}
|
|
114
|
-
const
|
|
67
|
+
const scrollToBottom = scrollToBottomCallbackRef.current;
|
|
115
68
|
return /* @__PURE__ */ jsxs("div", {
|
|
116
69
|
ref: containerRef,
|
|
117
70
|
...props,
|
|
118
|
-
className: classNames(
|
|
71
|
+
className: classNames(
|
|
72
|
+
"lb-root lb-ai-chat",
|
|
73
|
+
layout === "compact" ? "lb-ai-chat:layout-compact" : "lb-ai-chat:layout-inset",
|
|
74
|
+
className
|
|
75
|
+
),
|
|
119
76
|
children: [
|
|
120
77
|
knowledge ? knowledge.map((source, index) => /* @__PURE__ */ jsx(RegisterAiKnowledge, {
|
|
121
78
|
description: source.description,
|
|
122
79
|
value: source.value
|
|
123
80
|
}, index)) : null,
|
|
81
|
+
Object.entries(tools).map(([name, tool]) => /* @__PURE__ */ jsx(RegisterAiTool, {
|
|
82
|
+
chatId,
|
|
83
|
+
name,
|
|
84
|
+
tool
|
|
85
|
+
}, name)),
|
|
124
86
|
/* @__PURE__ */ jsx("div", {
|
|
125
87
|
className: "lb-ai-chat-content",
|
|
126
|
-
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
127
|
-
className: "lb-loading lb-ai-chat-loading",
|
|
128
|
-
children: /* @__PURE__ */ jsx(SpinnerIcon, {})
|
|
129
|
-
}) : error !== void 0 ? /* @__PURE__ */ jsx("div", {
|
|
88
|
+
children: isLoading ? /* @__PURE__ */ jsx(Loading, {}) : error !== void 0 ? /* @__PURE__ */ jsx("div", {
|
|
130
89
|
className: "lb-error lb-ai-chat-error",
|
|
131
90
|
children: $.AI_CHAT_MESSAGES_ERROR(error)
|
|
132
|
-
}) : /* @__PURE__ */ jsx(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
91
|
+
}) : messages.length === 0 ? /* @__PURE__ */ jsx(Empty, {
|
|
92
|
+
chatId,
|
|
93
|
+
copilotId
|
|
94
|
+
}) : /* @__PURE__ */ jsxs(Fragment, {
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ jsx(AutoScrollHandler, {
|
|
97
|
+
lastSentMessageId,
|
|
98
|
+
scrollToBottom
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ jsx("div", {
|
|
101
|
+
className: "lb-ai-chat-messages",
|
|
102
|
+
children: messages.map((message) => {
|
|
103
|
+
if (message.role === "user") {
|
|
104
|
+
return /* @__PURE__ */ jsx(AiChatUserMessage, {
|
|
105
|
+
message,
|
|
106
|
+
overrides
|
|
107
|
+
}, message.id);
|
|
108
|
+
} else if (message.role === "assistant") {
|
|
109
|
+
return /* @__PURE__ */ jsx(AiChatAssistantMessage, {
|
|
110
|
+
message,
|
|
111
|
+
overrides,
|
|
112
|
+
components
|
|
113
|
+
}, message.id);
|
|
114
|
+
} else {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
]
|
|
140
120
|
})
|
|
141
121
|
}),
|
|
142
122
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -145,22 +125,13 @@ const AiChat = forwardRef(
|
|
|
145
125
|
/* @__PURE__ */ jsx("div", {
|
|
146
126
|
className: "lb-ai-chat-footer-actions",
|
|
147
127
|
children: /* @__PURE__ */ jsx("div", {
|
|
148
|
-
className: "lb-elevation lb-ai-chat-scroll-indicator",
|
|
128
|
+
className: "lb-root lb-elevation lb-elevation-moderate lb-ai-chat-scroll-indicator",
|
|
149
129
|
"data-visible": isScrollIndicatorVisible ? "" : void 0,
|
|
150
130
|
children: /* @__PURE__ */ jsx("button", {
|
|
151
131
|
className: "lb-ai-chat-scroll-indicator-button",
|
|
152
132
|
tabIndex: isScrollIndicatorVisible ? 0 : -1,
|
|
153
133
|
"aria-hidden": !isScrollIndicatorVisible,
|
|
154
|
-
|
|
155
|
-
onClick: () => {
|
|
156
|
-
const container = containerRef.current;
|
|
157
|
-
if (container === null)
|
|
158
|
-
return;
|
|
159
|
-
container.scrollTo({
|
|
160
|
-
top: container.scrollHeight,
|
|
161
|
-
behavior: "smooth"
|
|
162
|
-
});
|
|
163
|
-
},
|
|
134
|
+
onClick: () => scrollToBottom("smooth"),
|
|
164
135
|
children: /* @__PURE__ */ jsx("span", {
|
|
165
136
|
className: "lb-icon-container",
|
|
166
137
|
children: /* @__PURE__ */ jsx(ArrowDownIcon, {})
|
|
@@ -171,41 +142,34 @@ const AiChat = forwardRef(
|
|
|
171
142
|
/* @__PURE__ */ jsx(AiChatComposer, {
|
|
172
143
|
chatId,
|
|
173
144
|
copilotId,
|
|
174
|
-
overrides
|
|
145
|
+
overrides,
|
|
175
146
|
autoFocus,
|
|
176
|
-
onUserMessageCreate: ({ id }) =>
|
|
147
|
+
onUserMessageCreate: ({ id }) => setLastSentMessageId(id),
|
|
148
|
+
className: layout === "inset" ? "lb-elevation lb-elevation-moderate" : void 0
|
|
177
149
|
}, chatId)
|
|
178
150
|
]
|
|
151
|
+
}),
|
|
152
|
+
/* @__PURE__ */ jsx("div", {
|
|
153
|
+
ref: containerBottomRef,
|
|
154
|
+
style: { position: "sticky", height: 0 },
|
|
155
|
+
"aria-hidden": true,
|
|
156
|
+
"data-scroll-at-bottom": isScrollAtBottom ? "" : void 0
|
|
179
157
|
})
|
|
180
158
|
]
|
|
181
159
|
});
|
|
182
160
|
}
|
|
183
161
|
);
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
components,
|
|
188
|
-
onDistanceToBottomChange
|
|
162
|
+
function AutoScrollHandler({
|
|
163
|
+
lastSentMessageId,
|
|
164
|
+
scrollToBottom
|
|
189
165
|
}) {
|
|
190
166
|
useLayoutEffect(() => {
|
|
191
|
-
|
|
192
|
-
}, [
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
overrides
|
|
198
|
-
}, message.id);
|
|
199
|
-
} else if (message.role === "assistant") {
|
|
200
|
-
return /* @__PURE__ */ jsx(AiChatAssistantMessage, {
|
|
201
|
-
message,
|
|
202
|
-
overrides,
|
|
203
|
-
components
|
|
204
|
-
}, message.id);
|
|
205
|
-
} else {
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
});
|
|
167
|
+
scrollToBottom("instant");
|
|
168
|
+
}, [scrollToBottom]);
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
scrollToBottom("smooth");
|
|
171
|
+
}, [lastSentMessageId, scrollToBottom]);
|
|
172
|
+
return null;
|
|
209
173
|
}
|
|
210
174
|
|
|
211
175
|
export { AiChat };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiChat.js","sources":["../../src/components/AiChat.tsx"],"sourcesContent":["import type {\n AiKnowledgeSource,\n AiToolDefinition,\n CopilotId,\n MessageId,\n UiChatMessage,\n} from \"@liveblocks/core\";\nimport { kInternal } from \"@liveblocks/core\";\nimport {\n RegisterAiKnowledge,\n useAiChatMessages,\n useClient,\n} from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n type ComponentProps,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport type { GlobalComponents } from \"../components\";\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { SpinnerIcon } from \"../icons/Spinner\";\nimport {\n type AiChatComposerOverrides,\n type AiChatMessageOverrides,\n type AiChatOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { AiChatAssistantMessage } from \"./internal/AiChatAssistantMessage\";\nimport { AiChatComposer } from \"./internal/AiChatComposer\";\nimport { AiChatUserMessage } from \"./internal/AiChatUserMessage\";\n\n/**\n * The number of pixels from the bottom of the messages list to trigger the scroll to bottom.\n */\nconst MIN_DISTANCE_TO_BOTTOM = 50;\n\nexport interface AiChatProps extends ComponentProps<\"div\"> {\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n /**\n * Whether to focus the chat composer on mount.\n */\n autoFocus?: boolean;\n /**\n * The id of the copilot to use to send the message.\n */\n copilotId?: string;\n /**\n * The contextual knowledge to include in the chat. May be used by the assistant when generating responses.\n * Any knowledge you provide via this prop will be added to any already globally registered knowledge via <RegisterAiKnowledge />.\n */\n knowledge?: AiKnowledgeSource[];\n /**\n * Tool definitions to make available within this chat. May be used by the assistant when generating responses.\n */\n tools?: Record<string, AiToolDefinition>;\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides &\n AiChatMessageOverrides &\n AiChatComposerOverrides &\n AiChatOverrides\n >;\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents>; // TODO: Add more slots than the global ones over time (Markdown tags, the empty state, etc)\n}\n\nexport const AiChat = forwardRef<HTMLDivElement, AiChatProps>(\n (\n {\n chatId,\n copilotId,\n autoFocus,\n overrides,\n knowledge,\n tools = {},\n components,\n className,\n ...props\n },\n forwardedRef\n ) => {\n const { messages, isLoading, error } = useAiChatMessages(chatId);\n const $ = useOverrides(overrides);\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [distanceToBottom, setDistanceToBottom] = useState<number | null>(\n null\n );\n const client = useClient();\n const ai = client[kInternal].ai;\n\n const [lastSendMessageId, setLastSendMessageId] =\n useState<MessageId | null>(null);\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => containerRef.current,\n []\n );\n\n // Register the provided tools to the chat on mount and unregister them on unmount\n useEffect(() => {\n Object.entries(tools).map(([key, value]) =>\n ai.registerChatTool(chatId, key, value)\n );\n return () => {\n Object.entries(tools).map(([key]) =>\n ai.unregisterChatTool(chatId, key)\n );\n };\n }, [ai, chatId, tools]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n function handleScrollChange() {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }\n container.addEventListener(\"scroll\", handleScrollChange);\n return () => {\n container.removeEventListener(\"scroll\", handleScrollChange);\n };\n }, []);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }, [messages]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }, [lastSendMessageId]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const observer = new ResizeObserver(() => {\n const container = containerRef.current;\n if (container === null) return;\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n });\n observer.observe(container);\n return () => {\n observer.disconnect();\n };\n }, []);\n\n const scrollToBottomCallbackRef = useRef<() => void>(undefined);\n if (scrollToBottomCallbackRef.current === undefined) {\n scrollToBottomCallbackRef.current = function () {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"instant\",\n });\n };\n }\n const isScrollIndicatorVisible =\n distanceToBottom !== null && distanceToBottom > MIN_DISTANCE_TO_BOTTOM;\n\n return (\n <div\n ref={containerRef}\n {...props}\n className={classNames(\"lb-root lb-ai-chat\", className)}\n >\n {knowledge\n ? knowledge.map((source, index) => (\n <RegisterAiKnowledge\n key={index}\n description={source.description}\n value={source.value}\n // knowledgeKey={source.knowledgeKey}\n />\n ))\n : null}\n <div className=\"lb-ai-chat-content\">\n {isLoading ? (\n <div className=\"lb-loading lb-ai-chat-loading\">\n <SpinnerIcon />\n </div>\n ) : error !== undefined ? (\n <div className=\"lb-error lb-ai-chat-error\">\n {$.AI_CHAT_MESSAGES_ERROR(error)}\n </div>\n ) : (\n <div className=\"lb-ai-chat-messages\">\n <Messages\n messages={messages}\n overrides={$}\n components={components}\n onDistanceToBottomChange={scrollToBottomCallbackRef.current}\n />\n </div>\n )}\n </div>\n\n <div className=\"lb-ai-chat-footer\">\n <div className=\"lb-ai-chat-footer-actions\">\n <div\n className=\"lb-elevation lb-ai-chat-scroll-indicator\"\n data-visible={isScrollIndicatorVisible ? \"\" : undefined}\n >\n <button\n className=\"lb-ai-chat-scroll-indicator-button\"\n tabIndex={isScrollIndicatorVisible ? 0 : -1}\n aria-hidden={!isScrollIndicatorVisible}\n disabled={!isScrollIndicatorVisible}\n onClick={() => {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }}\n >\n <span className=\"lb-icon-container\">\n <ArrowDownIcon />\n </span>\n </button>\n </div>\n </div>\n <AiChatComposer\n key={chatId}\n chatId={chatId}\n copilotId={copilotId as CopilotId}\n overrides={$}\n autoFocus={autoFocus}\n onUserMessageCreate={({ id }) => setLastSendMessageId(id)}\n />\n </div>\n </div>\n );\n }\n);\n\nfunction Messages({\n messages,\n overrides,\n components,\n onDistanceToBottomChange,\n}: {\n messages: readonly UiChatMessage[];\n overrides?: Partial<GlobalOverrides & AiChatMessageOverrides>;\n components?: Partial<GlobalComponents>;\n onDistanceToBottomChange: () => void;\n}) {\n useLayoutEffect(() => {\n onDistanceToBottomChange();\n }, [onDistanceToBottomChange]);\n\n return messages.map((message) => {\n if (message.role === \"user\") {\n return (\n <AiChatUserMessage\n key={message.id}\n message={message}\n overrides={overrides}\n />\n );\n } else if (message.role === \"assistant\") {\n return (\n <AiChatAssistantMessage\n key={message.id}\n message={message}\n overrides={overrides}\n components={components}\n />\n );\n } else {\n return null;\n }\n });\n}\n"],"names":["container"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AiChat.js","sources":["../../src/components/AiChat.tsx"],"sourcesContent":["import type {\n AiKnowledgeSource,\n AiOpaqueToolDefinition,\n CopilotId,\n MessageId,\n} from \"@liveblocks/core\";\nimport {\n RegisterAiKnowledge,\n RegisterAiTool,\n useAiChatMessages,\n} from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n type ComponentProps,\n type ComponentType,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport type { GlobalComponents } from \"../components\";\nimport { ArrowDownIcon } from \"../icons/ArrowDown\";\nimport { SpinnerIcon } from \"../icons/Spinner\";\nimport {\n type AiChatComposerOverrides,\n type AiChatMessageOverrides,\n type AiChatOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../overrides\";\nimport { classNames } from \"../utils/class-names\";\nimport { useVisible } from \"../utils/use-visible\";\nimport { AiChatAssistantMessage } from \"./internal/AiChatAssistantMessage\";\nimport { AiChatComposer } from \"./internal/AiChatComposer\";\nimport { AiChatUserMessage } from \"./internal/AiChatUserMessage\";\n\nexport type AiChatComponentsEmptyProps = {\n /**\n * The chat id provided to the `AiChat` component.\n */\n chatId: string;\n /**\n * The copilot id provided to the `AiChat` component.\n */\n copilotId?: string;\n};\n\nexport type AiChatComponentsLoadingProps = Record<string, never>;\n\n// TODO: Add Markdown components\nexport type AiChatComponents = {\n /**\n * The component used to render the empty state of the chat.\n */\n Empty: ComponentType<AiChatComponentsEmptyProps>;\n /**\n * The component used to render the loading state of the chat.\n */\n Loading: ComponentType<AiChatComponentsLoadingProps>;\n};\n\n/**\n * The minimum number of pixels from the bottom of the scrollable area\n * before showing the scroll to bottom indicator.\n */\nconst MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR = 50;\n\nexport interface AiChatProps extends ComponentProps<\"div\"> {\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n /**\n * Whether to focus the chat composer on mount.\n */\n autoFocus?: boolean;\n /**\n * The id of the copilot to use to send the message.\n */\n copilotId?: string;\n /**\n * The contextual knowledge to include in the chat. May be used by the assistant when generating responses.\n * Any knowledge you provide via this prop will be added to any already globally registered knowledge via <RegisterAiKnowledge />.\n */\n knowledge?: AiKnowledgeSource[];\n /**\n * Tool definitions to make available within this chat. May be used by the assistant when generating responses.\n */\n tools?: Record<string, AiOpaqueToolDefinition>;\n /**\n * The layout of the chat and its composer.\n */\n layout?: \"inset\" | \"compact\";\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides &\n AiChatMessageOverrides &\n AiChatComposerOverrides &\n AiChatOverrides\n >;\n /**\n * Override the component's components.\n */\n components?: Partial<GlobalComponents & AiChatComponents>;\n}\n\nconst defaultComponents: AiChatComponents = {\n Empty: () => null,\n Loading: () => (\n <div className=\"lb-loading lb-ai-chat-loading\">\n <SpinnerIcon />\n </div>\n ),\n};\n\nexport const AiChat = forwardRef<HTMLDivElement, AiChatProps>(\n (\n {\n chatId,\n copilotId,\n autoFocus,\n overrides,\n knowledge,\n tools = {},\n layout = \"inset\",\n components,\n className,\n ...props\n },\n forwardedRef\n ) => {\n const { messages, isLoading, error } = useAiChatMessages(chatId);\n const $ = useOverrides(overrides);\n const Empty = components?.Empty ?? defaultComponents.Empty;\n const Loading = components?.Loading ?? defaultComponents.Loading;\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const containerBottomRef = useRef<HTMLDivElement | null>(null);\n const isScrollIndicatorEnabled = !isLoading && !error;\n const isScrollAtBottom = useVisible(containerBottomRef, {\n enabled: isScrollIndicatorEnabled,\n root: containerRef,\n rootMargin: MIN_DISTANCE_BOTTOM_SCROLL_INDICATOR,\n initialValue: null,\n });\n const isScrollIndicatorVisible =\n isScrollIndicatorEnabled && isScrollAtBottom !== null\n ? !isScrollAtBottom\n : false;\n\n const [lastSentMessageId, setLastSentMessageId] =\n useState<MessageId | null>(null);\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => containerRef.current,\n []\n );\n\n const scrollToBottomCallbackRef =\n useRef<(behavior: \"instant\" | \"smooth\") => void>(undefined);\n if (scrollToBottomCallbackRef.current === undefined) {\n scrollToBottomCallbackRef.current = function (\n behavior: \"instant\" | \"smooth\"\n ) {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior,\n });\n };\n }\n const scrollToBottom = scrollToBottomCallbackRef.current;\n\n return (\n <div\n ref={containerRef}\n {...props}\n className={classNames(\n \"lb-root lb-ai-chat\",\n layout === \"compact\"\n ? \"lb-ai-chat:layout-compact\"\n : \"lb-ai-chat:layout-inset\",\n className\n )}\n >\n {knowledge\n ? knowledge.map((source, index) => (\n <RegisterAiKnowledge\n key={index}\n description={source.description}\n value={source.value}\n // knowledgeKey={source.knowledgeKey}\n />\n ))\n : null}\n\n {Object.entries(tools).map(([name, tool]) => (\n <RegisterAiTool key={name} chatId={chatId} name={name} tool={tool} />\n ))}\n\n <div className=\"lb-ai-chat-content\">\n {isLoading ? (\n <Loading />\n ) : error !== undefined ? (\n <div className=\"lb-error lb-ai-chat-error\">\n {$.AI_CHAT_MESSAGES_ERROR(error)}\n </div>\n ) : messages.length === 0 ? (\n <Empty chatId={chatId} copilotId={copilotId} />\n ) : (\n <>\n <AutoScrollHandler\n lastSentMessageId={lastSentMessageId}\n scrollToBottom={scrollToBottom}\n />\n <div className=\"lb-ai-chat-messages\">\n {messages.map((message) => {\n if (message.role === \"user\") {\n return (\n <AiChatUserMessage\n key={message.id}\n message={message}\n overrides={overrides}\n />\n );\n } else if (message.role === \"assistant\") {\n return (\n <AiChatAssistantMessage\n key={message.id}\n message={message}\n overrides={overrides}\n components={components}\n />\n );\n } else {\n return null;\n }\n })}\n </div>\n </>\n )}\n </div>\n\n <div className=\"lb-ai-chat-footer\">\n <div className=\"lb-ai-chat-footer-actions\">\n <div\n className=\"lb-root lb-elevation lb-elevation-moderate lb-ai-chat-scroll-indicator\"\n data-visible={isScrollIndicatorVisible ? \"\" : undefined}\n >\n <button\n className=\"lb-ai-chat-scroll-indicator-button\"\n tabIndex={isScrollIndicatorVisible ? 0 : -1}\n aria-hidden={!isScrollIndicatorVisible}\n onClick={() => scrollToBottom(\"smooth\")}\n >\n <span className=\"lb-icon-container\">\n <ArrowDownIcon />\n </span>\n </button>\n </div>\n </div>\n <AiChatComposer\n key={chatId}\n chatId={chatId}\n copilotId={copilotId as CopilotId}\n overrides={overrides}\n autoFocus={autoFocus}\n onUserMessageCreate={({ id }) => setLastSentMessageId(id)}\n className={\n layout === \"inset\"\n ? \"lb-elevation lb-elevation-moderate\"\n : undefined\n }\n />\n </div>\n {/* This invisible element is a trick which allows us to use IntersectionObserver to detect when the\n * scrollable area is fully scrolled to the bottom instead of manually tracking the scroll position\n * and having to deal with resizes, etc.\n *\n * It's positioned at the bottom of the scrollable area and reliably only becomes \"visible\" to the\n * IntersectionObserver when the scrollable area is fully scrolled.\n */}\n <div\n ref={containerBottomRef}\n style={{ position: \"sticky\", height: 0 }}\n aria-hidden\n data-scroll-at-bottom={isScrollAtBottom ? \"\" : undefined}\n />\n </div>\n );\n }\n);\n\nfunction AutoScrollHandler({\n lastSentMessageId,\n scrollToBottom,\n}: {\n lastSentMessageId: MessageId | null;\n scrollToBottom: (behavior: \"instant\" | \"smooth\") => void;\n}) {\n // Scroll to bottom when the component first mounts\n useLayoutEffect(() => {\n scrollToBottom(\"instant\");\n }, [scrollToBottom]);\n\n // Scroll to bottom when sending a new message\n useEffect(() => {\n scrollToBottom(\"smooth\");\n }, [lastSentMessageId, scrollToBottom]);\n\n return null;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var core = require('@liveblocks/core');
|
|
5
|
+
var react = require('react');
|
|
6
|
+
require('../_private/index.cjs');
|
|
7
|
+
require('../icons/index.cjs');
|
|
8
|
+
var overrides = require('../overrides.cjs');
|
|
9
|
+
var contexts = require('../primitives/AiMessage/contexts.cjs');
|
|
10
|
+
var index = require('../primitives/Collapsible/index.cjs');
|
|
11
|
+
var classNames = require('../utils/class-names.cjs');
|
|
12
|
+
var useControllableState = require('../utils/use-controllable-state.cjs');
|
|
13
|
+
var CodeBlock = require('./internal/CodeBlock.cjs');
|
|
14
|
+
var Button = require('./internal/Button.cjs');
|
|
15
|
+
var ChevronRight = require('../icons/ChevronRight.cjs');
|
|
16
|
+
var CheckCircleFill = require('../icons/CheckCircleFill.cjs');
|
|
17
|
+
var CrossCircleFill = require('../icons/CrossCircleFill.cjs');
|
|
18
|
+
var MinusCircle = require('../icons/MinusCircle.cjs');
|
|
19
|
+
var Spinner = require('../icons/Spinner.cjs');
|
|
20
|
+
|
|
21
|
+
function AiToolIcon({ className, ...props }) {
|
|
22
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
23
|
+
className: classNames.classNames("lb-ai-tool-icon", className),
|
|
24
|
+
...props
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function AiToolInspector({ className, ...props }) {
|
|
28
|
+
const { args, partialArgs, result } = contexts.useAiToolInvocationContext();
|
|
29
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
30
|
+
className: classNames.classNames("lb-ai-tool-inspector", className),
|
|
31
|
+
...props,
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsxRuntime.jsx(CodeBlock.CodeBlock, {
|
|
34
|
+
title: "Arguments",
|
|
35
|
+
code: JSON.stringify(args ?? partialArgs, null, 2)
|
|
36
|
+
}),
|
|
37
|
+
result !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlock.CodeBlock, {
|
|
38
|
+
title: "Result",
|
|
39
|
+
code: JSON.stringify(result, null, 2)
|
|
40
|
+
}) : null
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function AiToolConfirmation({
|
|
45
|
+
children,
|
|
46
|
+
variant = "default",
|
|
47
|
+
confirm,
|
|
48
|
+
cancel,
|
|
49
|
+
overrides: overrides$1,
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}) {
|
|
53
|
+
const { stage, args, respond, name, invocationId } = contexts.useAiToolInvocationContext();
|
|
54
|
+
const $ = overrides.useOverrides(overrides$1);
|
|
55
|
+
const enabled = stage === "executing";
|
|
56
|
+
const context = react.useMemo(() => ({ name, invocationId }), [name, invocationId]);
|
|
57
|
+
const onConfirmClick = react.useCallback(async () => {
|
|
58
|
+
if (enabled) {
|
|
59
|
+
const result = await confirm(args, context);
|
|
60
|
+
respond(result ?? void 0);
|
|
61
|
+
}
|
|
62
|
+
}, [enabled, args, confirm, respond, context]);
|
|
63
|
+
const onCancelClick = react.useCallback(async () => {
|
|
64
|
+
if (enabled) {
|
|
65
|
+
if (cancel === void 0) {
|
|
66
|
+
respond({ cancel: true });
|
|
67
|
+
} else {
|
|
68
|
+
const result = await cancel(args, context);
|
|
69
|
+
respond(result ?? void 0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, [enabled, args, cancel, respond, context]);
|
|
73
|
+
if (stage === "executed" && !children) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
77
|
+
className: classNames.classNames("lb-ai-tool-confirmation", className),
|
|
78
|
+
...props,
|
|
79
|
+
children: [
|
|
80
|
+
children ? /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
81
|
+
className: "lb-ai-tool-confirmation-content",
|
|
82
|
+
children
|
|
83
|
+
}) : null,
|
|
84
|
+
stage !== "executed" && /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
85
|
+
className: "lb-ai-tool-confirmation-footer",
|
|
86
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
87
|
+
className: "lb-ai-tool-confirmation-actions",
|
|
88
|
+
children: [
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button.Button, {
|
|
90
|
+
disabled: !enabled,
|
|
91
|
+
onClick: onCancelClick,
|
|
92
|
+
variant: "secondary",
|
|
93
|
+
children: $.AI_TOOL_CONFIRMATION_CANCEL
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button.Button, {
|
|
96
|
+
disabled: !enabled,
|
|
97
|
+
onClick: onConfirmClick,
|
|
98
|
+
variant: variant === "destructive" ? "destructive" : "primary",
|
|
99
|
+
children: $.AI_TOOL_CONFIRMATION_CONFIRM
|
|
100
|
+
})
|
|
101
|
+
]
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function prettifyString(string) {
|
|
108
|
+
return string.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase().replace(/^\w/, (character) => character.toUpperCase());
|
|
109
|
+
}
|
|
110
|
+
const AiTool = Object.assign(
|
|
111
|
+
react.forwardRef(
|
|
112
|
+
({
|
|
113
|
+
children,
|
|
114
|
+
title,
|
|
115
|
+
icon,
|
|
116
|
+
collapsed,
|
|
117
|
+
onCollapsedChange,
|
|
118
|
+
className,
|
|
119
|
+
...props
|
|
120
|
+
}, forwardedRef) => {
|
|
121
|
+
const {
|
|
122
|
+
stage,
|
|
123
|
+
result,
|
|
124
|
+
name,
|
|
125
|
+
[core.kInternal]: { execute }
|
|
126
|
+
} = contexts.useAiToolInvocationContext();
|
|
127
|
+
const [semiControlledCollapsed, onSemiControlledCollapsed] = useControllableState.useSemiControllableState(collapsed ?? false, onCollapsedChange);
|
|
128
|
+
const hasContent = react.Children.count(children) > 0;
|
|
129
|
+
const resolvedTitle = react.useMemo(() => {
|
|
130
|
+
return title ?? prettifyString(name);
|
|
131
|
+
}, [title, name]);
|
|
132
|
+
const handleCollapsibleOpenChange = react.useCallback(
|
|
133
|
+
(open) => {
|
|
134
|
+
onSemiControlledCollapsed(!open);
|
|
135
|
+
},
|
|
136
|
+
[onSemiControlledCollapsed]
|
|
137
|
+
);
|
|
138
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(index.Root, {
|
|
139
|
+
ref: forwardedRef,
|
|
140
|
+
className: classNames.classNames("lb-collapsible lb-ai-tool", className),
|
|
141
|
+
...props,
|
|
142
|
+
open: hasContent ? !semiControlledCollapsed : false,
|
|
143
|
+
onOpenChange: handleCollapsibleOpenChange,
|
|
144
|
+
disabled: !hasContent,
|
|
145
|
+
"data-result": result?.type,
|
|
146
|
+
"data-stage": stage,
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ jsxRuntime.jsxs(index.Trigger, {
|
|
149
|
+
className: "lb-collapsible-trigger lb-ai-tool-header",
|
|
150
|
+
children: [
|
|
151
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
152
|
+
className: "lb-ai-tool-header-icon-container",
|
|
153
|
+
children: icon
|
|
154
|
+
}) : null,
|
|
155
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
156
|
+
className: "lb-ai-tool-header-title",
|
|
157
|
+
children: resolvedTitle
|
|
158
|
+
}),
|
|
159
|
+
hasContent ? /* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
160
|
+
className: "lb-collapsible-chevron lb-icon-container",
|
|
161
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight.ChevronRightIcon, {})
|
|
162
|
+
}) : null,
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
164
|
+
className: "lb-ai-tool-header-status",
|
|
165
|
+
children: stage === "executed" ? result.type === "success" ? /* @__PURE__ */ jsxRuntime.jsx(CheckCircleFill.CheckCircleFillIcon, {}) : result.type === "error" ? /* @__PURE__ */ jsxRuntime.jsx(CrossCircleFill.CrossCircleFillIcon, {}) : result.type === "cancelled" ? /* @__PURE__ */ jsxRuntime.jsx(MinusCircle.MinusCircleIcon, {}) : null : execute !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(Spinner.SpinnerIcon, {}) : null
|
|
166
|
+
})
|
|
167
|
+
]
|
|
168
|
+
}),
|
|
169
|
+
hasContent ? /* @__PURE__ */ jsxRuntime.jsx(index.Content, {
|
|
170
|
+
className: "lb-collapsible-content lb-ai-tool-content-container",
|
|
171
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
172
|
+
className: "lb-ai-tool-content",
|
|
173
|
+
children
|
|
174
|
+
})
|
|
175
|
+
}) : null
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
{
|
|
181
|
+
Icon: AiToolIcon,
|
|
182
|
+
Inspector: AiToolInspector,
|
|
183
|
+
Confirmation: AiToolConfirmation
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
exports.AiTool = AiTool;
|
|
188
|
+
//# sourceMappingURL=AiTool.cjs.map
|