@cometchat/chat-uikit-react
Version:
Ready-to-use Chat UI Components for React
287 lines (283 loc) • 9.43 kB
JavaScript
import './index.css';
import { CometChatMarkdownFormatter, usePublishEvent } from './chunk-MI3XOQGY.js';
import { CometChatUIKitConstants } from './chunk-3DZVPW3I.js';
import { useTheme } from './chunk-SXG4FP55.js';
import { useCometChatFrameContext } from './chunk-UTFM6ET6.js';
import { useLocale } from './chunk-UVWJYQJ3.js';
import { useMemo, useState, useCallback } from 'react';
import { CometChatCardView } from '@cometchat/cards-react';
import DOMPurify from 'dompurify';
import { jsx, jsxs } from 'react/jsx-runtime';
var AI_ALLOWED_TAGS = [
"span",
"strong",
"em",
"b",
"i",
"u",
"s",
"del",
"code",
"pre",
"blockquote",
"ul",
"ol",
"li",
"a",
"br",
"p",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"table",
"thead",
"tbody",
"tr",
"th",
"td",
"img",
"hr"
];
var AI_ALLOWED_ATTR = [
"class",
"href",
"target",
"rel",
"src",
"alt",
"width",
"height",
"style",
"data-uid",
"data-mention-type"
];
function sanitizeAIHtml(html) {
if (!html) return "";
return DOMPurify.sanitize(html, {
ALLOWED_TAGS: AI_ALLOWED_TAGS,
ALLOWED_ATTR: AI_ALLOWED_ATTR
});
}
// src/assets/Copy.svg
var Copy_default = 'data:image/svg+xml,<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">%0A<g id="Base_Icon">%0A<path id="Vector" d="M7.92188 18.6641C7.49471 18.6641 7.12404 18.5069 6.80988 18.1926C6.49554 17.8784 6.33838 17.5077 6.33838 17.0806V3.74731C6.33838 3.32015 6.49554 2.94948 6.80988 2.63531C7.12404 2.32115 7.49471 2.16406 7.92188 2.16406H18.2551C18.6823 2.16406 19.053 2.32115 19.3671 2.63531C19.6813 2.94948 19.8384 3.32015 19.8384 3.74731V17.0806C19.8384 17.5077 19.6813 17.8784 19.3671 18.1926C19.053 18.5069 18.6823 18.6641 18.2551 18.6641H7.92188ZM7.92188 17.0806H18.2551V3.74731H7.92188V17.0806ZM4.75513 21.8306C4.32796 21.8306 3.95729 21.6735 3.64313 21.3593C3.32896 21.0451 3.17188 20.6745 3.17188 20.2473V6.11806C3.17188 5.90223 3.24921 5.71706 3.40387 5.56256C3.55854 5.4079 3.74604 5.33056 3.96638 5.33056C4.18671 5.33056 4.37321 5.4079 4.52588 5.56256C4.67871 5.71706 4.75513 5.90223 4.75513 6.11806V20.2473H15.8844C16.1002 20.2473 16.2854 20.3249 16.4399 20.4801C16.5945 20.6352 16.6719 20.8211 16.6719 21.0378C16.6719 21.2608 16.5945 21.4487 16.4399 21.6016C16.2854 21.7542 16.1002 21.8306 15.8844 21.8306H4.75513Z" fill="%23A1A1A1"/>%0A</g>%0A</svg>%0A';
var markdownFormatter = new CometChatMarkdownFormatter();
function renderAssistantMarkdown(text) {
if (!text) return "";
try {
return sanitizeAIHtml(markdownFormatter.format(text));
} catch {
return sanitizeAIHtml(text);
}
}
function extractElements(message) {
try {
const withElements = message;
return withElements.getElements?.() ?? [];
} catch {
return [];
}
}
function extractAssistantText(message) {
try {
const msgWithData = message;
const assistantText = msgWithData.getAssistantMessageData?.()?.getText?.();
if (assistantText) return assistantText;
if ("getText" in message && typeof message.getText === "function") {
const text = message.getText();
if (text) return text;
}
const data = message.data;
if (data?.text) return data.text;
if (data?.content) return data.content;
} catch {
}
return "";
}
var CometChatAIAssistantBubble = ({
message,
alignment = "left",
className
}) => {
const text = useMemo(() => extractAssistantText(message), [message]);
const elements = useMemo(() => extractElements(message), [message]);
const [copied, setCopied] = useState(false);
const { theme } = useTheme();
const publish = usePublishEvent();
const IframeContext = useCometChatFrameContext();
const getCurrentDocument = useCallback(() => {
return IframeContext.iframeDocument ?? document;
}, [IframeContext.iframeDocument]);
const { getLocalizedString } = useLocale();
const renderedHtml = useMemo(() => {
if (!text) return "";
try {
const html = markdownFormatter.format(text);
return sanitizeAIHtml(html);
} catch {
return sanitizeAIHtml(text);
}
}, [text]);
const handleCopy = useCallback(() => {
if (!text) return;
if (navigator.clipboard) {
void navigator.clipboard.writeText(text).then(() => {
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 2e3);
});
} else {
const textarea = getCurrentDocument().createElement("textarea");
textarea.value = text;
getCurrentDocument().body.appendChild(textarea);
textarea.select();
getCurrentDocument().execCommand("copy");
getCurrentDocument().body.removeChild(textarea);
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 2e3);
}
}, [text, getCurrentDocument]);
const handleCardAction = useCallback(
(event) => {
publish({ type: "ui:card/action", message, action: event.action });
},
[message, publish]
);
const renderElement = useCallback(
(element, index) => {
const type = element.getType();
const data = element.getData();
if (type === "text") {
const blockText = typeof data === "string" ? data : "";
if (!blockText) return null;
return /* @__PURE__ */ jsx(
"div",
{
className: "cometchat-ai-assistant-bubble__content",
dangerouslySetInnerHTML: { __html: renderAssistantMarkdown(blockText) }
},
`text-${String(index)}`
);
}
if (type === "card") {
const cardData = data;
const card = cardData?.card;
if (card != null) {
return /* @__PURE__ */ jsx(
"div",
{
className: "cometchat-card-bubble",
children: /* @__PURE__ */ jsx(
CometChatCardView,
{
cardJson: JSON.stringify(card),
themeMode: theme,
onAction: handleCardAction
}
)
},
`card-${cardData?.cardId ?? String(index)}`
);
}
return null;
}
return null;
},
[theme, handleCardAction]
);
const rootClasses = ["cometchat-ai-assistant-bubble", className].filter(Boolean).join(" ");
if (elements.length === 0 && !text) return null;
const showCopyButton = message.getReceiverType() !== CometChatUIKitConstants.MessageReceiverType.group;
if (elements.length > 0) {
return /* @__PURE__ */ jsxs("div", { className: rootClasses, "data-alignment": alignment, children: [
elements.map((element, index) => renderElement(element, index)),
showCopyButton && text && /* @__PURE__ */ jsxs(
"button",
{
className: "cometchat-ai-assistant-bubble__copy",
title: copied ? getLocalizedString("ai_copied") : getLocalizedString("ai_copy"),
"aria-label": copied ? getLocalizedString("ai_copied") : getLocalizedString("accessibility_copy_message"),
onClick: handleCopy,
type: "button",
children: [
/* @__PURE__ */ jsx(
"img",
{
src: Copy_default,
alt: "",
width: 20,
height: 20,
"aria-hidden": "true",
draggable: false,
style: { opacity: copied ? 1 : 0.6 }
}
),
copied && /* @__PURE__ */ jsx(
"span",
{
style: {
fontSize: 11,
color: "var(--cometchat-text-color-secondary)",
marginLeft: 4
},
children: getLocalizedString("ai_copied")
}
)
]
}
)
] });
}
return /* @__PURE__ */ jsxs("div", { className: rootClasses, "data-alignment": alignment, children: [
/* @__PURE__ */ jsx(
"div",
{
className: "cometchat-ai-assistant-bubble__content",
dangerouslySetInnerHTML: { __html: renderedHtml }
}
),
showCopyButton && /* @__PURE__ */ jsxs(
"button",
{
className: "cometchat-ai-assistant-bubble__copy",
title: copied ? getLocalizedString("ai_copied") : getLocalizedString("ai_copy"),
"aria-label": copied ? getLocalizedString("ai_copied") : getLocalizedString("accessibility_copy_message"),
onClick: handleCopy,
type: "button",
children: [
/* @__PURE__ */ jsx(
"img",
{
src: Copy_default,
alt: "",
width: 20,
height: 20,
"aria-hidden": "true",
draggable: false,
style: { opacity: copied ? 1 : 0.6 }
}
),
copied && /* @__PURE__ */ jsx(
"span",
{
style: {
fontSize: 11,
color: "var(--cometchat-text-color-secondary)",
marginLeft: 4
},
children: getLocalizedString("ai_copied")
}
)
]
}
)
] });
};
CometChatAIAssistantBubble.displayName = "CometChatAIAssistantBubble";
var CometChatAIAssistantBubble_default = CometChatAIAssistantBubble;
export { CometChatAIAssistantBubble, CometChatAIAssistantBubble_default, Copy_default, sanitizeAIHtml };