@unif/react-native-chat-markdown 0.1.1 → 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/lib/commonjs/index.js +41 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/markdown-bubble/MarkdownBubble.js +90 -0
- package/lib/commonjs/markdown-bubble/MarkdownBubble.js.map +1 -0
- package/lib/commonjs/markdown-bubble/index.md +61 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/streaming-bubble/StreamingBubble.js +64 -0
- package/lib/commonjs/streaming-bubble/StreamingBubble.js.map +1 -0
- package/lib/commonjs/streaming-bubble/index.md +47 -0
- package/lib/commonjs/think-block/ThinkBlock.js +92 -0
- package/lib/commonjs/think-block/ThinkBlock.js.map +1 -0
- package/lib/commonjs/think-block/index.md +57 -0
- package/lib/commonjs/utils/thinkTagParser.js +42 -0
- package/lib/commonjs/utils/thinkTagParser.js.map +1 -0
- package/lib/module/index.js +12 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/markdown-bubble/MarkdownBubble.js +84 -0
- package/lib/module/markdown-bubble/MarkdownBubble.js.map +1 -0
- package/lib/module/markdown-bubble/index.md +61 -0
- package/lib/module/package.json +1 -0
- package/lib/module/streaming-bubble/StreamingBubble.js +59 -0
- package/lib/module/streaming-bubble/StreamingBubble.js.map +1 -0
- package/lib/module/streaming-bubble/index.md +47 -0
- package/lib/module/think-block/ThinkBlock.js +87 -0
- package/lib/module/think-block/ThinkBlock.js.map +1 -0
- package/lib/module/think-block/index.md +57 -0
- package/lib/module/utils/thinkTagParser.js +37 -0
- package/lib/module/utils/thinkTagParser.js.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +13 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/markdown-bubble/MarkdownBubble.d.ts +15 -0
- package/lib/typescript/commonjs/markdown-bubble/MarkdownBubble.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/streaming-bubble/StreamingBubble.d.ts +16 -0
- package/lib/typescript/commonjs/streaming-bubble/StreamingBubble.d.ts.map +1 -0
- package/lib/typescript/commonjs/think-block/ThinkBlock.d.ts +24 -0
- package/lib/typescript/commonjs/think-block/ThinkBlock.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/thinkTagParser.d.ts +20 -0
- package/lib/typescript/commonjs/utils/thinkTagParser.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +13 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/markdown-bubble/MarkdownBubble.d.ts +15 -0
- package/lib/typescript/module/markdown-bubble/MarkdownBubble.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/streaming-bubble/StreamingBubble.d.ts +16 -0
- package/lib/typescript/module/streaming-bubble/StreamingBubble.d.ts.map +1 -0
- package/lib/typescript/module/think-block/ThinkBlock.d.ts +24 -0
- package/lib/typescript/module/think-block/ThinkBlock.d.ts.map +1 -0
- package/lib/typescript/module/utils/thinkTagParser.d.ts +20 -0
- package/lib/typescript/module/utils/thinkTagParser.d.ts.map +1 -0
- package/package.json +41 -10
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "MarkdownBubble", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _MarkdownBubble.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "StreamingBubble", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _StreamingBubble.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "ThinkBlock", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _ThinkBlock.default;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "hasUnclosedThink", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _thinkTagParser.hasUnclosedThink;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "parseThinkTags", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _thinkTagParser.parseThinkTags;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
var _ThinkBlock = _interopRequireDefault(require("./think-block/ThinkBlock"));
|
|
37
|
+
var _StreamingBubble = _interopRequireDefault(require("./streaming-bubble/StreamingBubble"));
|
|
38
|
+
var _MarkdownBubble = _interopRequireDefault(require("./markdown-bubble/MarkdownBubble"));
|
|
39
|
+
var _thinkTagParser = require("./utils/thinkTagParser");
|
|
40
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_ThinkBlock","_interopRequireDefault","require","_StreamingBubble","_MarkdownBubble","_thinkTagParser","e","__esModule","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,IAAAA,WAAA,GAAAC,sBAAA,CAAAC,OAAA;AAGA,IAAAC,gBAAA,GAAAF,sBAAA,CAAAC,OAAA;AAGA,IAAAE,eAAA,GAAAH,sBAAA,CAAAC,OAAA;AAGA,IAAAG,eAAA,GAAAH,OAAA;AAAwE,SAAAD,uBAAAK,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]}
|
|
@@ -0,0 +1,90 @@
|
|
|
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 _reactNativeMarkdownDisplay = _interopRequireDefault(require("@ronradtke/react-native-markdown-display"));
|
|
10
|
+
var _thinkTagParser = require("../utils/thinkTagParser");
|
|
11
|
+
var _ThinkBlock = _interopRequireDefault(require("../think-block/ThinkBlock"));
|
|
12
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
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); }
|
|
15
|
+
/**
|
|
16
|
+
* MarkdownBubble — Markdown 渲染气泡
|
|
17
|
+
* 完成的消息用 Markdown 渲染 + think 折叠
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const defaultMarkdownStyles = {
|
|
21
|
+
body: {
|
|
22
|
+
fontSize: 15,
|
|
23
|
+
color: '#1F2937',
|
|
24
|
+
lineHeight: 22
|
|
25
|
+
},
|
|
26
|
+
paragraph: {
|
|
27
|
+
marginTop: 0,
|
|
28
|
+
marginBottom: 6
|
|
29
|
+
},
|
|
30
|
+
code_inline: {
|
|
31
|
+
backgroundColor: '#F5F5F5',
|
|
32
|
+
borderRadius: 3,
|
|
33
|
+
paddingHorizontal: 4,
|
|
34
|
+
fontSize: 13,
|
|
35
|
+
color: '#E8550A'
|
|
36
|
+
},
|
|
37
|
+
fence: {
|
|
38
|
+
backgroundColor: '#F5F5F5',
|
|
39
|
+
borderRadius: 6,
|
|
40
|
+
padding: 10,
|
|
41
|
+
fontSize: 13
|
|
42
|
+
},
|
|
43
|
+
link: {
|
|
44
|
+
color: '#1677FF'
|
|
45
|
+
},
|
|
46
|
+
strong: {
|
|
47
|
+
fontWeight: '600'
|
|
48
|
+
},
|
|
49
|
+
list_item: {
|
|
50
|
+
marginBottom: 4
|
|
51
|
+
},
|
|
52
|
+
blockquote: {
|
|
53
|
+
borderLeftWidth: 3,
|
|
54
|
+
borderLeftColor: '#E5E7EB',
|
|
55
|
+
paddingLeft: 10,
|
|
56
|
+
marginLeft: 0
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const MarkdownBubble = ({
|
|
60
|
+
text,
|
|
61
|
+
markdownStyles,
|
|
62
|
+
style,
|
|
63
|
+
testID = 'markdown-bubble'
|
|
64
|
+
}) => {
|
|
65
|
+
const {
|
|
66
|
+
body,
|
|
67
|
+
thinks
|
|
68
|
+
} = (0, _react.useMemo)(() => (0, _thinkTagParser.parseThinkTags)(text), [text]);
|
|
69
|
+
const mergedStyles = (0, _react.useMemo)(() => ({
|
|
70
|
+
...defaultMarkdownStyles,
|
|
71
|
+
...markdownStyles
|
|
72
|
+
}), [markdownStyles]);
|
|
73
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
74
|
+
style: [defaultContainerStyles.container, style],
|
|
75
|
+
testID: testID,
|
|
76
|
+
children: [thinks.map((think, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_ThinkBlock.default, {
|
|
77
|
+
content: think
|
|
78
|
+
}, index)), body.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeMarkdownDisplay.default, {
|
|
79
|
+
style: mergedStyles,
|
|
80
|
+
children: body
|
|
81
|
+
})]
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const defaultContainerStyles = _reactNative.StyleSheet.create({
|
|
85
|
+
container: {
|
|
86
|
+
paddingVertical: 4
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(MarkdownBubble);
|
|
90
|
+
//# sourceMappingURL=MarkdownBubble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeMarkdownDisplay","_interopRequireDefault","_thinkTagParser","_ThinkBlock","_jsxRuntime","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","defaultMarkdownStyles","body","fontSize","color","lineHeight","paragraph","marginTop","marginBottom","code_inline","backgroundColor","borderRadius","paddingHorizontal","fence","padding","link","strong","fontWeight","list_item","blockquote","borderLeftWidth","borderLeftColor","paddingLeft","marginLeft","MarkdownBubble","text","markdownStyles","style","testID","thinks","useMemo","parseThinkTags","mergedStyles","jsxs","View","defaultContainerStyles","container","children","map","think","index","jsx","content","length","StyleSheet","create","paddingVertical","_default","exports","React","memo"],"sourceRoot":"../../../src","sources":["markdown-bubble/MarkdownBubble.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: MarkdownBubble Markdown 渲染
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# MarkdownBubble Markdown 渲染
|
|
9
|
+
|
|
10
|
+
完整的 Markdown 渲染气泡,自动解析 `<think>` 标签并渲染为 ThinkBlock。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- AI 回复完成后(status === 'success')渲染完整内容
|
|
15
|
+
- 内容包含 Markdown 格式(标题、代码、链接、列表等)
|
|
16
|
+
- 内容包含 `<think>` 标签需要折叠展示
|
|
17
|
+
|
|
18
|
+
## 代码示例
|
|
19
|
+
|
|
20
|
+
### 基本用法
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { MarkdownBubble } from '@unif/react-native-chat-markdown';
|
|
24
|
+
|
|
25
|
+
<MarkdownBubble text="**加粗** 和 `代码` 以及[链接](https://example.com)" />
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 包含思考内容
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<MarkdownBubble
|
|
32
|
+
text="<think>分析用户意图...</think>根据您的需求,推荐以下方案..."
|
|
33
|
+
/>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 自定义 Markdown 样式
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
<MarkdownBubble
|
|
40
|
+
text={messageText}
|
|
41
|
+
markdownStyles={{
|
|
42
|
+
body: { fontSize: 16, color: '#333' },
|
|
43
|
+
code_inline: { backgroundColor: '#F0F0F0' },
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
### MarkdownBubbleProps
|
|
51
|
+
|
|
52
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
53
|
+
|------|------|------|--------|
|
|
54
|
+
| text | Markdown 文本 | `string` | - |
|
|
55
|
+
| markdownStyles | 覆盖默认 Markdown 样式 | `Record<string, unknown>` | 内置样式 |
|
|
56
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
57
|
+
| testID | 测试标识 | `string` | `'markdown-bubble'` |
|
|
58
|
+
|
|
59
|
+
### 依赖
|
|
60
|
+
|
|
61
|
+
- `@ronradtke/react-native-markdown-display` — Markdown 渲染引擎
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,64 @@
|
|
|
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
|
+
* StreamingBubble — 流式文本气泡
|
|
13
|
+
* 显示正在流入的文本 + 呼吸动画光标
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const StreamingBubble = ({
|
|
17
|
+
text,
|
|
18
|
+
cursorColor = '#1677FF',
|
|
19
|
+
cursorChar = '▌',
|
|
20
|
+
style,
|
|
21
|
+
testID = 'streaming-bubble'
|
|
22
|
+
}) => {
|
|
23
|
+
const opacity = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
|
|
24
|
+
(0, _react.useEffect)(() => {
|
|
25
|
+
const animation = _reactNative.Animated.loop(_reactNative.Animated.sequence([_reactNative.Animated.timing(opacity, {
|
|
26
|
+
toValue: 0,
|
|
27
|
+
duration: 400,
|
|
28
|
+
useNativeDriver: true
|
|
29
|
+
}), _reactNative.Animated.timing(opacity, {
|
|
30
|
+
toValue: 1,
|
|
31
|
+
duration: 400,
|
|
32
|
+
useNativeDriver: true
|
|
33
|
+
})]));
|
|
34
|
+
animation.start();
|
|
35
|
+
return () => animation.stop();
|
|
36
|
+
}, [opacity]);
|
|
37
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
38
|
+
style: [defaultStyles.container, style],
|
|
39
|
+
testID: testID,
|
|
40
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
41
|
+
style: defaultStyles.text,
|
|
42
|
+
children: [text, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.Text, {
|
|
43
|
+
style: [{
|
|
44
|
+
color: cursorColor
|
|
45
|
+
}, {
|
|
46
|
+
opacity
|
|
47
|
+
}],
|
|
48
|
+
children: cursorChar
|
|
49
|
+
})]
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const defaultStyles = _reactNative.StyleSheet.create({
|
|
54
|
+
container: {
|
|
55
|
+
paddingVertical: 4
|
|
56
|
+
},
|
|
57
|
+
text: {
|
|
58
|
+
fontSize: 15,
|
|
59
|
+
color: '#1F2937',
|
|
60
|
+
lineHeight: 22
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(StreamingBubble);
|
|
64
|
+
//# sourceMappingURL=StreamingBubble.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","StreamingBubble","text","cursorColor","cursorChar","style","testID","opacity","useRef","Animated","Value","current","useEffect","animation","loop","sequence","timing","toValue","duration","useNativeDriver","start","stop","jsx","View","defaultStyles","container","children","jsxs","Text","color","StyleSheet","create","paddingVertical","fontSize","lineHeight","_default","exports","React","memo"],"sourceRoot":"../../../src","sources":["streaming-bubble/StreamingBubble.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: StreamingBubble 流式气泡
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# StreamingBubble 流式气泡
|
|
9
|
+
|
|
10
|
+
展示正在流入的文本内容,附带闪烁光标动画。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- AI 正在流式输出回复时(status === 'updating')
|
|
15
|
+
- 需要视觉上表示内容仍在生成中
|
|
16
|
+
|
|
17
|
+
## 代码示例
|
|
18
|
+
|
|
19
|
+
### 基本用法
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { StreamingBubble } from '@unif/react-native-chat-markdown';
|
|
23
|
+
|
|
24
|
+
<StreamingBubble text="正在生成的文本内容..." />
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 自定义光标
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<StreamingBubble
|
|
31
|
+
text={streamingText}
|
|
32
|
+
cursorColor="#FF6B00"
|
|
33
|
+
cursorChar="●"
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
### StreamingBubbleProps
|
|
40
|
+
|
|
41
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
42
|
+
|------|------|------|--------|
|
|
43
|
+
| text | 当前流式文本 | `string` | - |
|
|
44
|
+
| cursorColor | 光标颜色 | `string` | `'#1677FF'` |
|
|
45
|
+
| cursorChar | 光标字符 | `string` | `'▌'` |
|
|
46
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
47
|
+
| testID | 测试标识 | `string` | `'streaming-bubble'` |
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
* ThinkBlock — 思考折叠块
|
|
13
|
+
* 卡片式,圆角 12px
|
|
14
|
+
* 标题:🧠 已深度思考(展开) ▾
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const ThinkBlock = ({
|
|
18
|
+
content,
|
|
19
|
+
defaultExpanded = false,
|
|
20
|
+
label = '深度思考',
|
|
21
|
+
style,
|
|
22
|
+
styles: semanticStyles,
|
|
23
|
+
testID = 'think-block'
|
|
24
|
+
}) => {
|
|
25
|
+
const [expanded, setExpanded] = (0, _react.useState)(defaultExpanded);
|
|
26
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
27
|
+
style: [defaultStyles.container, semanticStyles?.root, style],
|
|
28
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
29
|
+
style: [defaultStyles.header, semanticStyles?.header],
|
|
30
|
+
onPress: () => setExpanded(!expanded),
|
|
31
|
+
activeOpacity: 0.7,
|
|
32
|
+
testID: `${testID}-toggle`,
|
|
33
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
34
|
+
style: defaultStyles.titleRow,
|
|
35
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
36
|
+
style: defaultStyles.brainIcon,
|
|
37
|
+
children: "\uD83E\uDDE0"
|
|
38
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
39
|
+
style: [defaultStyles.label, semanticStyles?.label],
|
|
40
|
+
children: ["\u5DF2", label, expanded ? '(展开)' : '(收起)']
|
|
41
|
+
})]
|
|
42
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
43
|
+
style: defaultStyles.chevron,
|
|
44
|
+
children: expanded ? '▲' : '▼'
|
|
45
|
+
})]
|
|
46
|
+
}), expanded && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
47
|
+
style: [defaultStyles.content, semanticStyles?.content],
|
|
48
|
+
testID: `${testID}-content`,
|
|
49
|
+
children: content
|
|
50
|
+
})]
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const defaultStyles = _reactNative.StyleSheet.create({
|
|
54
|
+
container: {
|
|
55
|
+
backgroundColor: '#F9FAFB',
|
|
56
|
+
borderRadius: 12,
|
|
57
|
+
marginBottom: 8,
|
|
58
|
+
overflow: 'hidden'
|
|
59
|
+
},
|
|
60
|
+
header: {
|
|
61
|
+
flexDirection: 'row',
|
|
62
|
+
alignItems: 'center',
|
|
63
|
+
justifyContent: 'space-between',
|
|
64
|
+
paddingHorizontal: 14,
|
|
65
|
+
paddingVertical: 10
|
|
66
|
+
},
|
|
67
|
+
titleRow: {
|
|
68
|
+
flexDirection: 'row',
|
|
69
|
+
alignItems: 'center'
|
|
70
|
+
},
|
|
71
|
+
brainIcon: {
|
|
72
|
+
fontSize: 14
|
|
73
|
+
},
|
|
74
|
+
label: {
|
|
75
|
+
marginLeft: 6,
|
|
76
|
+
fontSize: 12,
|
|
77
|
+
color: '#6B7280'
|
|
78
|
+
},
|
|
79
|
+
chevron: {
|
|
80
|
+
fontSize: 10,
|
|
81
|
+
color: '#6B7280'
|
|
82
|
+
},
|
|
83
|
+
content: {
|
|
84
|
+
fontSize: 12,
|
|
85
|
+
color: '#6B7280',
|
|
86
|
+
lineHeight: 20,
|
|
87
|
+
paddingHorizontal: 14,
|
|
88
|
+
paddingBottom: 12
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(ThinkBlock);
|
|
92
|
+
//# sourceMappingURL=ThinkBlock.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","ThinkBlock","content","defaultExpanded","label","style","styles","semanticStyles","testID","expanded","setExpanded","useState","jsxs","View","defaultStyles","container","root","children","TouchableOpacity","header","onPress","activeOpacity","titleRow","jsx","Text","brainIcon","chevron","StyleSheet","create","backgroundColor","borderRadius","marginBottom","overflow","flexDirection","alignItems","justifyContent","paddingHorizontal","paddingVertical","fontSize","marginLeft","color","lineHeight","paddingBottom","_default","exports","React","memo"],"sourceRoot":"../../../src","sources":["think-block/ThinkBlock.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: ThinkBlock 思考折叠块
|
|
3
|
+
nav:
|
|
4
|
+
title: 组件
|
|
5
|
+
path: /components
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# ThinkBlock 思考折叠块
|
|
9
|
+
|
|
10
|
+
展示 AI 的思考过程,可折叠/展开。
|
|
11
|
+
|
|
12
|
+
## 何时使用
|
|
13
|
+
|
|
14
|
+
- AI 回复中包含 `<think>` 标签的思考内容
|
|
15
|
+
- 需要可折叠展示推理过程(如 DeepSeek 的 reasoning_content)
|
|
16
|
+
|
|
17
|
+
## 代码示例
|
|
18
|
+
|
|
19
|
+
### 基本用法
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { ThinkBlock } from '@unif/react-native-chat-markdown';
|
|
23
|
+
|
|
24
|
+
<ThinkBlock content="用户询问的是账户余额,需要调用查询接口..." />
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 默认展开
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<ThinkBlock
|
|
31
|
+
content="分析用户意图..."
|
|
32
|
+
defaultExpanded={true}
|
|
33
|
+
label="思考过程"
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
### ThinkBlockProps
|
|
40
|
+
|
|
41
|
+
| 属性 | 说明 | 类型 | 默认值 |
|
|
42
|
+
|------|------|------|--------|
|
|
43
|
+
| content | 思考内容 | `string` | - |
|
|
44
|
+
| defaultExpanded | 默认展开 | `boolean` | `false` |
|
|
45
|
+
| label | 标题文字 | `string` | `'深度思考'` |
|
|
46
|
+
| style | 容器样式 | `ViewStyle` | - |
|
|
47
|
+
| styles | 语义样式 | `Partial<ThinkBlockSemanticStyles>` | - |
|
|
48
|
+
| testID | 测试标识 | `string` | `'think-block'` |
|
|
49
|
+
|
|
50
|
+
### ThinkBlockSemanticStyles
|
|
51
|
+
|
|
52
|
+
| 属性 | 说明 | 类型 |
|
|
53
|
+
|------|------|------|
|
|
54
|
+
| root | 外层容器 | `ViewStyle` |
|
|
55
|
+
| header | 标题栏 | `ViewStyle` |
|
|
56
|
+
| label | 标题文字 | `TextStyle` |
|
|
57
|
+
| content | 内容文字 | `TextStyle` |
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.hasUnclosedThink = hasUnclosedThink;
|
|
7
|
+
exports.parseThinkTags = parseThinkTags;
|
|
8
|
+
/**
|
|
9
|
+
* <think> 标签解析器
|
|
10
|
+
* 将文本中的 <think>...</think> 提取出来,分离为普通内容和思考内容
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const THINK_REGEX = /<think>([\s\S]*?)<\/think>/g;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 解析文本中的 <think> 标签
|
|
17
|
+
* 支持多个 <think> 块,返回分离后的正文和思考内容
|
|
18
|
+
*/
|
|
19
|
+
function parseThinkTags(text) {
|
|
20
|
+
const thinks = [];
|
|
21
|
+
const body = text.replace(THINK_REGEX, (_match, content) => {
|
|
22
|
+
const trimmed = content.trim();
|
|
23
|
+
if (trimmed) {
|
|
24
|
+
thinks.push(trimmed);
|
|
25
|
+
}
|
|
26
|
+
return '';
|
|
27
|
+
}).trim();
|
|
28
|
+
return {
|
|
29
|
+
body,
|
|
30
|
+
thinks
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 检查文本中是否包含未闭合的 <think> 标签(流式场景)
|
|
36
|
+
*/
|
|
37
|
+
function hasUnclosedThink(text) {
|
|
38
|
+
const opens = (text.match(/<think>/g) || []).length;
|
|
39
|
+
const closes = (text.match(/<\/think>/g) || []).length;
|
|
40
|
+
return opens > closes;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=thinkTagParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["THINK_REGEX","parseThinkTags","text","thinks","body","replace","_match","content","trimmed","trim","push","hasUnclosedThink","opens","match","length","closes"],"sourceRoot":"../../../src","sources":["utils/thinkTagParser.ts"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;;AASA,MAAMA,WAAW,GAAG,6BAA6B;;AAEjD;AACA;AACA;AACA;AACO,SAASC,cAAcA,CAACC,IAAY,EAAiB;EAC1D,MAAMC,MAAgB,GAAG,EAAE;EAC3B,MAAMC,IAAI,GAAGF,IAAI,CACdG,OAAO,CAACL,WAAW,EAAE,CAACM,MAAM,EAAEC,OAAe,KAAK;IACjD,MAAMC,OAAO,GAAGD,OAAO,CAACE,IAAI,CAAC,CAAC;IAC9B,IAAID,OAAO,EAAE;MACXL,MAAM,CAACO,IAAI,CAACF,OAAO,CAAC;IACtB;IACA,OAAO,EAAE;EACX,CAAC,CAAC,CACDC,IAAI,CAAC,CAAC;EAET,OAAO;IAACL,IAAI;IAAED;EAAM,CAAC;AACvB;;AAEA;AACA;AACA;AACO,SAASQ,gBAAgBA,CAACT,IAAY,EAAW;EACtD,MAAMU,KAAK,GAAG,CAACV,IAAI,CAACW,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,EAAEC,MAAM;EACnD,MAAMC,MAAM,GAAG,CAACb,IAAI,CAACW,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,EAAEC,MAAM;EACtD,OAAOF,KAAK,GAAGG,MAAM;AACvB","ignoreList":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @unif/react-native-chat-markdown
|
|
5
|
+
* Markdown 渲染、ThinkBlock、流式气泡
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export { default as ThinkBlock } from "./think-block/ThinkBlock.js";
|
|
9
|
+
export { default as StreamingBubble } from "./streaming-bubble/StreamingBubble.js";
|
|
10
|
+
export { default as MarkdownBubble } from "./markdown-bubble/MarkdownBubble.js";
|
|
11
|
+
export { parseThinkTags, hasUnclosedThink } from "./utils/thinkTagParser.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["default","ThinkBlock","StreamingBubble","MarkdownBubble","parseThinkTags","hasUnclosedThink"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,SAAQA,OAAO,IAAIC,UAAU,QAAO,6BAA0B;AAG9D,SAAQD,OAAO,IAAIE,eAAe,QAAO,uCAAoC;AAG7E,SAAQF,OAAO,IAAIG,cAAc,QAAO,qCAAkC;AAG1E,SAAQC,cAAc,EAAEC,gBAAgB,QAAO,2BAAwB","ignoreList":[]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MarkdownBubble — Markdown 渲染气泡
|
|
5
|
+
* 完成的消息用 Markdown 渲染 + think 折叠
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { useMemo } from 'react';
|
|
9
|
+
import { View, StyleSheet } from 'react-native';
|
|
10
|
+
import Markdown from '@ronradtke/react-native-markdown-display';
|
|
11
|
+
import { parseThinkTags } from "../utils/thinkTagParser.js";
|
|
12
|
+
import ThinkBlock from "../think-block/ThinkBlock.js";
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
const defaultMarkdownStyles = {
|
|
15
|
+
body: {
|
|
16
|
+
fontSize: 15,
|
|
17
|
+
color: '#1F2937',
|
|
18
|
+
lineHeight: 22
|
|
19
|
+
},
|
|
20
|
+
paragraph: {
|
|
21
|
+
marginTop: 0,
|
|
22
|
+
marginBottom: 6
|
|
23
|
+
},
|
|
24
|
+
code_inline: {
|
|
25
|
+
backgroundColor: '#F5F5F5',
|
|
26
|
+
borderRadius: 3,
|
|
27
|
+
paddingHorizontal: 4,
|
|
28
|
+
fontSize: 13,
|
|
29
|
+
color: '#E8550A'
|
|
30
|
+
},
|
|
31
|
+
fence: {
|
|
32
|
+
backgroundColor: '#F5F5F5',
|
|
33
|
+
borderRadius: 6,
|
|
34
|
+
padding: 10,
|
|
35
|
+
fontSize: 13
|
|
36
|
+
},
|
|
37
|
+
link: {
|
|
38
|
+
color: '#1677FF'
|
|
39
|
+
},
|
|
40
|
+
strong: {
|
|
41
|
+
fontWeight: '600'
|
|
42
|
+
},
|
|
43
|
+
list_item: {
|
|
44
|
+
marginBottom: 4
|
|
45
|
+
},
|
|
46
|
+
blockquote: {
|
|
47
|
+
borderLeftWidth: 3,
|
|
48
|
+
borderLeftColor: '#E5E7EB',
|
|
49
|
+
paddingLeft: 10,
|
|
50
|
+
marginLeft: 0
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const MarkdownBubble = ({
|
|
54
|
+
text,
|
|
55
|
+
markdownStyles,
|
|
56
|
+
style,
|
|
57
|
+
testID = 'markdown-bubble'
|
|
58
|
+
}) => {
|
|
59
|
+
const {
|
|
60
|
+
body,
|
|
61
|
+
thinks
|
|
62
|
+
} = useMemo(() => parseThinkTags(text), [text]);
|
|
63
|
+
const mergedStyles = useMemo(() => ({
|
|
64
|
+
...defaultMarkdownStyles,
|
|
65
|
+
...markdownStyles
|
|
66
|
+
}), [markdownStyles]);
|
|
67
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
68
|
+
style: [defaultContainerStyles.container, style],
|
|
69
|
+
testID: testID,
|
|
70
|
+
children: [thinks.map((think, index) => /*#__PURE__*/_jsx(ThinkBlock, {
|
|
71
|
+
content: think
|
|
72
|
+
}, index)), body.length > 0 && /*#__PURE__*/_jsx(Markdown, {
|
|
73
|
+
style: mergedStyles,
|
|
74
|
+
children: body
|
|
75
|
+
})]
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const defaultContainerStyles = StyleSheet.create({
|
|
79
|
+
container: {
|
|
80
|
+
paddingVertical: 4
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
export default /*#__PURE__*/React.memo(MarkdownBubble);
|
|
84
|
+
//# sourceMappingURL=MarkdownBubble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useMemo","View","StyleSheet","Markdown","parseThinkTags","ThinkBlock","jsx","_jsx","jsxs","_jsxs","defaultMarkdownStyles","body","fontSize","color","lineHeight","paragraph","marginTop","marginBottom","code_inline","backgroundColor","borderRadius","paddingHorizontal","fence","padding","link","strong","fontWeight","list_item","blockquote","borderLeftWidth","borderLeftColor","paddingLeft","marginLeft","MarkdownBubble","text","markdownStyles","style","testID","thinks","mergedStyles","defaultContainerStyles","container","children","map","think","index","content","length","create","paddingVertical","memo"],"sourceRoot":"../../../src","sources":["markdown-bubble/MarkdownBubble.tsx"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAGC,OAAO,QAAO,OAAO;AACpC,SAAQC,IAAI,EAAEC,UAAU,QAAuB,cAAc;AAC7D,OAAOC,QAAQ,MAAM,0CAA0C;AAC/D,SAAQC,cAAc,QAAO,4BAAyB;AACtD,OAAOC,UAAU,MAAM,8BAA2B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AASnD,MAAMC,qBAAqB,GAAG;EAC5BC,IAAI,EAAE;IACJC,QAAQ,EAAE,EAAE;IACZC,KAAK,EAAE,SAAS;IAChBC,UAAU,EAAE;EACd,CAAC;EACDC,SAAS,EAAE;IACTC,SAAS,EAAE,CAAC;IACZC,YAAY,EAAE;EAChB,CAAC;EACDC,WAAW,EAAE;IACXC,eAAe,EAAE,SAAS;IAC1BC,YAAY,EAAE,CAAC;IACfC,iBAAiB,EAAE,CAAC;IACpBT,QAAQ,EAAE,EAAE;IACZC,KAAK,EAAE;EACT,CAAC;EACDS,KAAK,EAAE;IACLH,eAAe,EAAE,SAAS;IAC1BC,YAAY,EAAE,CAAC;IACfG,OAAO,EAAE,EAAE;IACXX,QAAQ,EAAE;EACZ,CAAC;EACDY,IAAI,EAAE;IACJX,KAAK,EAAE;EACT,CAAC;EACDY,MAAM,EAAE;IACNC,UAAU,EAAE;EACd,CAAC;EACDC,SAAS,EAAE;IACTV,YAAY,EAAE;EAChB,CAAC;EACDW,UAAU,EAAE;IACVC,eAAe,EAAE,CAAC;IAClBC,eAAe,EAAE,SAAS;IAC1BC,WAAW,EAAE,EAAE;IACfC,UAAU,EAAE;EACd;AACF,CAAC;AAED,MAAMC,cAA6C,GAAGA,CAAC;EACrDC,IAAI;EACJC,cAAc;EACdC,KAAK;EACLC,MAAM,GAAG;AACX,CAAC,KAAK;EACJ,MAAM;IAAC1B,IAAI;IAAE2B;EAAM,CAAC,GAAGtC,OAAO,CAAC,MAAMI,cAAc,CAAC8B,IAAI,CAAC,EAAE,CAACA,IAAI,CAAC,CAAC;EAElE,MAAMK,YAAY,GAAGvC,OAAO,CAC1B,OAAO;IAAC,GAAGU,qBAAqB;IAAE,GAAGyB;EAAc,CAAC,CAAC,EACrD,CAACA,cAAc,CACjB,CAAC;EAED,oBACE1B,KAAA,CAACR,IAAI;IAACmC,KAAK,EAAE,CAACI,sBAAsB,CAACC,SAAS,EAAEL,KAAK,CAAE;IAACC,MAAM,EAAEA,MAAO;IAAAK,QAAA,GACpEJ,MAAM,CAACK,GAAG,CAAC,CAACC,KAAK,EAAEC,KAAK,kBACvBtC,IAAA,CAACF,UAAU;MAAayC,OAAO,EAAEF;IAAM,GAAtBC,KAAwB,CAC1C,CAAC,EACDlC,IAAI,CAACoC,MAAM,GAAG,CAAC,iBACdxC,IAAA,CAACJ,QAAQ;MAACiC,KAAK,EAAEG,YAAa;MAAAG,QAAA,EAAE/B;IAAI,CAAW,CAChD;EAAA,CACG,CAAC;AAEX,CAAC;AAED,MAAM6B,sBAAsB,GAAGtC,UAAU,CAAC8C,MAAM,CAAC;EAC/CP,SAAS,EAAE;IACTQ,eAAe,EAAE;EACnB;AACF,CAAC,CAAC;AAEF,4BAAelD,KAAK,CAACmD,IAAI,CAACjB,cAAc,CAAC","ignoreList":[]}
|