@unif/react-native-chat 0.1.0 → 0.1.2
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/README.md +156 -0
- package/lib/commonjs/bubble/Bubble.js +131 -0
- package/lib/commonjs/bubble/Bubble.js.map +1 -0
- package/lib/commonjs/bubble/BubbleList.js +73 -0
- package/lib/commonjs/bubble/BubbleList.js.map +1 -0
- package/lib/commonjs/bubble/index.md +111 -0
- package/lib/commonjs/card-wrapper/CardWrapper.js +65 -0
- package/lib/commonjs/card-wrapper/CardWrapper.js.map +1 -0
- package/lib/commonjs/card-wrapper/index.md +78 -0
- package/lib/commonjs/conversations/Conversations.js +184 -0
- package/lib/commonjs/conversations/Conversations.js.map +1 -0
- package/lib/commonjs/conversations/index.md +90 -0
- package/lib/commonjs/index.js +63 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/prompts/Prompts.js +87 -0
- package/lib/commonjs/prompts/Prompts.js.map +1 -0
- package/lib/commonjs/prompts/index.md +81 -0
- package/lib/commonjs/sender/Sender.js +354 -0
- package/lib/commonjs/sender/Sender.js.map +1 -0
- package/lib/commonjs/sender/index.md +131 -0
- package/lib/commonjs/theme/tokens.js +67 -0
- package/lib/commonjs/theme/tokens.js.map +1 -0
- package/lib/commonjs/welcome/Welcome.js +152 -0
- package/lib/commonjs/welcome/Welcome.js.map +1 -0
- package/lib/commonjs/welcome/index.md +95 -0
- package/lib/module/bubble/Bubble.js +126 -0
- package/lib/module/bubble/Bubble.js.map +1 -0
- package/lib/module/bubble/BubbleList.js +68 -0
- package/lib/module/bubble/BubbleList.js.map +1 -0
- package/lib/module/bubble/index.md +111 -0
- package/lib/module/card-wrapper/CardWrapper.js +60 -0
- package/lib/module/card-wrapper/CardWrapper.js.map +1 -0
- package/lib/module/card-wrapper/index.md +78 -0
- package/lib/module/conversations/Conversations.js +179 -0
- package/lib/module/conversations/Conversations.js.map +1 -0
- package/lib/module/conversations/index.md +90 -0
- package/lib/module/index.js +23 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/prompts/Prompts.js +82 -0
- package/lib/module/prompts/Prompts.js.map +1 -0
- package/lib/module/prompts/index.md +81 -0
- package/lib/module/sender/Sender.js +349 -0
- package/lib/module/sender/Sender.js.map +1 -0
- package/lib/module/sender/index.md +131 -0
- package/lib/module/theme/tokens.js +63 -0
- package/lib/module/theme/tokens.js.map +1 -0
- package/lib/module/welcome/Welcome.js +147 -0
- package/lib/module/welcome/Welcome.js.map +1 -0
- package/lib/module/welcome/index.md +95 -0
- package/lib/typescript/commonjs/bubble/Bubble.d.ts +29 -0
- package/lib/typescript/commonjs/bubble/Bubble.d.ts.map +1 -0
- package/lib/typescript/commonjs/bubble/BubbleList.d.ts +20 -0
- package/lib/typescript/commonjs/bubble/BubbleList.d.ts.map +1 -0
- package/lib/typescript/commonjs/card-wrapper/CardWrapper.d.ts +22 -0
- package/lib/typescript/commonjs/card-wrapper/CardWrapper.d.ts.map +1 -0
- package/lib/typescript/commonjs/conversations/Conversations.d.ts +37 -0
- package/lib/typescript/commonjs/conversations/Conversations.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +20 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/prompts/Prompts.d.ts +27 -0
- package/lib/typescript/commonjs/prompts/Prompts.d.ts.map +1 -0
- package/lib/typescript/commonjs/sender/Sender.d.ts +58 -0
- package/lib/typescript/commonjs/sender/Sender.d.ts.map +1 -0
- package/lib/typescript/commonjs/theme/tokens.d.ts +52 -0
- package/lib/typescript/commonjs/theme/tokens.d.ts.map +1 -0
- package/lib/typescript/commonjs/welcome/Welcome.d.ts +39 -0
- package/lib/typescript/commonjs/welcome/Welcome.d.ts.map +1 -0
- package/lib/typescript/module/bubble/Bubble.d.ts +29 -0
- package/lib/typescript/module/bubble/Bubble.d.ts.map +1 -0
- package/lib/typescript/module/bubble/BubbleList.d.ts +20 -0
- package/lib/typescript/module/bubble/BubbleList.d.ts.map +1 -0
- package/lib/typescript/module/card-wrapper/CardWrapper.d.ts +22 -0
- package/lib/typescript/module/card-wrapper/CardWrapper.d.ts.map +1 -0
- package/lib/typescript/module/conversations/Conversations.d.ts +37 -0
- package/lib/typescript/module/conversations/Conversations.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +20 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/prompts/Prompts.d.ts +27 -0
- package/lib/typescript/module/prompts/Prompts.d.ts.map +1 -0
- package/lib/typescript/module/sender/Sender.d.ts +58 -0
- package/lib/typescript/module/sender/Sender.d.ts.map +1 -0
- package/lib/typescript/module/theme/tokens.d.ts +52 -0
- package/lib/typescript/module/theme/tokens.d.ts.map +1 -0
- package/lib/typescript/module/welcome/Welcome.d.ts +39 -0
- package/lib/typescript/module/welcome/Welcome.d.ts.map +1 -0
- package/package.json +39 -8
- package/src/sender/Sender.tsx +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @unif/react-native-chat
|
|
2
|
+
|
|
3
|
+
AI 聊天 UI 组件库,基于 `@unif/react-native-ui` 构建,参考 [Ant Design X](https://ant-design-x.antgroup.com/) 架构设计。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @unif/react-native-chat
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### peerDependencies
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add react react-native
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 组件
|
|
18
|
+
|
|
19
|
+
### Bubble
|
|
20
|
+
|
|
21
|
+
消息气泡容器,根据 `role` 自动镜像布局。
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import {Bubble} from '@unif/react-native-chat';
|
|
25
|
+
|
|
26
|
+
<Bubble role="user">你好</Bubble>
|
|
27
|
+
|
|
28
|
+
<Bubble role="assistant" avatar={<Avatar />} name="小U">
|
|
29
|
+
<MarkdownBubble text={message.text} />
|
|
30
|
+
</Bubble>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
| 属性 | 类型 | 说明 |
|
|
34
|
+
|------|------|------|
|
|
35
|
+
| role | `'user' \| 'assistant' \| 'system'` | 消息角色 |
|
|
36
|
+
| avatar | `ReactNode` | 头像 |
|
|
37
|
+
| name | `string` | 发送者名称 |
|
|
38
|
+
| children | `ReactNode` | 消息内容 |
|
|
39
|
+
| footer | `ReactNode` | 底部区域 |
|
|
40
|
+
| styles | `BubbleSemanticStyles` | 语义化样式 |
|
|
41
|
+
|
|
42
|
+
### BubbleList
|
|
43
|
+
|
|
44
|
+
消息列表,封装 inverted FlatList,空状态自动渲染 header。
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import {BubbleList} from '@unif/react-native-chat';
|
|
48
|
+
|
|
49
|
+
<BubbleList
|
|
50
|
+
items={messages}
|
|
51
|
+
renderBubble={(item) => <Bubble role={item.role}>{item.text}</Bubble>}
|
|
52
|
+
header={<Welcome />}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| 属性 | 类型 | 说明 |
|
|
57
|
+
|------|------|------|
|
|
58
|
+
| items | `T[]` | 消息数组 |
|
|
59
|
+
| renderBubble | `(item: T) => ReactNode` | 渲染函数 |
|
|
60
|
+
| keyExtractor | `(item: T) => string` | key 提取 |
|
|
61
|
+
| header | `ReactNode` | 空状态占位(如 Welcome) |
|
|
62
|
+
| onEndReached | `() => void` | 加载更多 |
|
|
63
|
+
|
|
64
|
+
### Sender
|
|
65
|
+
|
|
66
|
+
输入发送器,包含文本/语音/录音三态状态机。
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import {Sender} from '@unif/react-native-chat';
|
|
70
|
+
|
|
71
|
+
<Sender
|
|
72
|
+
onSend={(text) => handleSend(text)}
|
|
73
|
+
onStop={abort}
|
|
74
|
+
isRequesting={requesting}
|
|
75
|
+
/>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
| 属性 | 类型 | 说明 |
|
|
79
|
+
|------|------|------|
|
|
80
|
+
| onSend | `(text: string) => void` | 发送回调 |
|
|
81
|
+
| onStop | `() => void` | 中止请求 |
|
|
82
|
+
| isRequesting | `boolean` | 是否请求中 |
|
|
83
|
+
| placeholder | `string` | 占位文本 |
|
|
84
|
+
| maxLength | `number` | 最大字数(默认 2000) |
|
|
85
|
+
| actions | `ActionSheetOption[]` | + 面板选项 |
|
|
86
|
+
|
|
87
|
+
### Conversations
|
|
88
|
+
|
|
89
|
+
会话列表,SectionList + 日期分组(今天/昨天/更早)。
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
import {Conversations} from '@unif/react-native-chat';
|
|
93
|
+
|
|
94
|
+
<Conversations
|
|
95
|
+
items={sessions}
|
|
96
|
+
activeId={currentId}
|
|
97
|
+
onSelect={(id) => switchSession(id)}
|
|
98
|
+
onDelete={(id) => deleteSession(id)}
|
|
99
|
+
onNew={() => newSession()}
|
|
100
|
+
/>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Prompts
|
|
104
|
+
|
|
105
|
+
建议提示,水平滚动 Chip 列表。
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import {Prompts} from '@unif/react-native-chat';
|
|
109
|
+
|
|
110
|
+
<Prompts
|
|
111
|
+
items={[{id: '1', label: '帮我搜商品'}]}
|
|
112
|
+
onSelect={(item) => sendMessage(item.label)}
|
|
113
|
+
/>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Welcome
|
|
117
|
+
|
|
118
|
+
欢迎页,渐变背景 + 快捷入口卡片网格。
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import {Welcome} from '@unif/react-native-chat';
|
|
122
|
+
|
|
123
|
+
<Welcome
|
|
124
|
+
subtitle="智能助手,有什么可以帮你?"
|
|
125
|
+
quickStarts={QUICK_STARTERS}
|
|
126
|
+
onQuickStart={(key) => handleQuickStart(key)}
|
|
127
|
+
renderIcon={renderIcon}
|
|
128
|
+
renderGradient={renderGradient}
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### CardWrapper
|
|
133
|
+
|
|
134
|
+
卡片路由容器,通过 registry 注入业务卡片。
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
import {CardWrapper} from '@unif/react-native-chat';
|
|
138
|
+
|
|
139
|
+
<CardWrapper
|
|
140
|
+
cardType="product-list"
|
|
141
|
+
data={cardData}
|
|
142
|
+
actions={['add_to_order']}
|
|
143
|
+
registry={CARD_REGISTRY}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 兼容性
|
|
148
|
+
|
|
149
|
+
| @unif/react-native-chat | React Native | React | 状态 |
|
|
150
|
+
|-------------------------|-------------|-------|------|
|
|
151
|
+
| 0.1.x | >= 0.71 | >= 18 | ✅ |
|
|
152
|
+
| 0.1.x | 0.74.x | 18.x | ✅ 已验证(PECPortal) |
|
|
153
|
+
|
|
154
|
+
## 许可证
|
|
155
|
+
|
|
156
|
+
MIT
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _tokens = require("../theme/tokens");
|
|
10
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/**
|
|
13
|
+
* Bubble — 消息气泡容器
|
|
14
|
+
*
|
|
15
|
+
* 根据 role 自动镜像布局:
|
|
16
|
+
* - user → 右对齐浅色气泡 + 不对称圆角
|
|
17
|
+
* - assistant → 左侧 Avatar + 名称 + 内容
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const Bubble = ({
|
|
21
|
+
role,
|
|
22
|
+
avatar,
|
|
23
|
+
name,
|
|
24
|
+
children,
|
|
25
|
+
footer,
|
|
26
|
+
style,
|
|
27
|
+
styles: semanticStyles,
|
|
28
|
+
testID
|
|
29
|
+
}) => {
|
|
30
|
+
if (role === 'user') {
|
|
31
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
32
|
+
style: [defaultStyles.userRow, semanticStyles?.root, style],
|
|
33
|
+
testID: testID ?? 'bubble-user',
|
|
34
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
35
|
+
style: defaultStyles.userBubble,
|
|
36
|
+
children: typeof children === 'string' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
37
|
+
style: defaultStyles.userText,
|
|
38
|
+
children: children
|
|
39
|
+
}) : children
|
|
40
|
+
}), footer && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
41
|
+
style: [defaultStyles.footer, semanticStyles?.footer],
|
|
42
|
+
children: footer
|
|
43
|
+
})]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// assistant / system
|
|
48
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
49
|
+
style: [defaultStyles.assistantRow, semanticStyles?.root, style],
|
|
50
|
+
testID: testID ?? 'bubble-assistant',
|
|
51
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
52
|
+
style: defaultStyles.headerRow,
|
|
53
|
+
children: [avatar && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
54
|
+
style: [defaultStyles.avatarContainer, semanticStyles?.avatar],
|
|
55
|
+
children: avatar
|
|
56
|
+
}), name && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
57
|
+
style: [defaultStyles.assistantName, semanticStyles?.name],
|
|
58
|
+
children: name
|
|
59
|
+
})]
|
|
60
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
61
|
+
style: [defaultStyles.contentArea, semanticStyles?.content],
|
|
62
|
+
children: children
|
|
63
|
+
}), footer && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
64
|
+
style: [defaultStyles.footer, semanticStyles?.footer],
|
|
65
|
+
children: footer
|
|
66
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
67
|
+
style: defaultStyles.separator
|
|
68
|
+
})]
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
const defaultStyles = _reactNative.StyleSheet.create({
|
|
72
|
+
// Assistant
|
|
73
|
+
assistantRow: {
|
|
74
|
+
paddingHorizontal: _tokens.chatTokens.spaceMd,
|
|
75
|
+
paddingVertical: _tokens.chatTokens.spaceSm,
|
|
76
|
+
marginBottom: 12
|
|
77
|
+
},
|
|
78
|
+
headerRow: {
|
|
79
|
+
flexDirection: 'row',
|
|
80
|
+
alignItems: 'center',
|
|
81
|
+
marginBottom: 6
|
|
82
|
+
},
|
|
83
|
+
avatarContainer: {
|
|
84
|
+
marginRight: 8
|
|
85
|
+
},
|
|
86
|
+
assistantName: {
|
|
87
|
+
fontSize: 13,
|
|
88
|
+
fontWeight: '500',
|
|
89
|
+
color: _tokens.chatTokens.colorTextSecondary
|
|
90
|
+
},
|
|
91
|
+
contentArea: {
|
|
92
|
+
paddingLeft: 36
|
|
93
|
+
},
|
|
94
|
+
separator: {
|
|
95
|
+
marginTop: 12,
|
|
96
|
+
marginLeft: 36,
|
|
97
|
+
height: _reactNative.StyleSheet.hairlineWidth,
|
|
98
|
+
backgroundColor: _tokens.chatTokens.colorBorder,
|
|
99
|
+
opacity: 0.5
|
|
100
|
+
},
|
|
101
|
+
footer: {
|
|
102
|
+
paddingLeft: 36,
|
|
103
|
+
marginTop: 4
|
|
104
|
+
},
|
|
105
|
+
// User
|
|
106
|
+
userRow: {
|
|
107
|
+
flexDirection: 'row',
|
|
108
|
+
justifyContent: 'flex-end',
|
|
109
|
+
flexWrap: 'wrap',
|
|
110
|
+
paddingHorizontal: _tokens.chatTokens.spaceMd,
|
|
111
|
+
paddingVertical: _tokens.chatTokens.spaceSm,
|
|
112
|
+
marginBottom: _tokens.chatTokens.spaceSm
|
|
113
|
+
},
|
|
114
|
+
userBubble: {
|
|
115
|
+
backgroundColor: _tokens.chatTokens.colorBgUserMsg,
|
|
116
|
+
borderTopLeftRadius: 20,
|
|
117
|
+
borderTopRightRadius: 20,
|
|
118
|
+
borderBottomLeftRadius: 20,
|
|
119
|
+
borderBottomRightRadius: 6,
|
|
120
|
+
paddingHorizontal: _tokens.chatTokens.spaceMd,
|
|
121
|
+
paddingVertical: _tokens.chatTokens.space,
|
|
122
|
+
maxWidth: '75%'
|
|
123
|
+
},
|
|
124
|
+
userText: {
|
|
125
|
+
fontSize: _tokens.chatTokens.fontSize,
|
|
126
|
+
color: _tokens.chatTokens.colorText,
|
|
127
|
+
lineHeight: _tokens.chatTokens.lineHeight
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(Bubble);
|
|
131
|
+
//# sourceMappingURL=Bubble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_tokens","_jsxRuntime","e","__esModule","default","Bubble","role","avatar","name","children","footer","style","styles","semanticStyles","testID","jsxs","View","defaultStyles","userRow","root","jsx","userBubble","Text","userText","assistantRow","headerRow","avatarContainer","assistantName","contentArea","content","separator","StyleSheet","create","paddingHorizontal","chatTokens","spaceMd","paddingVertical","spaceSm","marginBottom","flexDirection","alignItems","marginRight","fontSize","fontWeight","color","colorTextSecondary","paddingLeft","marginTop","marginLeft","height","hairlineWidth","backgroundColor","colorBorder","opacity","justifyContent","flexWrap","colorBgUserMsg","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius","space","maxWidth","colorText","lineHeight","_default","exports","React","memo"],"sourceRoot":"../../../src","sources":["bubble/Bubble.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
11
|
+
/**
|
|
12
|
+
* Bubble.List — 消息列表
|
|
13
|
+
* 封装 inverted FlatList,自动滚动到底部
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
function BubbleListInner(props) {
|
|
17
|
+
const {
|
|
18
|
+
items,
|
|
19
|
+
renderBubble,
|
|
20
|
+
keyExtractor,
|
|
21
|
+
onEndReached,
|
|
22
|
+
header,
|
|
23
|
+
footer,
|
|
24
|
+
style,
|
|
25
|
+
testID = 'bubble-list'
|
|
26
|
+
} = props;
|
|
27
|
+
const renderItem = (0, _react.useCallback)(({
|
|
28
|
+
item
|
|
29
|
+
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
30
|
+
children: renderBubble(item)
|
|
31
|
+
}), [renderBubble]);
|
|
32
|
+
const defaultKeyExtractor = (0, _react.useCallback)((item, index) => {
|
|
33
|
+
if (keyExtractor) return keyExtractor(item);
|
|
34
|
+
const record = item;
|
|
35
|
+
return record['id'] ?? String(index);
|
|
36
|
+
}, [keyExtractor]);
|
|
37
|
+
if (items.length === 0 && header) {
|
|
38
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
39
|
+
style: [defaultStyles.container, style],
|
|
40
|
+
testID: testID,
|
|
41
|
+
children: header
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
|
|
45
|
+
data: items,
|
|
46
|
+
renderItem: renderItem,
|
|
47
|
+
keyExtractor: defaultKeyExtractor,
|
|
48
|
+
inverted: true,
|
|
49
|
+
style: [defaultStyles.list, style],
|
|
50
|
+
contentContainerStyle: defaultStyles.contentContainer,
|
|
51
|
+
onEndReached: onEndReached,
|
|
52
|
+
onEndReachedThreshold: 0.3,
|
|
53
|
+
ListFooterComponent: footer ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
54
|
+
children: footer
|
|
55
|
+
}) : null,
|
|
56
|
+
showsVerticalScrollIndicator: false,
|
|
57
|
+
testID: testID
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
const defaultStyles = _reactNative.StyleSheet.create({
|
|
61
|
+
container: {
|
|
62
|
+
flex: 1
|
|
63
|
+
},
|
|
64
|
+
list: {
|
|
65
|
+
flex: 1
|
|
66
|
+
},
|
|
67
|
+
contentContainer: {
|
|
68
|
+
paddingVertical: 8
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const BubbleList = /*#__PURE__*/_react.default.memo(BubbleListInner);
|
|
72
|
+
var _default = exports.default = BubbleList;
|
|
73
|
+
//# sourceMappingURL=BubbleList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","BubbleListInner","props","items","renderBubble","keyExtractor","onEndReached","header","footer","style","testID","renderItem","useCallback","item","jsx","Fragment","children","defaultKeyExtractor","index","record","String","length","View","defaultStyles","container","FlatList","data","inverted","list","contentContainerStyle","contentContainer","onEndReachedThreshold","ListFooterComponent","showsVerticalScrollIndicator","StyleSheet","create","flex","paddingVertical","BubbleList","React","memo","_default","exports"],"sourceRoot":"../../../src","sources":["bubble/BubbleList.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Bubble 消息气泡
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Bubble 消息气泡
|
|
9
|
+
|
|
10
|
+
消息气泡容器,根据 `role` 自动镜像布局。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- 展示聊天消息(用户消息、AI 回复、系统消息)
|
|
15
|
+
- 需要根据角色自动区分左右布局
|
|
16
|
+
|
|
17
|
+
## 代码示例
|
|
18
|
+
|
|
19
|
+
### 基本用法
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Bubble } from '@unif/react-native-chat';
|
|
23
|
+
|
|
24
|
+
// 用户消息(右对齐)
|
|
25
|
+
<Bubble role="user">你好,请帮我查询订单</Bubble>
|
|
26
|
+
|
|
27
|
+
// AI 回复(左对齐)
|
|
28
|
+
<Bubble role="assistant" name="小U" avatar={<Avatar name="AI" />}>
|
|
29
|
+
好的,正在为您查询...
|
|
30
|
+
</Bubble>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 自定义底部区域
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
<Bubble role="assistant" footer={<Text>14:30</Text>}>
|
|
37
|
+
这是消息内容
|
|
38
|
+
</Bubble>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 语义样式覆盖
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<Bubble
|
|
45
|
+
role="user"
|
|
46
|
+
styles={{
|
|
47
|
+
root: { paddingHorizontal: 20 },
|
|
48
|
+
content: { backgroundColor: '#E8F0FE' },
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
自定义样式的消息
|
|
52
|
+
</Bubble>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### BubbleProps
|
|
58
|
+
|
|
59
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
60
|
+
|------|------|------|--------|
|
|
61
|
+
| role | 消息角色 | `'user' \| 'assistant' \| 'system'` | - |
|
|
62
|
+
| avatar | 头像(assistant/system 角色显示) | `ReactNode` | - |
|
|
63
|
+
| name | 发送者名称 | `string` | - |
|
|
64
|
+
| children | 消息内容 | `ReactNode` | - |
|
|
65
|
+
| footer | 底部区域(时间戳、操作等) | `ReactNode` | - |
|
|
66
|
+
| style | 外层容器样式 | `ViewStyle` | - |
|
|
67
|
+
| styles | 语义样式覆盖 | `Partial<BubbleSemanticStyles>` | - |
|
|
68
|
+
| testID | 测试标识 | `string` | - |
|
|
69
|
+
|
|
70
|
+
### BubbleSemanticStyles
|
|
71
|
+
|
|
72
|
+
| 属性 | 说明 | 类型 |
|
|
73
|
+
|------|------|------|
|
|
74
|
+
| root | 外层容器 | `ViewStyle` |
|
|
75
|
+
| avatar | 头像容器 | `ViewStyle` |
|
|
76
|
+
| name | 名称文字 | `TextStyle` |
|
|
77
|
+
| content | 内容区域 | `ViewStyle` |
|
|
78
|
+
| footer | 底部区域 | `ViewStyle` |
|
|
79
|
+
|
|
80
|
+
## Bubble.List 消息列表
|
|
81
|
+
|
|
82
|
+
封装 inverted FlatList,消息从底部向上排列,支持泛型。
|
|
83
|
+
|
|
84
|
+
### 基本用法
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { Bubble } from '@unif/react-native-chat';
|
|
88
|
+
|
|
89
|
+
<Bubble.List
|
|
90
|
+
items={messages}
|
|
91
|
+
header={<Welcome />}
|
|
92
|
+
renderBubble={(msg) => (
|
|
93
|
+
<Bubble role={msg.message.role}>
|
|
94
|
+
{msg.message.text}
|
|
95
|
+
</Bubble>
|
|
96
|
+
)}
|
|
97
|
+
/>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### BubbleListProps
|
|
101
|
+
|
|
102
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
103
|
+
|------|------|------|--------|
|
|
104
|
+
| items | 消息数据 | `T[]` | - |
|
|
105
|
+
| renderBubble | 渲染单条消息 | `(item: T) => ReactNode` | - |
|
|
106
|
+
| keyExtractor | 自定义 key 提取 | `(item: T) => string` | 使用 `item.id` |
|
|
107
|
+
| onEndReached | 滚动到底部回调(加载更多) | `() => void` | - |
|
|
108
|
+
| header | 列表为空时的顶部占位 | `ReactNode` | - |
|
|
109
|
+
| footer | 列表底部内容 | `ReactNode` | - |
|
|
110
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
111
|
+
| testID | 测试标识 | `string` | `'bubble-list'` |
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _tokens = require("../theme/tokens");
|
|
10
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
/**
|
|
13
|
+
* CardWrapper — 通用卡片路由容器
|
|
14
|
+
* registry 通过 props 注入(而非全局 import),更灵活
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const CardWrapper = ({
|
|
18
|
+
cardType,
|
|
19
|
+
data,
|
|
20
|
+
actions,
|
|
21
|
+
registry = {},
|
|
22
|
+
fallback,
|
|
23
|
+
style,
|
|
24
|
+
testID
|
|
25
|
+
}) => {
|
|
26
|
+
const CardComponent = registry[cardType];
|
|
27
|
+
if (!CardComponent) {
|
|
28
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
29
|
+
style: [defaultStyles.container, style],
|
|
30
|
+
testID: testID,
|
|
31
|
+
children: fallback ?? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
32
|
+
style: defaultStyles.fallback,
|
|
33
|
+
children: ["\u4E0D\u652F\u6301\u7684\u5361\u7247\u7C7B\u578B: ", cardType]
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
38
|
+
style: [defaultStyles.container, style],
|
|
39
|
+
testID: testID ?? `card-${cardType}`,
|
|
40
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(CardComponent, {
|
|
41
|
+
data: data,
|
|
42
|
+
actions: actions
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const defaultStyles = _reactNative.StyleSheet.create({
|
|
47
|
+
container: {
|
|
48
|
+
backgroundColor: _tokens.chatTokens.colorBgElevated,
|
|
49
|
+
borderRadius: 12,
|
|
50
|
+
borderWidth: 1,
|
|
51
|
+
borderColor: _tokens.chatTokens.colorBorder,
|
|
52
|
+
marginLeft: 8,
|
|
53
|
+
marginRight: 40,
|
|
54
|
+
marginBottom: 4,
|
|
55
|
+
overflow: 'hidden',
|
|
56
|
+
maxWidth: '85%'
|
|
57
|
+
},
|
|
58
|
+
fallback: {
|
|
59
|
+
padding: 12,
|
|
60
|
+
fontSize: 13,
|
|
61
|
+
color: _tokens.chatTokens.colorTextSecondary
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(CardWrapper);
|
|
65
|
+
//# sourceMappingURL=CardWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_tokens","_jsxRuntime","e","__esModule","default","CardWrapper","cardType","data","actions","registry","fallback","style","testID","CardComponent","jsx","View","defaultStyles","container","children","jsxs","Text","StyleSheet","create","backgroundColor","chatTokens","colorBgElevated","borderRadius","borderWidth","borderColor","colorBorder","marginLeft","marginRight","marginBottom","overflow","maxWidth","padding","fontSize","color","colorTextSecondary","_default","exports","React","memo"],"sourceRoot":"../../../src","sources":["card-wrapper/CardWrapper.tsx"],"mappings":";;;;;;AAKA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAA2C,IAAAG,WAAA,GAAAH,OAAA;AAAA,SAAAD,uBAAAK,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAP3C;AACA;AACA;AACA;;AAqBA,MAAMG,WAAuC,GAAGA,CAAC;EAC/CC,QAAQ;EACRC,IAAI;EACJC,OAAO;EACPC,QAAQ,GAAG,CAAC,CAAC;EACbC,QAAQ;EACRC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,aAAa,GAAGJ,QAAQ,CAACH,QAAQ,CAAC;EAExC,IAAI,CAACO,aAAa,EAAE;IAClB,oBACE,IAAAZ,WAAA,CAAAa,GAAA,EAACf,YAAA,CAAAgB,IAAI;MAACJ,KAAK,EAAE,CAACK,aAAa,CAACC,SAAS,EAAEN,KAAK,CAAE;MAACC,MAAM,EAAEA,MAAO;MAAAM,QAAA,EAC3DR,QAAQ,iBACP,IAAAT,WAAA,CAAAkB,IAAA,EAACpB,YAAA,CAAAqB,IAAI;QAACT,KAAK,EAAEK,aAAa,CAACN,QAAS;QAAAQ,QAAA,GAAC,oDACzB,EAACZ,QAAQ;MAAA,CACf;IACP,CACG,CAAC;EAEX;EAEA,oBACE,IAAAL,WAAA,CAAAa,GAAA,EAACf,YAAA,CAAAgB,IAAI;IACHJ,KAAK,EAAE,CAACK,aAAa,CAACC,SAAS,EAAEN,KAAK,CAAE;IACxCC,MAAM,EAAEA,MAAM,IAAI,QAAQN,QAAQ,EAAG;IAAAY,QAAA,eACrC,IAAAjB,WAAA,CAAAa,GAAA,EAACD,aAAa;MAACN,IAAI,EAAEA,IAAK;MAACC,OAAO,EAAEA;IAAQ,CAAE;EAAC,CAC3C,CAAC;AAEX,CAAC;AAED,MAAMQ,aAAa,GAAGK,uBAAU,CAACC,MAAM,CAAC;EACtCL,SAAS,EAAE;IACTM,eAAe,EAAEC,kBAAU,CAACC,eAAe;IAC3CC,YAAY,EAAE,EAAE;IAChBC,WAAW,EAAE,CAAC;IACdC,WAAW,EAAEJ,kBAAU,CAACK,WAAW;IACnCC,UAAU,EAAE,CAAC;IACbC,WAAW,EAAE,EAAE;IACfC,YAAY,EAAE,CAAC;IACfC,QAAQ,EAAE,QAAQ;IAClBC,QAAQ,EAAE;EACZ,CAAC;EACDxB,QAAQ,EAAE;IACRyB,OAAO,EAAE,EAAE;IACXC,QAAQ,EAAE,EAAE;IACZC,KAAK,EAAEb,kBAAU,CAACc;EACpB;AACF,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAApC,OAAA,gBAEYqC,cAAK,CAACC,IAAI,CAACrC,WAAW,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CardWrapper 卡片容器
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# CardWrapper 卡片容器
|
|
9
|
+
|
|
10
|
+
通用卡片路由容器,通过 `registry` props 注入实现卡片类型到组件的映射。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- AI 回复中包含结构化卡片内容(产品列表、表单、图表等)
|
|
15
|
+
- 需要根据 `cardType` 动态渲染不同业务组件
|
|
16
|
+
|
|
17
|
+
## 代码示例
|
|
18
|
+
|
|
19
|
+
### 基本用法
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { CardWrapper, type CardComponentType } from '@unif/react-native-chat';
|
|
23
|
+
|
|
24
|
+
// 定义业务卡片
|
|
25
|
+
const ProductCard: CardComponentType = ({ data, actions }) => (
|
|
26
|
+
<View>
|
|
27
|
+
<Text>{data.productName as string}</Text>
|
|
28
|
+
<Text>{data.price as string}</Text>
|
|
29
|
+
</View>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// 注册卡片
|
|
33
|
+
const registry = {
|
|
34
|
+
product_list: ProductCard,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
<CardWrapper
|
|
38
|
+
cardType="product_list"
|
|
39
|
+
data={{ productName: '基金A', price: '1.2345' }}
|
|
40
|
+
actions={['buy', 'detail']}
|
|
41
|
+
registry={registry}
|
|
42
|
+
/>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 自定义 fallback
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<CardWrapper
|
|
49
|
+
cardType="unknown_type"
|
|
50
|
+
data={{}}
|
|
51
|
+
actions={[]}
|
|
52
|
+
registry={registry}
|
|
53
|
+
fallback={<Text>暂不支持此类型</Text>}
|
|
54
|
+
/>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## API
|
|
58
|
+
|
|
59
|
+
### CardWrapperProps
|
|
60
|
+
|
|
61
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
62
|
+
|------|------|------|--------|
|
|
63
|
+
| cardType | 卡片类型标识 | `string` | - |
|
|
64
|
+
| data | 卡片数据 | `Record<string, unknown>` | - |
|
|
65
|
+
| actions | 可用操作列表 | `string[]` | - |
|
|
66
|
+
| registry | 卡片注册表 | `Record<string, CardComponentType>` | `{}` |
|
|
67
|
+
| fallback | 未知卡片类型的 fallback | `ReactNode` | 默认错误提示 |
|
|
68
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
69
|
+
| testID | 测试标识 | `string` | - |
|
|
70
|
+
|
|
71
|
+
### CardComponentType
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
type CardComponentType = React.ComponentType<{
|
|
75
|
+
data: Record<string, unknown>;
|
|
76
|
+
actions: string[];
|
|
77
|
+
}>;
|
|
78
|
+
```
|