@ant-design/agentic-ui 2.24.0 → 2.24.1

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.
@@ -51,11 +51,13 @@ function _object_spread_props(target, source) {
51
51
  return target;
52
52
  }
53
53
  import SkeletonList from "./SkeletonList";
54
- import { useContext, useMemo } from "react";
54
+ import { useContext, useMemo, useRef } from "react";
55
55
  import { ConfigProvider } from "antd";
56
56
  import cx from "classnames";
57
+ import { nanoid } from "nanoid";
57
58
  import React from "react";
58
59
  import { BubbleConfigContext } from "../BubbleConfigProvide";
60
+ import { LOADING_FLAT } from "../MessagesContent";
59
61
  import { PureAIBubble, PureUserBubble } from "../PureBubble";
60
62
  import { useStyle } from "./style";
61
63
  export var PureBubbleList = function(props) {
@@ -71,6 +73,8 @@ export var PureBubbleList = function(props) {
71
73
  }, [
72
74
  JSON.stringify(props.style)
73
75
  ]);
76
+ // 为 loading 项生成唯一的 key,使用 ref 缓存以确保稳定性
77
+ var loadingKeysRef = useRef(new Map());
74
78
  var listDom = useMemo(function() {
75
79
  return bubbleList.map(function(item, index) {
76
80
  var placement = item.role === 'user' ? 'right' : 'left';
@@ -78,8 +82,18 @@ export var PureBubbleList = function(props) {
78
82
  var isLast = index === bubbleList.length - 1;
79
83
  item.isLatest = isLast;
80
84
  item.isLast = isLast;
85
+ // 如果 id 是 LOADING_FLAT,使用 uuid 作为 key
86
+ // 使用 index 和 createAt 的组合作为缓存 key,确保同一项在重新渲染时保持相同的 key
87
+ var itemKey = item.id;
88
+ if (item.id === LOADING_FLAT) {
89
+ var cacheKey = "".concat(index, "-").concat(item.createAt || Date.now());
90
+ if (!loadingKeysRef.current.has(cacheKey)) {
91
+ loadingKeysRef.current.set(cacheKey, nanoid());
92
+ }
93
+ itemKey = loadingKeysRef.current.get(cacheKey);
94
+ }
81
95
  return /*#__PURE__*/ React.createElement(BubbleComponent, {
82
- key: item.id,
96
+ key: itemKey,
83
97
  "data-id": item.id,
84
98
  avatar: _object_spread({}, placement === 'right' ? userMeta : assistantMeta, item.meta),
85
99
  preMessage: bubbleList[index - 1],
@@ -52,12 +52,14 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import SkeletonList from "./SkeletonList";
54
54
  export { PureBubbleList } from "./PureBubbleList";
55
- import { useContext, useMemo } from "react";
55
+ import { useContext, useMemo, useRef } from "react";
56
56
  import { ConfigProvider } from "antd";
57
57
  import cx from "classnames";
58
+ import { nanoid } from "nanoid";
58
59
  import React from "react";
59
60
  import { Bubble } from "../Bubble";
60
61
  import { BubbleConfigContext } from "../BubbleConfigProvide";
62
+ import { LOADING_FLAT } from "../MessagesContent";
61
63
  import { useStyle } from "./style";
62
64
  /**
63
65
  * BubbleList 组件 - 聊天气泡列表组件
@@ -130,6 +132,9 @@ import { useStyle } from "./style";
130
132
  }, [
131
133
  JSON.stringify(props.style)
132
134
  ]);
135
+ // 为 loading 项生成唯一的 key,使用 ref 缓存以确保稳定性
136
+ // 使用 item 的唯一标识(index + createAt)作为缓存 key
137
+ var loadingKeysRef = useRef(new Map());
133
138
  var bubbleListDom = useMemo(function() {
134
139
  return bubbleList.map(function(item, index) {
135
140
  var _props_bubbleRenderConfig;
@@ -138,8 +143,18 @@ import { useStyle } from "./style";
138
143
  // 保持向后兼容性,设置isLatest
139
144
  item.isLatest = isLast;
140
145
  item.isLast = isLast;
146
+ // 如果 id 是 LOADING_FLAT,使用 uuid 作为 key
147
+ // 使用 index 和 createAt 的组合作为缓存 key,确保同一项在重新渲染时保持相同的 key
148
+ var itemKey = item.id;
149
+ if (item.id === LOADING_FLAT) {
150
+ var cacheKey = "".concat(index, "-").concat(item.createAt || Date.now());
151
+ if (!loadingKeysRef.current.has(cacheKey)) {
152
+ loadingKeysRef.current.set(cacheKey, nanoid());
153
+ }
154
+ itemKey = loadingKeysRef.current.get(cacheKey);
155
+ }
141
156
  return /*#__PURE__*/ React.createElement(Bubble, {
142
- key: item.id,
157
+ key: itemKey,
143
158
  "data-id": item.id,
144
159
  avatar: _object_spread({}, item.role === 'user' ? userMeta : assistantMeta, item.meta),
145
160
  preMessage: bubbleList[index - 1],
@@ -52,10 +52,11 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import { ConfigProvider } from "antd";
54
54
  import classNames from "classnames";
55
- import React, { useContext } from "react";
55
+ import React, { useContext, useRef } from "react";
56
56
  import { Editor, Path, Transforms } from "slate";
57
57
  import { ReactEditor } from "slate-react";
58
58
  import { I18nContext } from "../../../I18n";
59
+ import { isMobileDevice } from "../../../MarkdownInputField/AttachmentButton/utils";
59
60
  import { useEditorStore } from "../store";
60
61
  import { EditorUtils } from "../utils/editorUtils";
61
62
  import { Blockquote } from "./Blockquote";
@@ -407,6 +408,46 @@ var MLeafComponent = function(props) {
407
408
  }
408
409
  } catch (e) {}
409
410
  };
411
+ var handleFncOpen = function() {
412
+ var _props_fncProps;
413
+ if ((_props_fncProps = props.fncProps) === null || _props_fncProps === void 0 ? void 0 : _props_fncProps.onOriginUrlClick) {
414
+ props.fncProps.onOriginUrlClick(leaf === null || leaf === void 0 ? void 0 : leaf.identifier);
415
+ }
416
+ };
417
+ var isMobile = isMobileDevice();
418
+ var hasFnc = leaf.fnc || leaf.identifier;
419
+ // 长按处理:用于手机端打开 fnc
420
+ var longPressTimerRef = useRef(null);
421
+ var touchStartTimeRef = useRef(0);
422
+ var isLongPressRef = useRef(false);
423
+ var handleTouchStart = function() {
424
+ if (!hasFnc) return;
425
+ isLongPressRef.current = false;
426
+ touchStartTimeRef.current = Date.now();
427
+ longPressTimerRef.current = setTimeout(function() {
428
+ isLongPressRef.current = true;
429
+ handleFncOpen();
430
+ }, 500); // 500ms 长按时间
431
+ };
432
+ var handleTouchEnd = function(e) {
433
+ if (!hasFnc) return;
434
+ if (longPressTimerRef.current) {
435
+ clearTimeout(longPressTimerRef.current);
436
+ longPressTimerRef.current = null;
437
+ }
438
+ // 如果是短按(小于 500ms),在手机上阻止默认行为
439
+ var touchDuration = Date.now() - touchStartTimeRef.current;
440
+ if (touchDuration < 500 && isMobile) {
441
+ e.preventDefault();
442
+ }
443
+ };
444
+ var handleTouchCancel = function() {
445
+ if (longPressTimerRef.current) {
446
+ clearTimeout(longPressTimerRef.current);
447
+ longPressTimerRef.current = null;
448
+ }
449
+ isLongPressRef.current = false;
450
+ };
410
451
  var _obj;
411
452
  var fncClassName = classNames(prefixClassName === null || prefixClassName === void 0 ? void 0 : prefixClassName.trim(), props.hashId, (_obj = {}, _define_property(_obj, "".concat(mdEditorBaseClass, "-fnc"), leaf.fnc), _define_property(_obj, "".concat(mdEditorBaseClass, "-fnd"), leaf.fnd), _define_property(_obj, "".concat(mdEditorBaseClass, "-comment"), leaf.comment), _obj));
412
453
  var dom = /*#__PURE__*/ React.createElement("span", _object_spread_props(_object_spread({}, props.attributes), {
@@ -415,6 +456,11 @@ var MLeafComponent = function(props) {
415
456
  onDragStart: dragStart,
416
457
  onClick: function(e) {
417
458
  var _props_fncProps;
459
+ // 在手机上,如果是 fnc,阻止点击事件(使用长按代替)
460
+ if (isMobile && hasFnc) {
461
+ e.preventDefault();
462
+ return;
463
+ }
418
464
  if (e.detail === 2) {
419
465
  selectFormat();
420
466
  }
@@ -422,6 +468,9 @@ var MLeafComponent = function(props) {
422
468
  props.fncProps.onOriginUrlClick(leaf === null || leaf === void 0 ? void 0 : leaf.identifier);
423
469
  }
424
470
  },
471
+ onTouchStart: hasFnc ? handleTouchStart : undefined,
472
+ onTouchEnd: hasFnc ? handleTouchEnd : undefined,
473
+ onTouchCancel: hasFnc ? handleTouchCancel : undefined,
425
474
  contentEditable: leaf.fnc ? false : undefined,
426
475
  "data-fnc": leaf.fnc || leaf.identifier ? 'fnc' : undefined,
427
476
  "data-fnd": leaf.fnd ? 'fnd' : undefined,
@@ -0,0 +1,53 @@
1
+ import { Elements } from '../../el';
2
+ /**
3
+ * Markdown 解析缓存类
4
+ *
5
+ * 使用 Map 存储 markdown 块到 schema 的映射,避免重复解析相同的 markdown 内容
6
+ */
7
+ export declare class ParseCache {
8
+ private cache;
9
+ /**
10
+ * 从缓存中获取解析结果
11
+ *
12
+ * @param md - markdown 字符串
13
+ * @returns 如果缓存中存在则返回解析结果,否则返回 null
14
+ */
15
+ get(md: string): Elements[] | null;
16
+ /**
17
+ * 将解析结果存入缓存
18
+ *
19
+ * @param md - markdown 字符串
20
+ * @param schema - 解析后的 schema 数组
21
+ */
22
+ set(md: string, schema: Elements[]): void;
23
+ /**
24
+ * 检查缓存中是否存在指定的 markdown
25
+ *
26
+ * @param md - markdown 字符串
27
+ * @returns 是否存在
28
+ */
29
+ has(md: string): boolean;
30
+ /**
31
+ * 清空缓存
32
+ */
33
+ clear(): void;
34
+ /**
35
+ * 获取缓存大小
36
+ *
37
+ * @returns 缓存中存储的条目数
38
+ */
39
+ size(): number;
40
+ }
41
+ /**
42
+ * 按 \n\n 切分 markdown,但保护不应被切分的结构
43
+ *
44
+ * 切分规则:
45
+ * 1. 按 \n\n(双换行)切分 markdown
46
+ * 2. 保护代码块(```code```):代码块内部的 \n\n 不作为分隔符
47
+ * 3. 保护 HTML 注释(<!-- -->):注释内部的 \n\n 不作为分隔符
48
+ * 4. 保护 HTML 标签(<tag>...</tag>):标签内部的 \n\n 不作为分隔符
49
+ *
50
+ * @param md - 要切分的 markdown 字符串
51
+ * @returns 切分后的 markdown 块数组
52
+ */
53
+ export declare function splitMarkdownIntoBlocks(md: string): string[];
@@ -0,0 +1,355 @@
1
+ function _class_call_check(instance, Constructor) {
2
+ if (!(instance instanceof Constructor)) {
3
+ throw new TypeError("Cannot call a class as a function");
4
+ }
5
+ }
6
+ function _defineProperties(target, props) {
7
+ for(var i = 0; i < props.length; i++){
8
+ var descriptor = props[i];
9
+ descriptor.enumerable = descriptor.enumerable || false;
10
+ descriptor.configurable = true;
11
+ if ("value" in descriptor) descriptor.writable = true;
12
+ Object.defineProperty(target, descriptor.key, descriptor);
13
+ }
14
+ }
15
+ function _create_class(Constructor, protoProps, staticProps) {
16
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
17
+ if (staticProps) _defineProperties(Constructor, staticProps);
18
+ return Constructor;
19
+ }
20
+ function _define_property(obj, key, value) {
21
+ if (key in obj) {
22
+ Object.defineProperty(obj, key, {
23
+ value: value,
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true
27
+ });
28
+ } else {
29
+ obj[key] = value;
30
+ }
31
+ return obj;
32
+ }
33
+ /**
34
+ * Markdown 解析缓存类
35
+ *
36
+ * 使用 Map 存储 markdown 块到 schema 的映射,避免重复解析相同的 markdown 内容
37
+ */ export var ParseCache = /*#__PURE__*/ function() {
38
+ "use strict";
39
+ function ParseCache() {
40
+ _class_call_check(this, ParseCache);
41
+ _define_property(this, "cache", new Map());
42
+ }
43
+ _create_class(ParseCache, [
44
+ {
45
+ /**
46
+ * 从缓存中获取解析结果
47
+ *
48
+ * @param md - markdown 字符串
49
+ * @returns 如果缓存中存在则返回解析结果,否则返回 null
50
+ */ key: "get",
51
+ value: function get(md) {
52
+ return this.cache.get(md) || null;
53
+ }
54
+ },
55
+ {
56
+ /**
57
+ * 将解析结果存入缓存
58
+ *
59
+ * @param md - markdown 字符串
60
+ * @param schema - 解析后的 schema 数组
61
+ */ key: "set",
62
+ value: function set(md, schema) {
63
+ this.cache.set(md, schema);
64
+ }
65
+ },
66
+ {
67
+ /**
68
+ * 检查缓存中是否存在指定的 markdown
69
+ *
70
+ * @param md - markdown 字符串
71
+ * @returns 是否存在
72
+ */ key: "has",
73
+ value: function has(md) {
74
+ return this.cache.has(md);
75
+ }
76
+ },
77
+ {
78
+ /**
79
+ * 清空缓存
80
+ */ key: "clear",
81
+ value: function clear() {
82
+ this.cache.clear();
83
+ }
84
+ },
85
+ {
86
+ /**
87
+ * 获取缓存大小
88
+ *
89
+ * @returns 缓存中存储的条目数
90
+ */ key: "size",
91
+ value: function size() {
92
+ return this.cache.size;
93
+ }
94
+ }
95
+ ]);
96
+ return ParseCache;
97
+ }();
98
+ /**
99
+ * 获取代码块围栏的长度
100
+ */ function getFenceLength(md, start, fenceChar) {
101
+ var length = 0;
102
+ while(start + length < md.length && md[start + length] === fenceChar){
103
+ length++;
104
+ }
105
+ return length;
106
+ }
107
+ /**
108
+ * 查找 HTML 注释的结束位置
109
+ * 返回结束位置(包含 -->),如果未找到则返回 -1
110
+ */ function findHtmlCommentEnd(md, start) {
111
+ if (md.slice(start, start + 4) !== '<!--') {
112
+ return -1;
113
+ }
114
+ for(var i = start + 4; i < md.length - 2; i++){
115
+ if (md.slice(i, i + 3) === '-->') {
116
+ return i + 3;
117
+ }
118
+ }
119
+ return -1;
120
+ }
121
+ /**
122
+ * 查找 HTML 标签信息
123
+ * 返回标签信息对象,如果未找到则返回 null
124
+ */ function findHtmlTagInfo(md, start) {
125
+ if (md[start] !== '<') {
126
+ return null;
127
+ }
128
+ var i = start + 1;
129
+ // 跳过可能的 /(结束标签)
130
+ if (i < md.length && md[i] === '/') {
131
+ return null;
132
+ }
133
+ // 提取标签名
134
+ var tagName = '';
135
+ while(i < md.length && /[a-zA-Z0-9-]/.test(md[i])){
136
+ tagName += md[i];
137
+ i++;
138
+ }
139
+ if (!tagName) {
140
+ return null;
141
+ }
142
+ // 跳过空白和属性,查找 > 或 />
143
+ // 需要处理属性值中的引号
144
+ var inQuotes = false;
145
+ var quoteChar = '';
146
+ while(i < md.length){
147
+ var char = md[i];
148
+ // 处理引号(检查前一个字符是否是转义字符)
149
+ if (char === '"' || char === "'") {
150
+ var prevChar = i > 0 ? md[i - 1] : '';
151
+ if (prevChar !== '\\') {
152
+ if (!inQuotes) {
153
+ inQuotes = true;
154
+ quoteChar = char;
155
+ } else if (char === quoteChar) {
156
+ inQuotes = false;
157
+ quoteChar = '';
158
+ }
159
+ }
160
+ }
161
+ // 只有在引号外部才检查标签结束
162
+ if (!inQuotes) {
163
+ if (char === '>') {
164
+ return {
165
+ name: tagName.toLowerCase(),
166
+ end: i + 1,
167
+ isSelfClosing: false
168
+ };
169
+ }
170
+ if (i < md.length - 1 && md.slice(i, i + 2) === '/>') {
171
+ return {
172
+ name: tagName.toLowerCase(),
173
+ end: i + 2,
174
+ isSelfClosing: true
175
+ };
176
+ }
177
+ }
178
+ i++;
179
+ }
180
+ return null;
181
+ }
182
+ /**
183
+ * 查找 HTML 结束标签的位置
184
+ * 返回结束位置(包含 >),如果未找到则返回 -1
185
+ */ function findHtmlClosingTagEnd(md, start, tagName) {
186
+ if (md.slice(start, start + 2) !== '</') {
187
+ return -1;
188
+ }
189
+ // 检查标签名是否匹配
190
+ var expectedTag = "</".concat(tagName);
191
+ if (md.slice(start, start + expectedTag.length).toLowerCase() !== expectedTag.toLowerCase()) {
192
+ return -1;
193
+ }
194
+ // 查找 >
195
+ var i = start + expectedTag.length;
196
+ while(i < md.length && /\s/.test(md[i])){
197
+ i++;
198
+ }
199
+ if (i < md.length && md[i] === '>') {
200
+ return i + 1;
201
+ }
202
+ return -1;
203
+ }
204
+ /**
205
+ * 检查是否应该保护此分隔符(不切分)
206
+ * 返回 true 如果:
207
+ * 1. HTML 注释后紧跟着表格行
208
+ * 2. 当前块包含表格行,且后面也是表格行
209
+ */ function shouldProtectSeparator(md, separatorIndex, currentBlock) {
210
+ // 跳过 \n\n 和后续的换行符,查找下一行的开始
211
+ var nextLineStart = separatorIndex + 2;
212
+ while(nextLineStart < md.length && md[nextLineStart] === '\n'){
213
+ nextLineStart++;
214
+ }
215
+ // 检查下一行是否以 | 开头(表格行)
216
+ if (nextLineStart >= md.length || md[nextLineStart] !== '|') {
217
+ return false;
218
+ }
219
+ // 情况1:当前块以 HTML 注释结尾,后面是表格行
220
+ var trimmedBlock = currentBlock.trim();
221
+ if (trimmedBlock.endsWith('-->')) {
222
+ var commentStart = trimmedBlock.lastIndexOf('<!--');
223
+ if (commentStart !== -1) {
224
+ return true;
225
+ }
226
+ }
227
+ // 情况2:当前块包含表格行(检查最后几行是否包含表格行)
228
+ var lines = currentBlock.split('\n');
229
+ for(var i = lines.length - 1; i >= Math.max(0, lines.length - 5); i--){
230
+ var line = lines[i].trim();
231
+ if (line.startsWith('|') && line.endsWith('|')) {
232
+ return true;
233
+ }
234
+ }
235
+ return false;
236
+ }
237
+ /**
238
+ * 按 \n\n 切分 markdown,但保护不应被切分的结构
239
+ *
240
+ * 切分规则:
241
+ * 1. 按 \n\n(双换行)切分 markdown
242
+ * 2. 保护代码块(```code```):代码块内部的 \n\n 不作为分隔符
243
+ * 3. 保护 HTML 注释(<!-- -->):注释内部的 \n\n 不作为分隔符
244
+ * 4. 保护 HTML 标签(<tag>...</tag>):标签内部的 \n\n 不作为分隔符
245
+ *
246
+ * @param md - 要切分的 markdown 字符串
247
+ * @returns 切分后的 markdown 块数组
248
+ */ export function splitMarkdownIntoBlocks(md) {
249
+ if (!md) {
250
+ return [];
251
+ }
252
+ var blocks = [];
253
+ var currentBlock = '';
254
+ var i = 0;
255
+ var inCodeBlock = false;
256
+ var codeBlockFence = '';
257
+ var inHtmlTag = false;
258
+ var htmlTagName = '';
259
+ while(i < md.length){
260
+ var char = md[i];
261
+ var nextChar = i + 1 < md.length ? md[i + 1] : null;
262
+ // 检测代码块开始:``` 或 ~~~
263
+ if (!inCodeBlock && !inHtmlTag && (char === '`' || char === '~')) {
264
+ var fenceLength = getFenceLength(md, i, char);
265
+ if (fenceLength >= 3) {
266
+ inCodeBlock = true;
267
+ codeBlockFence = char.repeat(fenceLength);
268
+ currentBlock += codeBlockFence;
269
+ i += fenceLength;
270
+ continue;
271
+ }
272
+ }
273
+ // 检测代码块结束
274
+ if (inCodeBlock && md.slice(i, i + codeBlockFence.length) === codeBlockFence) {
275
+ currentBlock += codeBlockFence;
276
+ i += codeBlockFence.length;
277
+ inCodeBlock = false;
278
+ codeBlockFence = '';
279
+ continue;
280
+ }
281
+ // 检测 HTML 注释开始:<!--
282
+ if (!inCodeBlock && !inHtmlTag && md.slice(i, i + 4) === '<!--') {
283
+ var commentEnd = findHtmlCommentEnd(md, i);
284
+ if (commentEnd > i) {
285
+ currentBlock += md.slice(i, commentEnd);
286
+ i = commentEnd;
287
+ continue;
288
+ }
289
+ }
290
+ // 检测 HTML 标签开始:<tag
291
+ if (!inCodeBlock && !inHtmlTag && char === '<') {
292
+ var tagInfo = findHtmlTagInfo(md, i);
293
+ if (tagInfo) {
294
+ if (tagInfo.isSelfClosing) {
295
+ // 自闭合标签,直接添加并跳过
296
+ currentBlock += md.slice(i, tagInfo.end);
297
+ i = tagInfo.end;
298
+ continue;
299
+ } else {
300
+ // 开始标签,查找对应的结束标签
301
+ inHtmlTag = true;
302
+ htmlTagName = tagInfo.name;
303
+ currentBlock += md.slice(i, tagInfo.end);
304
+ i = tagInfo.end;
305
+ continue;
306
+ }
307
+ }
308
+ }
309
+ // 检测 HTML 标签结束:</tag>
310
+ if (inHtmlTag && md.slice(i, i + 2) === '</') {
311
+ var closingTagEnd = findHtmlClosingTagEnd(md, i, htmlTagName);
312
+ if (closingTagEnd > i) {
313
+ currentBlock += md.slice(i, closingTagEnd);
314
+ i = closingTagEnd;
315
+ inHtmlTag = false;
316
+ htmlTagName = '';
317
+ continue;
318
+ }
319
+ }
320
+ // 检测块分隔符 \n\n(仅在代码块、HTML 注释和 HTML 标签外部)
321
+ if (!inCodeBlock && !inHtmlTag && char === '\n' && nextChar === '\n') {
322
+ // 检查是否应该保护此分隔符(HTML 注释后跟着表格,或表格行之间)
323
+ if (shouldProtectSeparator(md, i, currentBlock)) {
324
+ // 不切分,继续添加到当前块
325
+ currentBlock += '\n\n';
326
+ i += 2;
327
+ while(i < md.length && md[i] === '\n'){
328
+ currentBlock += '\n';
329
+ i++;
330
+ }
331
+ continue;
332
+ }
333
+ if (currentBlock.trim().length > 0) {
334
+ blocks.push(currentBlock.trim());
335
+ }
336
+ currentBlock = '';
337
+ // 跳过连续的换行符
338
+ i += 2;
339
+ while(i < md.length && md[i] === '\n'){
340
+ i++;
341
+ }
342
+ continue;
343
+ }
344
+ // 普通字符,添加到当前块
345
+ currentBlock += char;
346
+ i++;
347
+ }
348
+ // 处理最后一个块
349
+ if (currentBlock.trim().length > 0) {
350
+ blocks.push(currentBlock.trim());
351
+ }
352
+ return blocks.filter(function(block) {
353
+ return block.trim().length > 0;
354
+ });
355
+ }
@@ -59,30 +59,6 @@ function _object_spread(target) {
59
59
  }
60
60
  return target;
61
61
  }
62
- function ownKeys(object, enumerableOnly) {
63
- var keys = Object.keys(object);
64
- if (Object.getOwnPropertySymbols) {
65
- var symbols = Object.getOwnPropertySymbols(object);
66
- if (enumerableOnly) {
67
- symbols = symbols.filter(function(sym) {
68
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
69
- });
70
- }
71
- keys.push.apply(keys, symbols);
72
- }
73
- return keys;
74
- }
75
- function _object_spread_props(target, source) {
76
- source = source != null ? source : {};
77
- if (Object.getOwnPropertyDescriptors) {
78
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
79
- } else {
80
- ownKeys(Object(source)).forEach(function(key) {
81
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
82
- });
83
- }
84
- return target;
85
- }
86
62
  function _to_consumable_array(arr) {
87
63
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
88
64
  }
@@ -213,18 +189,12 @@ import mdastParser from "./remarkParse";
213
189
  // 如果 HTML 注释不是代码块元数据注释,但包含 JSON 对象属性(如对齐注释),
214
190
  // 应该跳过注释本身,但将属性应用到下一个元素
215
191
  if (isHtmlComment && !isOtherPropsComment && htmlCommentProps && Object.keys(htmlCommentProps).length > 0) {
216
- if (!Array.isArray(htmlCommentProps)) {
217
- // 将对齐注释等非代码块元数据注释的属性存储到 contextProps 中,供下一个元素使用
218
- contextProps = _object_spread({}, contextProps, htmlCommentProps);
219
- // 同时将属性作为 config 传递,以便 applyContextPropsAndConfig 设置 otherProps
220
- config = _object_spread({}, config, htmlCommentProps, contextProps);
221
- // 跳过 HTML 注释本身,避免生成独立的 HTML 代码节点
222
- return "continue";
223
- } else {
224
- config = _object_spread_props(_object_spread({}, config), {
225
- config: _to_consumable_array((config === null || config === void 0 ? void 0 : config.config) || []).concat(_to_consumable_array(htmlCommentProps))
226
- });
227
- }
192
+ // 将对齐注释等非代码块元数据注释的属性存储到 contextProps 中,供下一个元素使用
193
+ contextProps = _object_spread({}, contextProps, htmlCommentProps);
194
+ // 同时将属性作为 config 传递,以便 applyContextPropsAndConfig 设置 otherProps
195
+ config = _object_spread({}, config, htmlCommentProps);
196
+ // 跳过 HTML 注释本身,避免生成独立的 HTML 代码节点
197
+ return "continue";
228
198
  }
229
199
  // 如果当前元素应该使用 contextProps 中的属性作为 config(用于设置 otherProps)
230
200
  // 这主要针对对齐注释等场景,需要同时设置 contextProps 和 otherProps
@@ -305,7 +305,7 @@ import { getPointStrOffset, getSelectionFromDomSelection } from "../../utils/edi
305
305
  key: "comment",
306
306
  className: classnames("".concat(baseClassName, "-item"), hashId),
307
307
  onClick: function() {
308
- var _i18n_locale;
308
+ var _i18n_locale, _editorProps_comment, _i18n_locale1;
309
309
  if (typeof window === 'undefined') return;
310
310
  var domSelection = window.getSelection();
311
311
  var editor = markdownEditorRef.current;
@@ -376,6 +376,7 @@ import { getPointStrOffset, getSelectionFromDomSelection } from "../../utils/edi
376
376
  height: 100,
377
377
  resize: 'none'
378
378
  },
379
+ placeholder: (editorProps === null || editorProps === void 0 ? void 0 : (_editorProps_comment = editorProps.comment) === null || _editorProps_comment === void 0 ? void 0 : _editorProps_comment.placeholder) || (editorProps === null || editorProps === void 0 ? void 0 : editorProps.titlePlaceholderContent) || ((_i18n_locale1 = i18n.locale) === null || _i18n_locale1 === void 0 ? void 0 : _i18n_locale1.inputPlaceholder) || '请输入内容...',
379
380
  onChange: function(e) {
380
381
  comment.content = e.target.value;
381
382
  }
@@ -280,6 +280,11 @@ export type MarkdownEditorProps = {
280
280
  onEdit?: (id: string | number, comment: CommentDataType) => void;
281
281
  deleteConfirmText?: string;
282
282
  mentionsPlaceholder?: string;
283
+ /**
284
+ * 评论输入框占位符
285
+ * @description 评论输入框的占位符文本,如果不提供则使用 titlePlaceholderContent
286
+ */
287
+ placeholder?: string;
283
288
  listItemRender?: (defaultDom: {
284
289
  checkbox: React.JSX.Element | null;
285
290
  mentionsUser: React.JSX.Element | null;
@@ -254,6 +254,7 @@ import React, { useCallback, useContext, useEffect, useImperativeHandle, useMemo
254
254
  import { useRefFunction } from "../Hooks/useRefFunction";
255
255
  import { BaseMarkdownEditor } from "../MarkdownEditor";
256
256
  import { upLoadFileToServer } from "./AttachmentButton";
257
+ import { isMobileDevice } from "./AttachmentButton/utils";
257
258
  import { AttachmentFileList } from "./AttachmentButton/AttachmentFileList";
258
259
  import { getFileListFromDataTransferItems } from "./FilePaste";
259
260
  import { useFileUploadManager } from "./FileUploadManager";
@@ -642,6 +643,10 @@ import { useVoiceInputManager } from "./VoiceInputManager";
642
643
  var isEnter = e.key === 'Enter';
643
644
  var isMod = e.ctrlKey || e.metaKey;
644
645
  var isShift = e.shiftKey;
646
+ // 手机端禁用 Enter 键发送
647
+ if (isEnter && !isMod && !isShift && isMobileDevice()) {
648
+ return; // 让编辑器正常处理换行
649
+ }
645
650
  // Enter 发送,Shift+Enter 换行
646
651
  if (!isEnter || isMod) return;
647
652
  if (isShift) return; // Shift+Enter 时让编辑器处理换行
@@ -3,8 +3,8 @@
3
3
  * 提供图表组件相关的 React Hooks
4
4
  * @author Chart Plugin Team
5
5
  */
6
- export type { ChartStatisticConfig, StatisticConfigType } from './useChartStatistic';
7
6
  export { useChartDataFilter } from './useChartDataFilter';
7
+ export type { ChartStatisticConfig, StatisticConfigType, } from './useChartStatistic';
8
8
  export { useChartStatistics } from './useChartStatistics';
9
9
  export { useChartTheme } from './useChartTheme';
10
10
  export { useResponsiveSize } from './useResponsiveSize';
@@ -304,4 +304,4 @@ export declare const isConfigEqual: (config1: any, config2: any) => boolean;
304
304
  * @since 1.0.0
305
305
  */
306
306
  export declare const hexToRgba: (hex: string, alpha: number) => string;
307
- export { registerChartComponents, registerLineChartComponents, registerBarChartComponents, } from './utils/registerChart';
307
+ export { registerBarChartComponents, registerChartComponents, registerLineChartComponents, } from './utils/registerChart';
@@ -462,4 +462,4 @@ var intl = new Intl.NumberFormat('en-US', {
462
462
  return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(a, ")");
463
463
  };
464
464
  // 导出 Chart.js 注册相关函数
465
- export { registerChartComponents, registerLineChartComponents, registerBarChartComponents } from "./utils/registerChart";
465
+ export { registerBarChartComponents, registerChartComponents, registerLineChartComponents } from "./utils/registerChart";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.24.0",
3
+ "version": "2.24.1",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",