@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
138 lines (135 loc) • 5.45 kB
JavaScript
'use client';
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
import { useTranslation } from "../../i18n/useTranslation.mjs";
import chat_default from "../../i18n/resources/en/chat.mjs";
import { styles } from "./style.mjs";
import Actions_default from "./components/Actions.mjs";
import Avatar_default from "./components/Avatar.mjs";
import BorderSpacing_default from "./components/BorderSpacing.mjs";
import ErrorContent_default from "./components/ErrorContent.mjs";
import MessageContent_default from "./components/MessageContent.mjs";
import Title_default from "./components/Title.mjs";
import { memo, useEffect, useMemo, useRef, useState } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { cx, useResponsive } from "antd-style";
//#region src/chat/ChatItem/ChatItem.tsx
const MOBILE_AVATAR_SIZE = 32;
const ChatItem = memo(({ avatarAddon, onAvatarClick, avatarProps, actions, className, primary, loading, message, placeholderMessage, placement = "left", variant = "bubble", avatar, error, showTitle, time, editing, onChange, onEditingChange, messageExtra, renderMessage, text, errorMessage, onDoubleClick, fontSize, aboveMessage, belowMessage, markdownProps, actionsWrapWidth = 54, showAvatar = true, titleAddon, ...rest }) => {
const { mobile } = useResponsive();
const { t } = useTranslation(chat_default);
const avatarSize = mobile ? MOBILE_AVATAR_SIZE : avatarProps?.size || 40;
const cssVariables = useMemo(() => ({ "--chat-item-avatar-size": `${avatarSize}px` }), [avatarSize]);
const hasTime = Boolean(time);
const placeholderText = placeholderMessage ?? t("chat.placeholder");
const avatarAlt = avatarProps?.alt || avatar.title || t("chat.avatar");
const contentRef = useRef(null);
const containerRef = useRef(null);
const [layoutMode, setLayoutMode] = useState(variant === "bubble" ? "horizontal" : "vertical");
useEffect(() => {
if (variant === "docs") {
setLayoutMode("vertical");
return;
}
if (!contentRef.current || !containerRef.current) return;
const observer = new ResizeObserver(() => {
if (!contentRef.current || !containerRef.current) return;
const containerWidth = containerRef.current.clientWidth;
const contentWidth = contentRef.current.scrollWidth;
setLayoutMode(contentWidth + actionsWrapWidth > containerWidth ? "vertical" : "horizontal");
});
observer.observe(contentRef.current);
observer.observe(containerRef.current);
return () => observer.disconnect();
}, [variant, actionsWrapWidth]);
const containerClassName = cx(variant === "docs" ? styles.containerDocs : styles.container, className);
const messageContainerClassName = useMemo(() => {
if (editing) return hasTime ? styles.messageContainerEditingWithTime : styles.messageContainerEditing;
return hasTime ? styles.messageContainerWithTime : styles.messageContainer;
}, [editing, hasTime]);
const messageContentClassName = useMemo(() => {
return editing ? styles.messageContentEditing : styles.messageContent;
}, [editing]);
return /* @__PURE__ */ jsxs(FlexBasic_default, {
className: containerClassName,
direction: placement === "left" ? "horizontal" : "horizontal-reverse",
gap: mobile ? 6 : 12,
style: cssVariables,
...rest,
children: [
showAvatar && /* @__PURE__ */ jsx(Avatar_default, {
...avatarProps,
addon: avatarAddon,
alt: avatarAlt,
avatar,
loading,
onClick: onAvatarClick,
placement,
size: avatarSize,
style: {
marginTop: showTitle ? -12 : 6,
...avatarProps?.style
}
}),
/* @__PURE__ */ jsxs(FlexBasic_default, {
align: placement === "left" ? "flex-start" : "flex-end",
className: messageContainerClassName,
ref: containerRef,
children: [
/* @__PURE__ */ jsx(Title_default, {
avatar,
placement,
showTitle,
time,
titleAddon
}),
aboveMessage,
/* @__PURE__ */ jsxs(FlexBasic_default, {
align: placement === "left" ? "flex-start" : "flex-end",
className: messageContentClassName,
"data-layout": layoutMode,
direction: layoutMode === "horizontal" ? placement === "left" ? "horizontal" : "horizontal-reverse" : "vertical",
gap: 8,
children: [/* @__PURE__ */ jsx(FlexBasic_default, {
ref: contentRef,
width: "100%",
children: error && (message === placeholderText || !message) ? /* @__PURE__ */ jsx(ErrorContent_default, {
error,
message: errorMessage,
placement
}) : /* @__PURE__ */ jsx(MessageContent_default, {
editing,
fontSize,
markdownProps,
message,
messageExtra: /* @__PURE__ */ jsxs(Fragment$1, { children: [error && /* @__PURE__ */ jsx(ErrorContent_default, {
error,
message: errorMessage,
placement
}), messageExtra] }),
onChange,
onDoubleClick,
onEditingChange,
placement,
primary,
renderMessage,
text,
variant
})
}), actions && /* @__PURE__ */ jsx(Actions_default, {
actions,
editing,
placement,
variant
})]
}),
belowMessage
]
}),
mobile && variant === "bubble" && showAvatar && /* @__PURE__ */ jsx(BorderSpacing_default, { borderSpacing: MOBILE_AVATAR_SIZE })
]
});
});
var ChatItem_default = ChatItem;
//#endregion
export { ChatItem_default as default };
//# sourceMappingURL=ChatItem.mjs.map