Skip to content

Commit dc003e6

Browse files
author
zhaoge
committed
feat: add think component, update test and details
1 parent 074b483 commit dc003e6

File tree

12 files changed

+271
-5
lines changed

12 files changed

+271
-5
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Think component snapshot renders completed state with children correctly 1`] = `
4+
<div>
5+
<div
6+
class="dtc__custom__think"
7+
>
8+
<section
9+
class="dtc-flex dtc__custom__think__btn"
10+
style="flex-wrap: nowrap; justify-content: normal; align-items: center; gap: 4px;"
11+
>
12+
已完成深度思考
13+
<span
14+
color="#64698B"
15+
data-mock-icon="UpOutlined"
16+
size="12"
17+
style="transform: none;"
18+
/>
19+
</section>
20+
<div
21+
class="dtc__custom__think__content"
22+
>
23+
<div
24+
class="dtc__custom__think__line"
25+
/>
26+
<div
27+
class="dtc__custom__think__text"
28+
>
29+
这里是 Think 的内容示例(支持 Markdown)
30+
31+
- 列表项 A
32+
- 列表项 B
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
`;
38+
39+
exports[`Think component snapshot renders loading state correctly 1`] = `
40+
<div>
41+
<div
42+
class="dtc__custom__think"
43+
>
44+
<section
45+
class="dtc-flex dtc__custom__think__btn"
46+
style="flex-wrap: nowrap; justify-content: normal; align-items: center; gap: 4px;"
47+
>
48+
<span
49+
class="gradient-text"
50+
>
51+
思考中...
52+
</span>
53+
<span
54+
color="#64698B"
55+
data-mock-icon="UpOutlined"
56+
size="12"
57+
style="transform: none;"
58+
/>
59+
</section>
60+
<div
61+
class="dtc__custom__think__content"
62+
>
63+
<div
64+
class="dtc__custom__think__line"
65+
/>
66+
<div
67+
class="dtc__custom__think__text"
68+
>
69+
正在思考中,暂无内容。
70+
</div>
71+
</div>
72+
</div>
73+
</div>
74+
`;

src/chat/__tests__/think.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import { render } from '@testing-library/react';
3+
4+
import Think from '../think';
5+
6+
describe('Think component snapshot', () => {
7+
it('renders loading state correctly', () => {
8+
const data = { children: '正在思考中,暂无内容。' } as any;
9+
const { container } = render(<Think data={data} loading />);
10+
expect(container).toMatchSnapshot();
11+
});
12+
13+
it('renders completed state with children correctly', () => {
14+
const markdown = `这里是 Think 的内容示例(支持 Markdown)\n\n- 列表项 A\n- 列表项 B`;
15+
const data = { children: markdown } as any;
16+
const { container } = render(<Think data={data} loading={false} />);
17+
expect(container).toMatchSnapshot();
18+
});
19+
});

src/chat/demos/markdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ SELECT * FROM table_name;
3434
| 单元格 | 单元格 | 单元格 |
3535
| 单元格 | 单元格 | 单元格 |
3636
| 单元格 | 单元格 | 单元格 |
37-
<span style="color: red;">自定义颜色</span>
37+
<span style="color: red;">带自定义样式的dom结构显示</span>
3838
`;
3939

4040
export default function () {

src/chat/demos/think.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import type { ReactMarkdownProps } from 'react-markdown/lib/complex-types';
3+
import { Chat } from 'dt-react-component';
4+
5+
const children = `
6+
这里是 Think 的内容示例
7+
8+
- 列表项 A
9+
- 列表项 B
10+
`;
11+
12+
export default function () {
13+
const [loading, setLoading] = React.useState(true);
14+
15+
React.useEffect(() => {
16+
const timer = setTimeout(() => {
17+
setLoading(false);
18+
}, 3000);
19+
20+
return () => clearTimeout(timer);
21+
}, []);
22+
const data = { children } as ReactMarkdownProps;
23+
return <Chat.Think data={data} loading={loading} />;
24+
}

src/chat/gradientText/index.scss

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
$loadingGradient: #90F8FF99 6%, #4983DA 28%, #002DA1 46%, #4983DA 72%, #90F8FF99 94%;
2+
3+
span.gradient-text {
4+
background: linear-gradient(102deg, $loadingGradient);
5+
background-size: 200% 100%;
6+
background-clip: text;
7+
color: transparent;
8+
animation: gradientScroll 2s linear infinite;
9+
}
10+
11+
@keyframes gradientScroll {
12+
0% {
13+
background-position: 200% 50%;
14+
}
15+
100% {
16+
background-position: 0% 50%;
17+
}
18+
}

src/chat/gradientText/index.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import classNames from 'classnames';
3+
4+
import './index.scss';
5+
6+
interface IGradientTextProps {
7+
className?: string;
8+
gradient?: boolean;
9+
}
10+
/**
11+
* @deprecated 从 rc 中同步过来,切勿直接修改该组件
12+
*/
13+
export default function GradientText({
14+
className,
15+
gradient,
16+
children,
17+
}: React.PropsWithChildren<IGradientTextProps>) {
18+
return <span className={classNames(gradient && 'gradient-text', className)}>{children}</span>;
19+
}

src/chat/index.$tab-think.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
title: Think
3+
group: 组件
4+
toc: content
5+
demo:
6+
cols: 2
7+
---
8+
9+
# Think
10+
11+
## 何时使用
12+
13+
Think 组件用以展示 AI 交互中深度思考样式。
14+
15+
## 示例
16+
17+
<code src="./demos/think.tsx" title="基本使用"></code>
18+
19+
## API
20+
21+
| 参数 | 说明 | 类型 | 默认值 |
22+
| ------- | ---- | ------------------ | ------ |
23+
| data | 类型 | ReactMarkdownProps | - |
24+
| loading | 类型 | boolean | - |

src/chat/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Chat 规范由多个组件复合使用实现落地场景,其中:
2121
- `Message` 组件是符合 AI 规范的回答框
2222
- `Prompt` 组件是符合 AI 规范的提问框
2323
- `Content` 组件是符合 AI 规范的正文内容
24+
- `Think` 组件是符合 AI 规范的深度思考样式
2425

2526
## 何时使用
2627

src/chat/index.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Message from './message';
1010
import Pagination from './pagination';
1111
import Prompt from './prompt';
1212
import Tag from './tag';
13+
import Think from './think';
1314
import useChat from './useChat';
1415
import { context, type IChatContext, useContext } from './useContext';
1516
import Welcome from './welcome';
@@ -21,7 +22,24 @@ const DEFAULT_MAX_REGENERATE_COUNT = 5;
2122
type ChatProviderConfig = Omit<IChatProps, 'maxRegenerateCount'> &
2223
Partial<Pick<IChatProps, 'maxRegenerateCount'>>;
2324

24-
function Chat({
25+
type ChatComponent = React.FC<PropsWithChildren<ChatProviderConfig>> & {
26+
useChat: typeof useChat;
27+
useContext: typeof useContext;
28+
Loading: typeof Loading;
29+
Button: typeof Button;
30+
CodeBlock: typeof CodeBlock;
31+
Input: typeof Input;
32+
Markdown: typeof Markdown;
33+
Pagination: typeof Pagination;
34+
Message: typeof Message;
35+
Prompt: typeof Prompt;
36+
Content: typeof Content;
37+
Tag: typeof Tag;
38+
Welcome: typeof Welcome;
39+
Think: typeof Think;
40+
};
41+
42+
const Chat: ChatComponent = function Chat({
2543
chat,
2644
components,
2745
maxRegenerateCount = DEFAULT_MAX_REGENERATE_COUNT,
@@ -50,11 +68,10 @@ function Chat({
5068
{children}
5169
</context.Provider>
5270
);
53-
}
71+
};
5472

5573
Chat.useChat = useChat;
5674
Chat.useContext = useContext;
57-
5875
Chat.Loading = Loading;
5976
Chat.Button = Button;
6077
Chat.CodeBlock = CodeBlock;
@@ -66,6 +83,7 @@ Chat.Prompt = Prompt;
6683
Chat.Content = Content;
6784
Chat.Tag = Tag;
6885
Chat.Welcome = Welcome;
86+
Chat.Think = Think;
6987

7088
export { type IContentRef } from './content';
7189
export default Chat;

src/chat/markdown/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default memo(
8181
includeElementIndex
8282
{...rest}
8383
>
84-
{children}
84+
{children?.replace(/<\/think>/g, '\n\n</think>')}
8585
</ReactMarkdown>
8686
);
8787
},

0 commit comments

Comments
 (0)