@unif/react-native-chat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +45 -0
- package/src/bubble/Bubble.tsx +160 -0
- package/src/bubble/BubbleList.tsx +84 -0
- package/src/bubble/index.md +111 -0
- package/src/card-wrapper/CardWrapper.tsx +76 -0
- package/src/card-wrapper/index.md +78 -0
- package/src/conversations/Conversations.tsx +236 -0
- package/src/conversations/index.md +90 -0
- package/src/index.tsx +41 -0
- package/src/prompts/Prompts.tsx +123 -0
- package/src/prompts/index.md +81 -0
- package/src/sender/Sender.tsx +435 -0
- package/src/sender/index.md +131 -0
- package/src/theme/tokens.ts +61 -0
- package/src/welcome/Welcome.tsx +208 -0
- package/src/welcome/index.md +95 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Welcome — 欢迎页
|
|
3
|
+
* 渐变背景 + 装饰性光晕 + 2x2 快捷入口卡片网格
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import {
|
|
8
|
+
View,
|
|
9
|
+
Text,
|
|
10
|
+
TouchableOpacity,
|
|
11
|
+
StyleSheet,
|
|
12
|
+
type ViewStyle,
|
|
13
|
+
type TextStyle,
|
|
14
|
+
} from 'react-native';
|
|
15
|
+
import {chatTokens} from '../theme/tokens';
|
|
16
|
+
|
|
17
|
+
export interface WelcomeQuickStart {
|
|
18
|
+
key: string;
|
|
19
|
+
icon: string;
|
|
20
|
+
title: string;
|
|
21
|
+
description: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface WelcomeSemanticStyles {
|
|
25
|
+
root?: ViewStyle;
|
|
26
|
+
title?: TextStyle;
|
|
27
|
+
subtitle?: TextStyle;
|
|
28
|
+
card?: ViewStyle;
|
|
29
|
+
cardTitle?: TextStyle;
|
|
30
|
+
cardDescription?: TextStyle;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface WelcomeProps {
|
|
34
|
+
title?: string;
|
|
35
|
+
subtitle?: string;
|
|
36
|
+
quickStarts?: WelcomeQuickStart[];
|
|
37
|
+
onQuickStart?: (key: string) => void;
|
|
38
|
+
gradientColors?: string[];
|
|
39
|
+
style?: ViewStyle;
|
|
40
|
+
styles?: Partial<WelcomeSemanticStyles>;
|
|
41
|
+
testID?: string;
|
|
42
|
+
renderIcon?: (name: string, size: number, color: string) => React.ReactNode;
|
|
43
|
+
renderGradient?: (props: {
|
|
44
|
+
colors: string[];
|
|
45
|
+
children: React.ReactNode;
|
|
46
|
+
style: ViewStyle;
|
|
47
|
+
}) => React.ReactNode;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const Welcome: React.FC<WelcomeProps> = ({
|
|
51
|
+
title = '你好,我是小U',
|
|
52
|
+
subtitle = '智能助手,有什么可以帮你?',
|
|
53
|
+
quickStarts = [],
|
|
54
|
+
onQuickStart,
|
|
55
|
+
gradientColors = [
|
|
56
|
+
chatTokens.colorBgWelcomeStart,
|
|
57
|
+
chatTokens.colorBgWelcomeMid,
|
|
58
|
+
chatTokens.colorBgWelcomeEnd,
|
|
59
|
+
],
|
|
60
|
+
style,
|
|
61
|
+
styles: semanticStyles,
|
|
62
|
+
testID = 'welcome',
|
|
63
|
+
renderIcon,
|
|
64
|
+
renderGradient,
|
|
65
|
+
}) => {
|
|
66
|
+
const content = (
|
|
67
|
+
<>
|
|
68
|
+
{/* 右上角装饰光晕 */}
|
|
69
|
+
<View style={defaultStyles.glowTopRight} />
|
|
70
|
+
{/* 左下角装饰光晕 */}
|
|
71
|
+
<View style={defaultStyles.glowBottomLeft} />
|
|
72
|
+
|
|
73
|
+
<View style={defaultStyles.content}>
|
|
74
|
+
{renderIcon?.('sparkles', 48, chatTokens.colorPrimary)}
|
|
75
|
+
|
|
76
|
+
<Text style={[defaultStyles.title, semanticStyles?.title]}>
|
|
77
|
+
{title}
|
|
78
|
+
</Text>
|
|
79
|
+
<Text style={[defaultStyles.subtitle, semanticStyles?.subtitle]}>
|
|
80
|
+
{subtitle}
|
|
81
|
+
</Text>
|
|
82
|
+
|
|
83
|
+
{quickStarts.length > 0 && (
|
|
84
|
+
<View style={defaultStyles.grid}>
|
|
85
|
+
{quickStarts.map((item, index) => (
|
|
86
|
+
<TouchableOpacity
|
|
87
|
+
key={item.key}
|
|
88
|
+
style={[defaultStyles.card, semanticStyles?.card]}
|
|
89
|
+
onPress={() => onQuickStart?.(item.key)}
|
|
90
|
+
activeOpacity={0.7}
|
|
91
|
+
testID={`${testID}-quick-${index}`}>
|
|
92
|
+
{renderIcon?.(item.icon, 24, chatTokens.colorPrimary)}
|
|
93
|
+
<Text
|
|
94
|
+
style={[
|
|
95
|
+
defaultStyles.cardTitle,
|
|
96
|
+
semanticStyles?.cardTitle,
|
|
97
|
+
]}>
|
|
98
|
+
{item.title}
|
|
99
|
+
</Text>
|
|
100
|
+
<Text
|
|
101
|
+
style={[
|
|
102
|
+
defaultStyles.cardDescription,
|
|
103
|
+
semanticStyles?.cardDescription,
|
|
104
|
+
]}>
|
|
105
|
+
{item.description}
|
|
106
|
+
</Text>
|
|
107
|
+
</TouchableOpacity>
|
|
108
|
+
))}
|
|
109
|
+
</View>
|
|
110
|
+
)}
|
|
111
|
+
</View>
|
|
112
|
+
</>
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// 如果提供了 renderGradient,使用自定义渐变
|
|
116
|
+
if (renderGradient) {
|
|
117
|
+
return renderGradient({
|
|
118
|
+
colors: gradientColors,
|
|
119
|
+
children: content,
|
|
120
|
+
style: { ...defaultStyles.container, ...semanticStyles?.root, ...style } as ViewStyle,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 无渐变 fallback(纯色背景)
|
|
125
|
+
return (
|
|
126
|
+
<View
|
|
127
|
+
style={[
|
|
128
|
+
defaultStyles.container,
|
|
129
|
+
{backgroundColor: gradientColors[0]},
|
|
130
|
+
semanticStyles?.root,
|
|
131
|
+
style,
|
|
132
|
+
]}
|
|
133
|
+
testID={testID}>
|
|
134
|
+
{content}
|
|
135
|
+
</View>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const defaultStyles = StyleSheet.create({
|
|
140
|
+
container: {
|
|
141
|
+
flex: 1,
|
|
142
|
+
},
|
|
143
|
+
content: {
|
|
144
|
+
flex: 1,
|
|
145
|
+
justifyContent: 'flex-start',
|
|
146
|
+
alignItems: 'center',
|
|
147
|
+
paddingHorizontal: 20,
|
|
148
|
+
paddingTop: 56,
|
|
149
|
+
},
|
|
150
|
+
glowTopRight: {
|
|
151
|
+
position: 'absolute',
|
|
152
|
+
top: -40,
|
|
153
|
+
right: -40,
|
|
154
|
+
width: 200,
|
|
155
|
+
height: 200,
|
|
156
|
+
borderRadius: 100,
|
|
157
|
+
backgroundColor: 'rgba(235,110,0,0.06)',
|
|
158
|
+
},
|
|
159
|
+
glowBottomLeft: {
|
|
160
|
+
position: 'absolute',
|
|
161
|
+
bottom: 40,
|
|
162
|
+
left: -40,
|
|
163
|
+
width: 160,
|
|
164
|
+
height: 160,
|
|
165
|
+
borderRadius: 80,
|
|
166
|
+
backgroundColor: 'rgba(0,122,255,0.04)',
|
|
167
|
+
},
|
|
168
|
+
title: {
|
|
169
|
+
marginTop: 16,
|
|
170
|
+
fontSize: 20,
|
|
171
|
+
fontWeight: '600',
|
|
172
|
+
color: chatTokens.colorText,
|
|
173
|
+
},
|
|
174
|
+
subtitle: {
|
|
175
|
+
marginTop: 6,
|
|
176
|
+
textAlign: 'center',
|
|
177
|
+
fontSize: 15,
|
|
178
|
+
color: chatTokens.colorTextSecondary,
|
|
179
|
+
},
|
|
180
|
+
grid: {
|
|
181
|
+
marginTop: 32,
|
|
182
|
+
width: '100%',
|
|
183
|
+
flexDirection: 'row',
|
|
184
|
+
flexWrap: 'wrap',
|
|
185
|
+
justifyContent: 'space-between',
|
|
186
|
+
gap: 12,
|
|
187
|
+
},
|
|
188
|
+
card: {
|
|
189
|
+
width: '47%',
|
|
190
|
+
backgroundColor: chatTokens.colorBgElevated,
|
|
191
|
+
borderRadius: 16,
|
|
192
|
+
padding: 16,
|
|
193
|
+
...chatTokens.shadowSm,
|
|
194
|
+
},
|
|
195
|
+
cardTitle: {
|
|
196
|
+
marginTop: 8,
|
|
197
|
+
fontSize: 14,
|
|
198
|
+
fontWeight: '500',
|
|
199
|
+
color: chatTokens.colorText,
|
|
200
|
+
},
|
|
201
|
+
cardDescription: {
|
|
202
|
+
marginTop: 2,
|
|
203
|
+
fontSize: 11,
|
|
204
|
+
color: chatTokens.colorTextSecondary,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
export default React.memo(Welcome);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Welcome 欢迎页
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Welcome 欢迎页
|
|
9
|
+
|
|
10
|
+
聊天欢迎页组件,渐变背景 + 装饰性光晕 + 快捷入口卡片网格。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- 聊天界面无消息时的空状态
|
|
15
|
+
- 引导用户通过快捷入口开始对话
|
|
16
|
+
|
|
17
|
+
## 代码示例
|
|
18
|
+
|
|
19
|
+
### 基本用法
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Welcome } from '@unif/react-native-chat';
|
|
23
|
+
|
|
24
|
+
<Welcome
|
|
25
|
+
title="你好,我是小U"
|
|
26
|
+
subtitle="智能助手,有什么可以帮你?"
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 带快捷入口
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<Welcome
|
|
34
|
+
quickStarts={[
|
|
35
|
+
{ key: 'balance', icon: 'wallet', title: '余额查询', description: '查看账户余额' },
|
|
36
|
+
{ key: 'transfer', icon: 'send', title: '转账汇款', description: '快速转账' },
|
|
37
|
+
{ key: 'invest', icon: 'trending-up', title: '理财推荐', description: '个性化推荐' },
|
|
38
|
+
{ key: 'service', icon: 'chatbubbles', title: '客户服务', description: '在线客服' },
|
|
39
|
+
]}
|
|
40
|
+
onQuickStart={(key) => console.log('选择:', key)}
|
|
41
|
+
renderIcon={(name, size, color) => <Icon name={name} size={size} color={color} />}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 自定义渐变
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import LinearGradient from 'react-native-linear-gradient';
|
|
49
|
+
|
|
50
|
+
<Welcome
|
|
51
|
+
gradientColors={['#E8F4FD', '#F0E6FF', '#F5F5F5']}
|
|
52
|
+
renderGradient={({ colors, children, style }) => (
|
|
53
|
+
<LinearGradient colors={colors} style={style}>
|
|
54
|
+
{children}
|
|
55
|
+
</LinearGradient>
|
|
56
|
+
)}
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API
|
|
61
|
+
|
|
62
|
+
### WelcomeProps
|
|
63
|
+
|
|
64
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
65
|
+
|------|------|------|--------|
|
|
66
|
+
| title | 主标题 | `string` | `'你好,我是小U'` |
|
|
67
|
+
| subtitle | 副标题 | `string` | `'智能助手,有什么可以帮你?'` |
|
|
68
|
+
| quickStarts | 快捷入口配置 | `WelcomeQuickStart[]` | `[]` |
|
|
69
|
+
| onQuickStart | 快捷入口点击回调 | `(key: string) => void` | - |
|
|
70
|
+
| gradientColors | 背景渐变色 | `string[]` | 内置渐变 |
|
|
71
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
72
|
+
| styles | 语义样式 | `Partial<WelcomeSemanticStyles>` | - |
|
|
73
|
+
| testID | 测试标识 | `string` | `'welcome'` |
|
|
74
|
+
| renderIcon | 图标渲染函数 | `(name, size, color) => ReactNode` | - |
|
|
75
|
+
| renderGradient | 渐变背景渲染函数 | `(props) => ReactNode` | - |
|
|
76
|
+
|
|
77
|
+
### WelcomeQuickStart
|
|
78
|
+
|
|
79
|
+
| 属性 | 说明 | 类型 |
|
|
80
|
+
|------|------|------|
|
|
81
|
+
| key | 唯一标识 | `string` |
|
|
82
|
+
| icon | 图标名称 | `string` |
|
|
83
|
+
| title | 标题 | `string` |
|
|
84
|
+
| description | 描述 | `string` |
|
|
85
|
+
|
|
86
|
+
### WelcomeSemanticStyles
|
|
87
|
+
|
|
88
|
+
| 属性 | 说明 | 类型 |
|
|
89
|
+
|------|------|------|
|
|
90
|
+
| root | 外层容器 | `ViewStyle` |
|
|
91
|
+
| title | 标题文字 | `TextStyle` |
|
|
92
|
+
| subtitle | 副标题文字 | `TextStyle` |
|
|
93
|
+
| card | 快捷入口卡片 | `ViewStyle` |
|
|
94
|
+
| cardTitle | 卡片标题 | `TextStyle` |
|
|
95
|
+
| cardDescription | 卡片描述 | `TextStyle` |
|