diff --git a/src/client/AIAssistantProvider.tsx b/src/client/AIAssistantProvider.tsx index 6abbd7f..8dde022 100644 --- a/src/client/AIAssistantProvider.tsx +++ b/src/client/AIAssistantProvider.tsx @@ -8,7 +8,7 @@ import React, { useState, } from "react"; import type { ExplainContext, ExplainEvent } from "../types"; -import AIChatBot from "./AIChatBot"; +import AIChatBot, { type MessageRenderer } from "./AIChatBot"; import AIFloatingButton from "./AIFloatingButton"; import * as S from "./styles"; @@ -44,6 +44,7 @@ type AIAssistantProviderProps = { subtitle?: string; onExplain?: (event: ExplainEvent) => void; showChat?: boolean; + renderMessage?: MessageRenderer; }; /** @@ -125,6 +126,7 @@ export default function AIAssistantProvider({ subtitle, onExplain, showChat = true, + renderMessage, }: AIAssistantProviderProps) { const [isChatOpen, setIsChatOpen] = useState(false); const [initialQuery, setInitialQuery] = useState(""); @@ -309,6 +311,7 @@ export default function AIAssistantProvider({ apiKey={apiKey} title={title} subtitle={subtitle} + renderMessage={renderMessage} /> )} diff --git a/src/client/AIChatBot.tsx b/src/client/AIChatBot.tsx index 2e849c8..7c44b02 100644 --- a/src/client/AIChatBot.tsx +++ b/src/client/AIChatBot.tsx @@ -12,6 +12,8 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; import type { Message } from "../types"; import * as S from "./styles"; +export type MessageRenderer = (message: Message) => React.ReactNode; + type Props = { open: boolean; onClose: () => void; @@ -20,6 +22,7 @@ type Props = { apiKey?: string; title?: string; subtitle?: string; + renderMessage?: MessageRenderer; }; async function fetchAIResponse( @@ -54,6 +57,25 @@ async function fetchAIResponse( return data.reply; } +function defaultRenderMessage(msg: Message): React.ReactNode { + return msg.content.split("\n").map((line, i) => ( + + {line + .split(/(\*\*[^*]+\*\*)/) + .map((part, j) => + part.startsWith("**") && part.endsWith("**") ? ( + + {part.slice(2, -2)} + + ) : ( + {part} + ), + )} + {i < msg.content.split("\n").length - 1 &&
} +
+ )); +} + export default function AIChatBot({ open, onClose, @@ -62,6 +84,7 @@ export default function AIChatBot({ apiKey, title = "AI Assistant", subtitle = "Ask anything", + renderMessage, }: Props) { const [messages, setMessages] = useState([]); const [input, setInput] = useState(""); @@ -244,22 +267,9 @@ export default function AIChatBot({ )}
- {msg.content.split("\n").map((line, i) => ( - - {line - .split(/(\*\*[^*]+\*\*)/) - .map((part, j) => - part.startsWith("**") && part.endsWith("**") ? ( - - {part.slice(2, -2)} - - ) : ( - {part} - ), - )} - {i < msg.content.split("\n").length - 1 &&
} -
- ))} + {renderMessage + ? renderMessage(msg) + : defaultRenderMessage(msg)}
{msg.role === "user" && (
diff --git a/src/client/index.ts b/src/client/index.ts index 7f5624d..896895a 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,4 +1,5 @@ export { default as AIAssistantProvider, useAIAssistant } from "./AIAssistantProvider"; export { default as AIChatBot } from "./AIChatBot"; +export type { MessageRenderer } from "./AIChatBot"; export { default as AIFloatingButton } from "./AIFloatingButton"; export type { Message, ExplainContext, ExplainEvent } from "../types"; \ No newline at end of file