Skip to content

Commit

Permalink
✨ feat: ProChat support className
Browse files Browse the repository at this point in the history
  • Loading branch information
chenshuai2144 committed Jan 22, 2024
1 parent 76f45f8 commit 83d8bb3
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 56 deletions.
12 changes: 3 additions & 9 deletions src/ChatItem/components/Actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@ import { Flexbox } from 'react-layout-kit';

import { ChatItemProps } from '@/ChatItem';

import { useStyles } from '../style';

export interface ActionsProps {
actions: ChatItemProps['actions'];
editing?: boolean;
placement?: ChatItemProps['placement'];
type?: ChatItemProps['type'];
className?: string;
}

const Actions = memo<ActionsProps>(({ actions, placement, type, editing }) => {
const { styles } = useStyles({ editing, placement, type });

const Actions = memo<ActionsProps>(({ actions, className }) => {
return (
<Flexbox align={'flex-start'} className={styles.actions} role="menubar">
<Flexbox align={'flex-start'} className={className} role="menubar">
{actions}
</Flexbox>
);
Expand Down
48 changes: 25 additions & 23 deletions src/ChatItem/components/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import A from '@/components/Avatar';
import AvatarComponent from '@/components/Avatar';

import { useStyles } from '../style';
import type { ChatItemProps } from '../type';
Expand All @@ -16,28 +16,30 @@ export interface AvatarProps {
size?: number;
}

const Avatar = memo<AvatarProps>(({ loading, avatar, placement, addon, onClick, size = 40 }) => {
const { styles } = useStyles({ avatarSize: size });
const avatarContent = (
<div className={styles.avatarContainer}>
<A
avatar={avatar.avatar}
background={avatar.backgroundColor}
onClick={onClick}
size={size}
title={avatar.title}
/>
<Loading loading={loading} placement={placement} />
</div>
);
const Avatar = memo<AvatarProps>(
({ loading, avatar = {}, placement, addon, onClick, size = 40 }) => {
const { styles } = useStyles({ avatarSize: size });
const avatarContent = (
<div className={styles.avatarContainer}>
<AvatarComponent
avatar={avatar.avatar}
background={avatar.backgroundColor}
onClick={onClick}
size={size}
title={avatar.title}
/>
<Loading loading={loading} placement={placement} />
</div>
);

if (!addon) return avatarContent;
return (
<Flexbox align={'center'} className={styles.avatarGroupContainer} gap={8}>
{avatarContent}
{addon}
</Flexbox>
);
});
if (!addon) return avatarContent;
return (
<Flexbox align={'center'} className={styles.avatarGroupContainer} gap={8}>
{avatarContent}
{addon}
</Flexbox>
);
},
);

export default Avatar;
4 changes: 3 additions & 1 deletion src/ChatItem/components/MessageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ export interface MessageContentProps {
renderMessage?: ChatItemProps['renderMessage'];
text?: ChatItemProps['text'];
type?: ChatItemProps['type'];
className?: string;
}

const MessageContent = memo<MessageContentProps>(
({
editing,
onChange,
onEditingChange,
className,
text,
message,
placement,
Expand Down Expand Up @@ -55,7 +57,7 @@ const MessageContent = memo<MessageContentProps>(

return (
<Flexbox
className={cx(styles.message, editing && styles.editingContainer)}
className={cx(styles.message, className, editing && styles.editingContainer)}
onDoubleClick={onDoubleClick}
>
{messageContent}
Expand Down
9 changes: 3 additions & 6 deletions src/ChatItem/components/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ import { Flexbox } from 'react-layout-kit';
import { ChatItemProps } from '@/ChatItem';
import { formatTime } from '@/ChatItem/utils/formatTime';

import { useStyles } from '../style';

export interface TitleProps {
avatar: ChatItemProps['avatar'];
placement?: ChatItemProps['placement'];
showTitle?: ChatItemProps['showTitle'];
time?: ChatItemProps['time'];
className?: string;
}

const Title = memo<TitleProps>(({ showTitle, placement, time, avatar }) => {
const { styles } = useStyles({ placement, showTitle });

const Title = memo<TitleProps>(({ showTitle, className, placement, time, avatar }) => {
return (
<Flexbox
className={styles.name}
className={className}
direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
gap={4}
>
Expand Down
41 changes: 32 additions & 9 deletions src/ChatItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useResponsive } from 'antd-style';
import { memo, useMemo } from 'react';
import { memo, useContext, useMemo } from 'react';
import { Flexbox } from 'react-layout-kit';

import { ConfigProvider } from 'antd';
import Actions from './components/Actions';
import Avatar from './components/Avatar';
import BorderSpacing from './components/BorderSpacing';
Expand Down Expand Up @@ -37,7 +38,7 @@ const ChatItem = memo<ChatItemProps>((props) => {
errorMessage,
chatItemRenderConfig,
onDoubleClick,
originData = {},
originData,
...restProps
} = props;
const { mobile } = useResponsive();
Expand All @@ -50,21 +51,23 @@ const ChatItem = memo<ChatItemProps>((props) => {
type,
});

const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixClass = getPrefixCls('pro-chat');

const avatarDom = useMemo(() => {
if (chatItemRenderConfig?.avatarRender === false) return null;

const dom = (
<Avatar
addon={avatarAddon}
avatar={originData.avatar}
avatar={avatar}
loading={loading}
onClick={onAvatarClick}
placement={placement}
size={mobile ? MOBILE_AVATAR_SIZE : undefined}
/>
);
return chatItemRenderConfig?.avatarRender?.(props, dom) || dom;
}, [originData.avatar, placement, mobile, loading]);
}, [avatar, placement, mobile, loading]);

const messageContentDom = useMemo(() => {
if (chatItemRenderConfig?.contentRender === false) return null;
Expand All @@ -74,6 +77,7 @@ const ChatItem = memo<ChatItemProps>((props) => {
<MessageContent
editing={editing}
message={message}
className={`${prefixClass}-list-item-message-content`}
messageExtra={messageExtra}
onChange={onChange}
onDoubleClick={onDoubleClick}
Expand All @@ -97,33 +101,52 @@ const ChatItem = memo<ChatItemProps>((props) => {
type,
editing,
errorMessage,
originData,
]);

const actionsDom = useMemo(() => {
if (chatItemRenderConfig?.actionsRender === false) return null;
const dom = <Actions actions={actions} editing={editing} placement={placement} type={type} />;
const dom = (
<Actions
actions={actions}
className={`${cx(styles.actions, `${prefixClass}-list-item-actions`)}`}
/>
);
return chatItemRenderConfig?.actionsRender?.(props, dom) || dom;
}, [actions]);

const titleDom = useMemo(() => {
if (chatItemRenderConfig?.titleRender === false) return null;
const dom = <Title avatar={avatar} placement={placement} showTitle={showTitle} time={time} />;
const dom = (
<Title
className={`${cx(styles.name, `${prefixClass}-list-item-title`)}`}
avatar={avatar}
placement={placement}
showTitle={showTitle}
time={time}
/>
);
return chatItemRenderConfig?.titleRender?.(props, dom) || dom;
}, [time, avatar]);

if (chatItemRenderConfig?.render === false) return null;

const itemDom = (
<Flexbox
className={cx(styles.container, className)}
className={cx(
styles.container,
`${prefixClass}-list-item`,
`${prefixClass}-list-item-${placement}`,
className,
)}
direction={placement === 'left' ? 'horizontal' : 'horizontal-reverse'}
gap={mobile ? 6 : 12}
{...restProps}
>
{avatarDom}
<Flexbox
align={placement === 'left' ? 'flex-start' : 'flex-end'}
className={styles.messageContainer}
className={cx(styles.messageContainer, `${prefixClass}-list-item-message-container`)}
>
{titleDom}
<Flexbox
Expand Down
8 changes: 5 additions & 3 deletions src/ChatList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Fragment, memo } from 'react';
import { Fragment, memo, useContext } from 'react';

import type { ChatMessage, DivProps } from '@/types';

import { ConfigProvider } from 'antd';
import ChatItem, { ChatListItemProps, ListItemProps } from './ChatListItem';
import HistoryDivider from './HistoryDivider';
import ShouldUpdateItem from './ShouldUpdateItem';
Expand Down Expand Up @@ -49,9 +50,10 @@ const ChatList = memo<ChatListProps>(
...props
}) => {
const { cx, styles } = useStyles();

const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
const prefixClass = getPrefixCls('pro-chat');
return (
<div className={cx(styles.container, className)} {...props}>
<div className={cx(styles.container, `${prefixClass}-list`, className)} {...props}>
{data.map((item, index) => {
const itemProps = {
loading: loadingId === item.id,
Expand Down
14 changes: 9 additions & 5 deletions src/ProChat/container/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import BackBottom from '@/BackBottom';
import { createStyles } from 'antd-style';
import RcResizeObserver from 'rc-resize-observer';
import { CSSProperties, ReactNode, memo, useEffect, useRef, useState } from 'react';
import { CSSProperties, ReactNode, memo, useContext, useEffect, useRef, useState } from 'react';
import { Flexbox } from 'react-layout-kit';

import { ConfigProvider } from 'antd';
import ChatList from '../components/ChatList';
import InputArea from '../components/InputArea';
import ChatScrollAnchor from '../components/ScrollAnchor';
Expand Down Expand Up @@ -38,6 +39,7 @@ const App = memo<ConversationProps>(
const { styles: override } = useOverrideStyles();
const [isRender, setIsRender] = useState(false);
const [height, setHeight] = useState('100%' as string | number);
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
useEffect(() => {
// 保证 ref 永远存在
setIsRender(true);
Expand All @@ -51,6 +53,8 @@ const App = memo<ConversationProps>(
};
}
}, []);

const prefixClass = getPrefixCls('pro-chat');
return (
<RcResizeObserver
onResize={(e) => {
Expand All @@ -60,17 +64,17 @@ const App = memo<ConversationProps>(
}}
>
<Flexbox
className={cx(override.container, className)}
className={cx(override.container, className, `${prefixClass}-container`)}
style={{
maxHeight: '100vh',
height: '100%',
...style,
}}
>
<div style={{ position: 'relative' }}>
<>
<div
className={styles}
ref={ref}
className={cx(`${prefixClass}-chat-list-container`, styles)}
style={{
height: (height as number) - (areaHtml.current?.clientHeight || 120) || '100%',
}}
Expand All @@ -83,7 +87,7 @@ const App = memo<ConversationProps>(
<ChatScrollAnchor />
</div>
{isRender ? <BackBottom target={ref} text={'返回底部'} /> : null}
</div>
</>
<div ref={areaHtml}>{chatInput ?? <InputArea />}</div>
</Flexbox>
</RcResizeObserver>
Expand Down

0 comments on commit 83d8bb3

Please sign in to comment.