import { For, Show } from 'solid-js'; import { Avatar } from '../avatars/Avatar'; import { Marked } from '@ts-stack/markdown'; import { FileUpload, MessageType } from '../Bot'; import { AttachmentIcon } from '../icons'; type Props = { message: MessageType; apiHost?: string; chatflowid: string; chatId: string; showAvatar?: boolean; avatarSrc?: string; backgroundColor?: string; textColor?: string; fontSize?: number; renderHTML?: boolean; }; const defaultBackgroundColor = '#3B81F6'; const defaultTextColor = '#ffffff'; const defaultFontSize = 16; export const GuestBubble = (props: Props) => { Marked.setOptions({ isNoP: true, sanitize: props.renderHTML !== undefined ? !props.renderHTML : true }); // Callback ref to set innerHTML and apply text color to all Markdown elements const setUserMessageRef = (el: HTMLSpanElement) => { if (el) { el.innerHTML = Marked.parse(props.message.message); // Apply textColor to all links, headings, and other markdown elements const textColor = props.textColor ?? defaultTextColor; el.querySelectorAll('a, h1, h2, h3, h4, h5, h6, strong, em, blockquote, li').forEach((element) => { (element as HTMLElement).style.color = textColor; }); // Code blocks (with pre) get white text el.querySelectorAll('pre').forEach((element) => { (element as HTMLElement).style.color = '#FFFFFF'; // Also ensure any code elements inside pre have white text element.querySelectorAll('code').forEach((codeElement) => { (codeElement as HTMLElement).style.color = '#FFFFFF'; }); }); // Inline code (not in pre) gets green text el.querySelectorAll('code:not(pre code)').forEach((element) => { (element as HTMLElement).style.color = '#4CAF50'; // Green color }); // Set target="_blank" for links el.querySelectorAll('a').forEach((link) => { link.target = '_blank'; }); } }; const renderFileUploads = (item: Partial) => { if (item?.mime?.startsWith('image/')) { const fileData = `${props.apiHost}/api/v1/get-upload-file?chatflowId=${props.chatflowid}&chatId=${props.chatId}&fileName=${item.name}`; const src = (item.data as string) ?? fileData; return (
); } else if (item?.mime?.startsWith('audio/')) { const fileData = `${props.apiHost}/api/v1/get-upload-file?chatflowId=${props.chatflowid}&chatId=${props.chatId}&fileName=${item.name}`; const src = (item.data as string) ?? fileData; return ( ); } else { return (
{item.name}
); } }; return (
{props.message.fileUploads && props.message.fileUploads.length > 0 && (
{(item) => { return renderFileUploads(item); }}
)} {props.message.message && ( )}
); };