@ant-design/agentic-ui 2.29.59 → 2.30.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.
Files changed (99) hide show
  1. package/dist/Bubble/List/index.d.ts +11 -0
  2. package/dist/Bubble/List/index.js +13 -1
  3. package/dist/Bubble/MessagesContent/EXCEPTION.js +11 -2
  4. package/dist/Bubble/MessagesContent/MarkdownPreview.js +34 -4
  5. package/dist/Bubble/MessagesContent/index.js +39 -10
  6. package/dist/Bubble/MessagesContent/style.js +55 -22
  7. package/dist/Bubble/UserBubble.js +3 -1
  8. package/dist/Bubble/type.d.ts +11 -0
  9. package/dist/Hooks/useLanguage.d.ts +1 -0
  10. package/dist/I18n/locales.d.ts +1 -0
  11. package/dist/I18n/locales.js +5 -3
  12. package/dist/MarkdownEditor/BaseMarkdownEditor.js +37 -5
  13. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiTaskBlock.d.ts +4 -0
  14. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiTaskBlock.js +74 -0
  15. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiToolUseBarBlock.d.ts +4 -0
  16. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiToolUseBarBlock.js +114 -0
  17. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +20 -0
  18. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +169 -0
  19. package/dist/MarkdownEditor/editor/elements/Table/EditableTable.d.ts +11 -0
  20. package/dist/MarkdownEditor/editor/elements/Table/EditableTable.js +207 -0
  21. package/dist/MarkdownEditor/editor/elements/Table/Table.js +10 -276
  22. package/dist/MarkdownEditor/editor/elements/Table/TableCellIndex/index.js +7 -227
  23. package/dist/MarkdownEditor/editor/elements/Table/TableCellIndexSpacer/index.js +20 -229
  24. package/dist/MarkdownEditor/editor/elements/Table/commands/tableCommands.d.ts +9 -0
  25. package/dist/MarkdownEditor/editor/elements/Table/commands/tableCommands.js +242 -0
  26. package/dist/MarkdownEditor/editor/elements/Table/utils/editableTableWidth.d.ts +20 -0
  27. package/dist/MarkdownEditor/editor/elements/Table/utils/editableTableWidth.js +60 -0
  28. package/dist/MarkdownEditor/editor/elements/Table/utils/useEditableTableColWidths.d.ts +6 -0
  29. package/dist/MarkdownEditor/editor/elements/Table/utils/useEditableTableColWidths.js +20 -0
  30. package/dist/MarkdownEditor/editor/elements/Table/utils/useEditableTableContentWidth.d.ts +10 -0
  31. package/dist/MarkdownEditor/editor/elements/Table/utils/useEditableTableContentWidth.js +103 -0
  32. package/dist/MarkdownEditor/editor/elements/index.js +7 -0
  33. package/dist/MarkdownEditor/editor/parser/parse/parseCode.js +33 -2
  34. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +3 -0
  35. package/dist/MarkdownEditor/editor/plugins/handlePaste.js +4 -1
  36. package/dist/MarkdownEditor/plugin.d.ts +15 -0
  37. package/dist/MarkdownEditor/style.js +258 -326
  38. package/dist/MarkdownEditor/types.d.ts +14 -0
  39. package/dist/MarkdownInputField/AttachmentButton/AttachmentButtonPopover.js +1 -1
  40. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +2 -2
  41. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +11 -8
  42. package/dist/MarkdownInputField/AttachmentButton/index.js +7 -2
  43. package/dist/MarkdownInputField/AttachmentButton/types.d.ts +5 -1
  44. package/dist/MarkdownInputField/AttachmentButton/utils.d.ts +7 -0
  45. package/dist/MarkdownInputField/AttachmentButton/utils.js +9 -1
  46. package/dist/MarkdownInputField/FileMapView/FileMapViewItem.js +10 -5
  47. package/dist/MarkdownInputField/FileUploadManager/index.d.ts +9 -0
  48. package/dist/MarkdownInputField/FileUploadManager/index.js +20 -4
  49. package/dist/MarkdownInputField/MarkdownInputField.js +5 -3
  50. package/dist/MarkdownInputField/SendActions/index.d.ts +9 -0
  51. package/dist/MarkdownInputField/SendActions/index.js +3 -2
  52. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldRefs.js +10 -3
  53. package/dist/MarkdownInputField/utils/renderHelpers.d.ts +8 -1
  54. package/dist/MarkdownInputField/utils/renderHelpers.js +5 -1
  55. package/dist/MarkdownRenderer/AnimationText.d.ts +19 -0
  56. package/dist/MarkdownRenderer/AnimationText.js +226 -0
  57. package/dist/MarkdownRenderer/CharacterQueue.d.ts +36 -0
  58. package/dist/MarkdownRenderer/CharacterQueue.js +188 -0
  59. package/dist/MarkdownRenderer/MarkdownRenderer.d.ts +13 -0
  60. package/dist/MarkdownRenderer/MarkdownRenderer.js +362 -0
  61. package/dist/MarkdownRenderer/index.d.ts +11 -0
  62. package/dist/MarkdownRenderer/index.js +9 -0
  63. package/dist/MarkdownRenderer/renderers/AgenticUiTaskBlockRenderer.d.ts +6 -0
  64. package/dist/MarkdownRenderer/renderers/AgenticUiTaskBlockRenderer.js +66 -0
  65. package/dist/MarkdownRenderer/renderers/AgenticUiToolUseBarBlockRenderer.d.ts +6 -0
  66. package/dist/MarkdownRenderer/renderers/AgenticUiToolUseBarBlockRenderer.js +134 -0
  67. package/dist/MarkdownRenderer/renderers/ChartRenderer.d.ts +12 -0
  68. package/dist/MarkdownRenderer/renderers/ChartRenderer.js +395 -0
  69. package/dist/MarkdownRenderer/renderers/CodeRenderer.d.ts +7 -0
  70. package/dist/MarkdownRenderer/renderers/CodeRenderer.js +218 -0
  71. package/dist/MarkdownRenderer/renderers/MermaidRenderer.d.ts +7 -0
  72. package/dist/MarkdownRenderer/renderers/MermaidRenderer.js +43 -0
  73. package/dist/MarkdownRenderer/renderers/SchemaRenderer.d.ts +15 -0
  74. package/dist/MarkdownRenderer/renderers/SchemaRenderer.js +115 -0
  75. package/dist/MarkdownRenderer/renderers/index.d.ts +4 -0
  76. package/dist/MarkdownRenderer/renderers/index.js +4 -0
  77. package/dist/MarkdownRenderer/style.d.ts +16 -0
  78. package/dist/MarkdownRenderer/style.js +47 -0
  79. package/dist/MarkdownRenderer/types.d.ts +74 -0
  80. package/dist/MarkdownRenderer/types.js +1 -0
  81. package/dist/MarkdownRenderer/useMarkdownToReact.d.ts +23 -0
  82. package/dist/MarkdownRenderer/useMarkdownToReact.js +1241 -0
  83. package/dist/MarkdownRenderer/useStreaming.d.ts +29 -0
  84. package/dist/MarkdownRenderer/useStreaming.js +399 -0
  85. package/dist/Plugins/chart/AreaChart/index.js +4 -2
  86. package/dist/Plugins/chart/ChartRender.js +1 -0
  87. package/dist/Plugins/chart/LineChart/index.js +4 -2
  88. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +8 -0
  89. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.js +31 -6
  90. package/dist/Plugins/chart/index.js +3 -1
  91. package/dist/Plugins/mermaid/style.js +0 -3
  92. package/dist/TaskList/TaskList.js +3 -12
  93. package/dist/TaskList/components/TaskListItem.js +3 -12
  94. package/dist/ThoughtChainList/ThoughtChainListItem.js +2 -4
  95. package/dist/ThoughtChainList/index.js +4 -21
  96. package/dist/ToolUseBarThink/index.js +20 -59
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.js +2 -0
  99. package/package.json +2 -1
@@ -4,6 +4,7 @@ import React from 'react';
4
4
  import { BaseEditor, Editor, Selection } from 'slate';
5
5
  import { HistoryEditor } from 'slate-history';
6
6
  import { ReactEditor, RenderElementProps } from 'slate-react';
7
+ import type { RenderMode } from '../MarkdownRenderer/types';
7
8
  import { TagPopupProps } from './editor/elements/TagPopup';
8
9
  import { EditorStore } from './editor/store';
9
10
  import { InsertAutocompleteProps } from './editor/tools/InsertAutocomplete';
@@ -613,4 +614,17 @@ export type MarkdownEditorProps = {
613
614
  * @description 配置附件上传功能
614
615
  */
615
616
  attachment?: Record<string, unknown>;
617
+ /**
618
+ * 渲染模式
619
+ * @description 仅在 readonly 模式下生效
620
+ * - 'slate': 使用 Slate 编辑器渲染(默认,向后兼容)
621
+ * - 'markdown': 使用轻量 MarkdownRenderer 渲染(无 Slate 实例,性能更优)
622
+ * @default 'slate'
623
+ */
624
+ renderMode?: RenderMode;
625
+ /**
626
+ * 与 `renderMode` 等价,兼容部分协议或查询参数命名(如 `renderType=markdown`)
627
+ * @description 当同时传入时,`renderMode` 优先
628
+ */
629
+ renderType?: RenderMode;
616
630
  };
@@ -140,7 +140,7 @@ export var SupportedFileFormats = {
140
140
  ]
141
141
  }
142
142
  };
143
- var DEFAULT_FORMAT_MESSAGE = '支持上传文件,每个文件不超过 ${maxSize},支持 ${extensions}等格式。';
143
+ var DEFAULT_FORMAT_MESSAGE = '每个文件不超过 ${maxSize},支持 ${extensions}等格式。';
144
144
  var buildFormatMessage = function buildFormatMessage(format, locale) {
145
145
  var _ref;
146
146
  var _format_extensions;
@@ -261,8 +261,8 @@ var IMAGE_PREVIEW_CONFIG = {
261
261
  export var AttachmentFileIcon = function AttachmentFileIcon(props) {
262
262
  var _file_type;
263
263
  var file = props.file, className = props.className;
264
- // 上传中状态
265
- if (file.status === 'uploading') {
264
+ // 上传中状态(兼容 pending)
265
+ if (file.status === 'uploading' || file.status === 'pending') {
266
266
  return /*#__PURE__*/ React.createElement(FileUploadingSpin, null);
267
267
  }
268
268
  // 错误状态
@@ -17,7 +17,7 @@ import classNames from "clsx";
17
17
  import { motion } from "framer-motion";
18
18
  import React, { useContext } from "react";
19
19
  import { I18nContext } from "../../../I18n";
20
- import { isFileMetaPlaceholderState, kbToSize } from "../utils";
20
+ import { isAttachmentFileLoading, isFileMetaPlaceholderState, kbToSize } from "../utils";
21
21
  import { AttachmentFileIcon, FileMetaPlaceholder } from "./AttachmentFileIcon";
22
22
  var getFileNameWithoutExtension = function getFileNameWithoutExtension(fileName) {
23
23
  return fileName.split('.').slice(0, -1).join('.');
@@ -27,7 +27,7 @@ var getFileExtension = function getFileExtension(fileName) {
27
27
  };
28
28
  var FileIcon = function FileIcon(param) {
29
29
  var file = param.file, prefixCls = param.prefixCls, hashId = param.hashId;
30
- var status = file.status || 'done';
30
+ var status = (file.status || 'done') === 'pending' ? 'uploading' : file.status || 'done';
31
31
  var iconMap = {
32
32
  uploading: /*#__PURE__*/ React.createElement("div", {
33
33
  className: classNames("".concat(prefixCls, "-uploading-icon"), hashId)
@@ -50,9 +50,10 @@ var FileSizeInfo = function FileSizeInfo(param) {
50
50
  var baseClassName = classNames("".concat(prefixCls, "-file-size"), hashId);
51
51
  var statusContentMap = {
52
52
  uploading: (locale === null || locale === void 0 ? void 0 : locale.uploading) || '上传中...',
53
+ pending: (locale === null || locale === void 0 ? void 0 : locale.uploading) || '上传中...',
53
54
  error: /*#__PURE__*/ React.createElement("div", {
54
55
  className: classNames(baseClassName, "".concat(prefixCls, "-file-size-error"))
55
- }, (locale === null || locale === void 0 ? void 0 : locale.uploadFailed) || '上传失败'),
56
+ }, file.errorMessage || (locale === null || locale === void 0 ? void 0 : locale.uploadFailed) || '上传失败'),
56
57
  done: function() {
57
58
  var fileExtension = getFileExtension(file.name);
58
59
  var fileSize = file.size ? kbToSize(file.size / 1024) : '';
@@ -104,14 +105,16 @@ export var AttachmentFileListItem = function AttachmentFileListItem(param) {
104
105
  var file = param.file, prefixCls = param.prefixCls, hashId = param.hashId, onPreview = param.onPreview, onRetry = param.onRetry, onDelete = param.onDelete, className = param.className;
105
106
  var locale = useContext(I18nContext).locale;
106
107
  var isErrorStatus = file.status === 'error';
108
+ var isSizeExceededError = isErrorStatus && file.errorCode === 'FILE_SIZE_EXCEEDED';
109
+ var canRetry = isErrorStatus && !isSizeExceededError;
107
110
  var isDoneStatus = file.status === 'done';
108
- var canDelete = file.status !== 'uploading';
111
+ var canDelete = !isAttachmentFileLoading(file.status);
109
112
  var handleFileClick = function handleFileClick() {
110
113
  if (!isDoneStatus) return;
111
114
  onPreview === null || onPreview === void 0 ? void 0 : onPreview(file);
112
115
  };
113
116
  var handleRetryClick = function handleRetryClick() {
114
- if (!isErrorStatus) return;
117
+ if (!canRetry) return;
115
118
  onRetry === null || onRetry === void 0 ? void 0 : onRetry(file);
116
119
  };
117
120
  var handleDeleteClick = function handleDeleteClick(e) {
@@ -119,15 +122,15 @@ export var AttachmentFileListItem = function AttachmentFileListItem(param) {
119
122
  onDelete(file);
120
123
  };
121
124
  // 有 status 但无 url/previewUrl:文件内容未拿到,展示大小与格式占位块
122
- if (file.status !== undefined && file.status !== null && !file.url && !file.previewUrl) {
125
+ if (isFileMetaPlaceholderState(file)) {
123
126
  return /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
124
127
  file: file,
125
128
  className: className
126
129
  });
127
130
  }
128
131
  return /*#__PURE__*/ React.createElement(Tooltip, {
129
- title: (locale === null || locale === void 0 ? void 0 : locale.clickToRetry) || '点击重试',
130
- open: isErrorStatus ? undefined : false
132
+ title: canRetry ? (locale === null || locale === void 0 ? void 0 : locale.clickToRetry) || '点击重试' : undefined,
133
+ open: canRetry ? undefined : false
131
134
  }, /*#__PURE__*/ React.createElement(motion.div, {
132
135
  variants: ANIMATION_VARIANTS,
133
136
  onClick: handleFileClick,
@@ -166,7 +166,7 @@ var DEFAULT_MESSAGES = {
166
166
  return "至少需要上传 ".concat(count, " 个文件");
167
167
  },
168
168
  fileSizeExceeded: function fileSizeExceeded(size) {
169
- return "文件大小超过 ".concat(size, " KB");
169
+ return "超过 ".concat(size, " KB");
170
170
  }
171
171
  };
172
172
  var waitTime = function waitTime(ms) {
@@ -271,11 +271,12 @@ var handleUploadSuccess = function handleUploadSuccess(file, url, map, props) {
271
271
  };
272
272
  var handleUploadError = function handleUploadError(file, errorMsg, map, props) {
273
273
  file.status = 'error';
274
+ if (errorMsg !== null) file.errorMessage = errorMsg;
274
275
  updateFileMap(map, file, props.onFileMapChange);
275
276
  };
276
277
  var processFile = function processFile(file, index, map, props) {
277
278
  return _async_to_generator(function() {
278
- var _ref, url, isSuccess, errorMsg, error, errorMessage;
279
+ var maxSizeKb, raw, _ref, url, isSuccess, errorMsg, error, errorMessage;
279
280
  return _ts_generator(this, function(_state) {
280
281
  switch(_state.label){
281
282
  case 0:
@@ -286,6 +287,10 @@ var processFile = function processFile(file, index, map, props) {
286
287
  case 1:
287
288
  _state.sent();
288
289
  if (!validateFileSize(file, props)) {
290
+ maxSizeKb = Math.round((props.maxFileSize || 0) / 1024);
291
+ raw = getLocaleMessage(props.locale, 'markdownInput.fileSizeExceeded', DEFAULT_MESSAGES.fileSizeExceeded(maxSizeKb));
292
+ file.errorMessage = raw.includes('${maxSize}') ? raw.replace(/\$\{maxSize\}/g, String(maxSizeKb)) : raw;
293
+ file.errorCode = 'FILE_SIZE_EXCEEDED';
289
294
  file.status = 'error';
290
295
  updateFileMap(map, file, props.onFileMapChange);
291
296
  return [
@@ -13,10 +13,14 @@ export type UploadResponse = {
13
13
  };
14
14
  export type AttachmentFile = File & {
15
15
  url?: string;
16
- status?: 'error' | 'uploading' | 'done';
16
+ status?: 'error' | 'uploading' | 'pending' | 'done';
17
17
  uuid?: string;
18
18
  size?: number | null;
19
19
  previewUrl?: string;
20
+ /** 错误信息(如文件超限、上传失败等),在 status 为 error 时展示 */
21
+ errorMessage?: string | null;
22
+ /** 错误类型,如 FILE_SIZE_EXCEEDED 表示因大小超限不可重试 */
23
+ errorCode?: string | null;
20
24
  /** 上传响应数据(使用 uploadWithResponse 时会填充此字段) */
21
25
  uploadResponse?: UploadResponse;
22
26
  };
@@ -40,6 +40,13 @@ export declare const isMediaFile: (file: File) => boolean;
40
40
  /**
41
41
  * 是否为「仅元信息占位」状态:有 status 但无 url/previewUrl,内容未拿到时整行以 FileMetaPlaceholder 风格展示
42
42
  */
43
+ export declare const isAttachmentFileLoading: (status?: string | null) => boolean;
44
+ /**
45
+ * 是否应该展示 FileMetaPlaceholder:
46
+ * - 有状态
47
+ * - 非 loading(uploading/pending)
48
+ * - 且没有可预览 URL
49
+ */
43
50
  export declare const isFileMetaPlaceholderState: (file: File & {
44
51
  status?: string;
45
52
  url?: string;
@@ -109,8 +109,16 @@ var hasVideoExtension = function hasVideoExtension(pathOrName) {
109
109
  };
110
110
  /**
111
111
  * 是否为「仅元信息占位」状态:有 status 但无 url/previewUrl,内容未拿到时整行以 FileMetaPlaceholder 风格展示
112
+ */ export var isAttachmentFileLoading = function isAttachmentFileLoading(status) {
113
+ return status === 'uploading' || status === 'pending';
114
+ };
115
+ /**
116
+ * 是否应该展示 FileMetaPlaceholder:
117
+ * - 有状态
118
+ * - 非 loading(uploading/pending)
119
+ * - 且没有可预览 URL
112
120
  */ export var isFileMetaPlaceholderState = function isFileMetaPlaceholderState(file) {
113
- return file.status !== undefined && file.status !== null && !file.url && !file.previewUrl;
121
+ return file.status !== undefined && file.status !== null && !isAttachmentFileLoading(file.status) && !file.url && !file.previewUrl;
114
122
  };
115
123
  /**
116
124
  * 设备品牌匹配列表
@@ -117,14 +117,14 @@ import { isFileMetaPlaceholderState, kbToSize } from "../AttachmentButton/utils"
117
117
  var lastDotIndex = fileName.lastIndexOf('.');
118
118
  var displayName = lastDotIndex > 0 ? fileName.slice(0, lastDotIndex) : fileName;
119
119
  var displayExtension = lastDotIndex > 0 && lastDotIndex < fileName.length - 1 ? fileName.slice(lastDotIndex + 1) : '';
120
- // 有 status 但无 url/previewUrl:文件内容未拿到,展示大小与格式占位块
121
- if (file.status !== undefined && file.status !== null && !file.url && !file.previewUrl) {
120
+ // 有 status 但无 url/previewUrl:文件内容未拿到,展示大小与格式占位块(loading 状态除外)
121
+ if (isFileMetaPlaceholderState(file)) {
122
122
  return /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
123
123
  file: file
124
124
  });
125
125
  }
126
126
  return /*#__PURE__*/ React.createElement(Tooltip, {
127
- title: /*#__PURE__*/ React.createElement("div", null, locale === null || locale === void 0 ? void 0 : locale.clickToPreview),
127
+ title: file.status === 'error' && file.errorMessage ? /*#__PURE__*/ React.createElement("div", null, file.errorMessage) : /*#__PURE__*/ React.createElement("div", null, locale === null || locale === void 0 ? void 0 : locale.clickToPreview),
128
128
  placement: "topLeft",
129
129
  arrow: false
130
130
  }, /*#__PURE__*/ React.createElement(motion.div, {
@@ -175,7 +175,12 @@ import { isFileMetaPlaceholderState, kbToSize } from "../AttachmentButton/utils"
175
175
  title: file === null || file === void 0 ? void 0 : file.name
176
176
  }, displayName)), /*#__PURE__*/ React.createElement("div", {
177
177
  className: classNames("".concat(props.prefixCls, "-file-name-extension-container"), props.hashId)
178
- }, /*#__PURE__*/ React.createElement("span", {
178
+ }, file.status === 'error' && file.errorMessage ? /*#__PURE__*/ React.createElement("span", {
179
+ className: classNames("".concat(props.prefixCls, "-file-error-msg"), props.hashId),
180
+ style: {
181
+ color: 'var(--color-red-text-secondary)'
182
+ }
183
+ }, file.errorMessage) : /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("span", {
179
184
  className: classNames("".concat(props.prefixCls, "-file-name-extension"), props.hashId)
180
185
  }, displayExtension), /*#__PURE__*/ React.createElement("span", {
181
186
  className: classNames("".concat(props.prefixCls, "-separator"), props.hashId)
@@ -183,7 +188,7 @@ import { isFileMetaPlaceholderState, kbToSize } from "../AttachmentButton/utils"
183
188
  className: classNames("".concat(props.prefixCls, "-file-size"), props.hashId)
184
189
  }, kbToSize(file.size / 1024)), /*#__PURE__*/ React.createElement("span", {
185
190
  className: classNames("".concat(props.prefixCls, "-separator"), props.hashId)
186
- }, "|"), /*#__PURE__*/ React.createElement("div", null, (file === null || file === void 0 ? void 0 : file.lastModified) ? dayjs(file === null || file === void 0 ? void 0 : file.lastModified).format('HH:mm') : ''))), hovered ? /*#__PURE__*/ React.createElement("div", {
191
+ }, "|"), /*#__PURE__*/ React.createElement("div", null, (file === null || file === void 0 ? void 0 : file.lastModified) ? dayjs(file === null || file === void 0 ? void 0 : file.lastModified).format('HH:mm') : '')))), hovered ? /*#__PURE__*/ React.createElement("div", {
187
192
  className: classNames("".concat(props.prefixCls, "-action-bar"), props.hashId)
188
193
  }, props.customSlot ? /*#__PURE__*/ React.createElement(ActionIconBox, {
189
194
  title: '更多',
@@ -18,6 +18,15 @@ export interface FileUploadManagerReturn {
18
18
  fileMap?: Map<string, AttachmentFile>;
19
19
  /** 文件上传是否完成 */
20
20
  fileUploadDone: boolean;
21
+ /** 文件上传状态 */
22
+ fileUploadStatus: 'uploading' | 'done' | 'error';
23
+ /** 文件上传状态统计 */
24
+ fileUploadSummary: {
25
+ totalCount: number;
26
+ doneCount: number;
27
+ uploadingCount: number;
28
+ errorCount: number;
29
+ };
21
30
  /** 支持的文件格式 */
22
31
  supportedFormat: SupportedFileFormatsType;
23
32
  /** 上传图片 */
@@ -191,10 +191,24 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
191
191
  */ export var useFileUploadManager = function useFileUploadManager(param) {
192
192
  var attachment = param.attachment, fileMap = param.fileMap, onFileMapChange = param.onFileMapChange;
193
193
  var locale = useContext(I18nContext).locale;
194
- // 判断是否所有文件上传完成
195
- var fileUploadDone = (fileMap === null || fileMap === void 0 ? void 0 : fileMap.size) ? Array.from((fileMap === null || fileMap === void 0 ? void 0 : fileMap.values()) || []).every(function(file) {
196
- return file.status === 'done';
197
- }) : true;
194
+ var fileList = Array.from((fileMap === null || fileMap === void 0 ? void 0 : fileMap.values()) || []);
195
+ var uploadingCount = fileList.filter(function(file) {
196
+ return file.status === 'uploading';
197
+ }).length;
198
+ var errorCount = fileList.filter(function(file) {
199
+ return file.status === 'error';
200
+ }).length;
201
+ var totalCount = fileList.length;
202
+ var fileUploadSummary = {
203
+ totalCount: totalCount,
204
+ uploadingCount: uploadingCount,
205
+ errorCount: errorCount,
206
+ // 兜底把未知状态也按完成态处理,避免统计缺口
207
+ doneCount: Math.max(0, totalCount - uploadingCount - errorCount)
208
+ };
209
+ var fileUploadStatus = fileUploadSummary.errorCount > 0 ? 'error' : fileUploadSummary.uploadingCount > 0 ? 'uploading' : 'done';
210
+ // 向后兼容:无文件时视为已完成
211
+ var fileUploadDone = fileUploadSummary.totalCount > 0 ? fileUploadStatus === 'done' : true;
198
212
  // 默认支持的文件格式
199
213
  var supportedFormat = (attachment === null || attachment === void 0 ? void 0 : attachment.supportedFormat) || SupportedFileFormats.image;
200
214
  /**
@@ -507,6 +521,8 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
507
521
  return {
508
522
  fileMap: fileMap,
509
523
  fileUploadDone: fileUploadDone,
524
+ fileUploadStatus: fileUploadStatus,
525
+ fileUploadSummary: fileUploadSummary,
510
526
  supportedFormat: supportedFormat,
511
527
  uploadImage: uploadImage,
512
528
  updateAttachmentFiles: updateAttachmentFiles,
@@ -258,7 +258,7 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
258
258
  attachment: attachment,
259
259
  fileMap: fileMap,
260
260
  onFileMapChange: setFileMap
261
- }), fileUploadDone = _useFileUploadManager.fileUploadDone, supportedFormat = _useFileUploadManager.supportedFormat, uploadImage = _useFileUploadManager.uploadImage, updateAttachmentFiles = _useFileUploadManager.updateAttachmentFiles, handleFileRemoval = _useFileUploadManager.handleFileRemoval, handleFileRetry = _useFileUploadManager.handleFileRetry;
261
+ }), fileUploadDone = _useFileUploadManager.fileUploadDone, fileUploadStatus = _useFileUploadManager.fileUploadStatus, fileUploadSummary = _useFileUploadManager.fileUploadSummary, supportedFormat = _useFileUploadManager.supportedFormat, uploadImage = _useFileUploadManager.uploadImage, updateAttachmentFiles = _useFileUploadManager.updateAttachmentFiles, handleFileRemoval = _useFileUploadManager.handleFileRemoval, handleFileRetry = _useFileUploadManager.handleFileRetry;
262
262
  // 语音输入管理
263
263
  var _useVoiceInputManager = useVoiceInputManager({
264
264
  voiceRecognizer: props.voiceRecognizer,
@@ -322,6 +322,8 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
322
322
  setFileMap: setFileMap,
323
323
  supportedFormat: supportedFormat,
324
324
  fileUploadDone: fileUploadDone,
325
+ fileUploadStatus: fileUploadStatus,
326
+ fileUploadSummary: fileUploadSummary,
325
327
  recording: recording,
326
328
  isLoading: isLoading,
327
329
  collapseSendActions: collapseSendActions,
@@ -473,7 +475,7 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
473
475
  isHover: isHover,
474
476
  isLoading: isLoading,
475
477
  disabled: props.disabled,
476
- fileUploadStatus: fileUploadDone ? 'done' : 'uploading',
478
+ fileUploadStatus: fileUploadStatus,
477
479
  refinePrompt: props.refinePrompt,
478
480
  editorRef: markdownEditorRef,
479
481
  onValueChange: function onValueChange(text) {
@@ -507,7 +509,7 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
507
509
  }, props), {
508
510
  isHover: isHover,
509
511
  isLoading: isLoading,
510
- fileUploadStatus: fileUploadDone ? 'done' : 'uploading'
512
+ fileUploadStatus: fileUploadStatus
511
513
  }))), sendActionsNode) : sendActionsNode))));
512
514
  };
513
515
  MarkdownInputFieldComponent.displayName = 'MarkdownInputField';
@@ -25,6 +25,15 @@ export interface SendActionsProps {
25
25
  isLoading?: boolean;
26
26
  /** 文件上传是否完成 */
27
27
  fileUploadDone?: boolean;
28
+ /** 文件上传状态 */
29
+ fileUploadStatus?: 'uploading' | 'done' | 'error';
30
+ /** 文件上传状态统计 */
31
+ fileUploadSummary?: {
32
+ totalCount: number;
33
+ doneCount: number;
34
+ uploadingCount: number;
35
+ errorCount: number;
36
+ };
28
37
  /** 是否正在录音 */
29
38
  recording?: boolean;
30
39
  /** 是否折叠操作按钮 */
@@ -66,7 +66,7 @@ import { MARKDOWN_INPUT_FIELD_TEST_IDS } from "../testIds";
66
66
  *
67
67
  * @description 封装发送操作相关的按钮,包括附件上传、语音输入、发送按钮等
68
68
  */ export var SendActions = function SendActions(param) {
69
- var attachment = param.attachment, voiceRecognizer = param.voiceRecognizer, value = param.value, disabled = param.disabled, typing = param.typing, isLoading = param.isLoading, _param_fileUploadDone = param.fileUploadDone, fileUploadDone = _param_fileUploadDone === void 0 ? true : _param_fileUploadDone, _param_recording = param.recording, recording = _param_recording === void 0 ? false : _param_recording, _param_collapseSendActions = param.collapseSendActions, collapseSendActions = _param_collapseSendActions === void 0 ? false : _param_collapseSendActions, _param_allowEmptySubmit = param.allowEmptySubmit, allowEmptySubmit = _param_allowEmptySubmit === void 0 ? false : _param_allowEmptySubmit, uploadImage = param.uploadImage, onStartRecording = param.onStartRecording, onStopRecording = param.onStopRecording, onSend = param.onSend, onStop = param.onStop, actionsRender = param.actionsRender, _param_prefixCls = param.prefixCls, prefixCls = _param_prefixCls === void 0 ? 'ant-agentic-md-input-field' : _param_prefixCls, _param_hashId = param.hashId, hashId = _param_hashId === void 0 ? '' : _param_hashId, _param_hasTools = param.hasTools, hasTools = _param_hasTools === void 0 ? false : _param_hasTools, onResize = param.onResize, sendButtonProps = param.sendButtonProps, triggerSendKey = param.triggerSendKey;
69
+ var attachment = param.attachment, voiceRecognizer = param.voiceRecognizer, value = param.value, disabled = param.disabled, typing = param.typing, isLoading = param.isLoading, _param_fileUploadDone = param.fileUploadDone, fileUploadDone = _param_fileUploadDone === void 0 ? true : _param_fileUploadDone, _param_fileUploadStatus = param.fileUploadStatus, fileUploadStatus = _param_fileUploadStatus === void 0 ? fileUploadDone ? 'done' : 'uploading' : _param_fileUploadStatus, fileUploadSummary = param.fileUploadSummary, _param_recording = param.recording, recording = _param_recording === void 0 ? false : _param_recording, _param_collapseSendActions = param.collapseSendActions, collapseSendActions = _param_collapseSendActions === void 0 ? false : _param_collapseSendActions, _param_allowEmptySubmit = param.allowEmptySubmit, allowEmptySubmit = _param_allowEmptySubmit === void 0 ? false : _param_allowEmptySubmit, uploadImage = param.uploadImage, onStartRecording = param.onStartRecording, onStopRecording = param.onStopRecording, onSend = param.onSend, onStop = param.onStop, actionsRender = param.actionsRender, _param_prefixCls = param.prefixCls, prefixCls = _param_prefixCls === void 0 ? 'ant-agentic-md-input-field' : _param_prefixCls, _param_hashId = param.hashId, hashId = _param_hashId === void 0 ? '' : _param_hashId, _param_hasTools = param.hasTools, hasTools = _param_hasTools === void 0 ? false : _param_hasTools, onResize = param.onResize, sendButtonProps = param.sendButtonProps, triggerSendKey = param.triggerSendKey;
70
70
  var fileMap = attachment === null || attachment === void 0 ? void 0 : attachment.fileMap;
71
71
  var defaultActionsLen = [
72
72
  (attachment === null || attachment === void 0 ? void 0 : attachment.enable) ? '()' : null,
@@ -155,7 +155,8 @@ import { MARKDOWN_INPUT_FIELD_TEST_IDS } from "../testIds";
155
155
  onStopRecording: onStopRecording,
156
156
  onSend: onSend,
157
157
  onStop: onStop,
158
- fileUploadStatus: fileUploadDone ? 'done' : 'uploading'
158
+ fileUploadStatus: fileUploadStatus,
159
+ fileUploadSummary: fileUploadSummary
159
160
  }, defaultActions) : defaultActions;
160
161
  return /*#__PURE__*/ React.createElement(RcResizeObserver, {
161
162
  onResize: function onResize1(e) {
@@ -69,6 +69,7 @@ import { useEffect, useImperativeHandle, useRef } from "react";
69
69
  props.value
70
70
  ]);
71
71
  // 通过 ref 暴露编辑器实例,包装 store.setMDContent 以同步 value 状态,确保发送按钮正确响应
72
+ // 使用 Proxy 包装 store,仅覆盖 setMDContent,保留 getMDContent、clearContent、focus 等全部方法
72
73
  useImperativeHandle(props.inputRef, function() {
73
74
  var editor = markdownEditorRef.current;
74
75
  var syncValueAndSetMDContent = function syncValueAndSetMDContent(md, plugins, options) {
@@ -85,10 +86,16 @@ import { useEffect, useImperativeHandle, useRef } from "react";
85
86
  }
86
87
  };
87
88
  }
89
+ var storeProxy = new Proxy(editor.store, {
90
+ get: function get(target, prop) {
91
+ if (prop === 'setMDContent') {
92
+ return syncValueAndSetMDContent;
93
+ }
94
+ return Reflect.get(target, prop);
95
+ }
96
+ });
88
97
  return _object_spread_props(_object_spread({}, editor), {
89
- store: _object_spread_props(_object_spread({}, editor.store), {
90
- setMDContent: syncValueAndSetMDContent
91
- })
98
+ store: storeProxy
92
99
  });
93
100
  }, [
94
101
  props.setValue
@@ -29,6 +29,13 @@ interface UseSendActionsNodeParams {
29
29
  setFileMap?: (fileMap?: Map<string, AttachmentFile>) => void;
30
30
  supportedFormat: AttachmentButtonProps['supportedFormat'];
31
31
  fileUploadDone: boolean;
32
+ fileUploadStatus: 'uploading' | 'done' | 'error';
33
+ fileUploadSummary: {
34
+ totalCount: number;
35
+ doneCount: number;
36
+ uploadingCount: number;
37
+ errorCount: number;
38
+ };
32
39
  recording: boolean;
33
40
  isLoading: boolean;
34
41
  collapseSendActions: boolean;
@@ -45,5 +52,5 @@ interface UseSendActionsNodeParams {
45
52
  /**
46
53
  * SendActions 节点渲染 Hook
47
54
  */
48
- export declare const useSendActionsNode: ({ props: sendProps, fileMap, setFileMap, supportedFormat, fileUploadDone, recording, isLoading, collapseSendActions, uploadImage, startRecording, stopRecording, sendMessage, setIsLoading, onStop, setRightPadding, baseCls, hashId, }: UseSendActionsNodeParams) => React.ReactElement;
55
+ export declare const useSendActionsNode: ({ props: sendProps, fileMap, setFileMap, supportedFormat, fileUploadDone, fileUploadStatus, fileUploadSummary, recording, isLoading, collapseSendActions, uploadImage, startRecording, stopRecording, sendMessage, setIsLoading, onStop, setRightPadding, baseCls, hashId, }: UseSendActionsNodeParams) => React.ReactElement;
49
56
  export {};
@@ -99,7 +99,7 @@ import { MARKDOWN_INPUT_FIELD_TEST_IDS } from "../testIds";
99
99
  /**
100
100
  * SendActions 节点渲染 Hook
101
101
  */ export var useSendActionsNode = function useSendActionsNode(param) {
102
- var sendProps = param.props, fileMap = param.fileMap, setFileMap = param.setFileMap, supportedFormat = param.supportedFormat, fileUploadDone = param.fileUploadDone, recording = param.recording, isLoading = param.isLoading, collapseSendActions = param.collapseSendActions, uploadImage = param.uploadImage, startRecording = param.startRecording, stopRecording = param.stopRecording, sendMessage = param.sendMessage, setIsLoading = param.setIsLoading, onStop = param.onStop, setRightPadding = param.setRightPadding, baseCls = param.baseCls, hashId = param.hashId;
102
+ var sendProps = param.props, fileMap = param.fileMap, setFileMap = param.setFileMap, supportedFormat = param.supportedFormat, fileUploadDone = param.fileUploadDone, fileUploadStatus = param.fileUploadStatus, fileUploadSummary = param.fileUploadSummary, recording = param.recording, isLoading = param.isLoading, collapseSendActions = param.collapseSendActions, uploadImage = param.uploadImage, startRecording = param.startRecording, stopRecording = param.stopRecording, sendMessage = param.sendMessage, setIsLoading = param.setIsLoading, onStop = param.onStop, setRightPadding = param.setRightPadding, baseCls = param.baseCls, hashId = param.hashId;
103
103
  return useMemo(function() {
104
104
  var _sendProps_attachment;
105
105
  return React.createElement(SendActions, {
@@ -117,6 +117,8 @@ import { MARKDOWN_INPUT_FIELD_TEST_IDS } from "../testIds";
117
117
  typing: sendProps.typing,
118
118
  isLoading: isLoading,
119
119
  fileUploadDone: fileUploadDone,
120
+ fileUploadStatus: fileUploadStatus,
121
+ fileUploadSummary: fileUploadSummary,
120
122
  recording: recording,
121
123
  collapseSendActions: collapseSendActions,
122
124
  allowEmptySubmit: sendProps.allowEmptySubmit,
@@ -151,6 +153,8 @@ import { MARKDOWN_INPUT_FIELD_TEST_IDS } from "../testIds";
151
153
  setFileMap,
152
154
  supportedFormat,
153
155
  fileUploadDone,
156
+ fileUploadStatus,
157
+ fileUploadSummary,
154
158
  recording,
155
159
  isLoading,
156
160
  collapseSendActions,
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ export interface AnimationConfig {
3
+ /** 淡入动画持续时间(ms),默认 250 */
4
+ fadeDuration?: number;
5
+ /** 缓动函数,默认 ease-out */
6
+ easing?: string;
7
+ }
8
+ export interface AnimationTextProps {
9
+ children: React.ReactNode;
10
+ animationConfig?: AnimationConfig;
11
+ }
12
+ /**
13
+ * 流式文字淡入动画组件。
14
+ *
15
+ * 采用 opacity + translateY(GPU 硬件加速),清爽流派。
16
+ * 动画结束后通过 animationend 标记 done,仍用 span 包裹以保持布局稳定。
17
+ */
18
+ declare const AnimationText: React.NamedExoticComponent<AnimationTextProps>;
19
+ export default AnimationText;