@ant-design/agentic-ui 2.30.13 → 2.30.15

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 (41) hide show
  1. package/dist/Bubble/AIBubble.js +32 -18
  2. package/dist/Bubble/ContentFilemapView.d.ts +14 -0
  3. package/dist/Bubble/ContentFilemapView.js +95 -0
  4. package/dist/Bubble/UserBubble.js +48 -6
  5. package/dist/Bubble/extractFilemapBlocks.d.ts +17 -0
  6. package/dist/Bubble/extractFilemapBlocks.js +23 -0
  7. package/dist/Bubble/type.d.ts +3 -0
  8. package/dist/Hooks/useLanguage.d.ts +2 -0
  9. package/dist/I18n/locales.d.ts +2 -0
  10. package/dist/I18n/locales.js +7 -3
  11. package/dist/MarkdownEditor/editor/elements/Code/ReadonlyCode.js +1 -1
  12. package/dist/MarkdownEditor/editor/elements/Code/index.js +23 -15
  13. package/dist/MarkdownEditor/editor/parser/constants.d.ts +10 -0
  14. package/dist/MarkdownEditor/editor/parser/constants.js +46 -0
  15. package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.js +3 -1
  16. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +11 -0
  17. package/dist/MarkdownEditor/editor/utils/markdownToHtml.js +6 -4
  18. package/dist/MarkdownInputField/AttachmentButton/AttachmentButtonPopover.d.ts +1 -6
  19. package/dist/MarkdownInputField/AttachmentButton/AttachmentButtonPopover.js +2 -13
  20. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +3 -1
  21. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +2 -1
  22. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.js +6 -1
  23. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +8 -0
  24. package/dist/MarkdownInputField/AttachmentButton/index.d.ts +30 -0
  25. package/dist/MarkdownInputField/AttachmentButton/index.js +22 -6
  26. package/dist/MarkdownInputField/AttachmentButton/utils.d.ts +3 -6
  27. package/dist/MarkdownInputField/FileMapView/FileMapViewItem.js +20 -1
  28. package/dist/MarkdownInputField/FileMapView/index.js +35 -12
  29. package/dist/MarkdownInputField/FileMapView/style.js +6 -0
  30. package/dist/MarkdownInputField/FileUploadManager/index.js +36 -21
  31. package/dist/MarkdownInputField/MarkdownInputField.js +2 -1
  32. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldHandlers.d.ts +1 -0
  33. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldHandlers.js +20 -0
  34. package/dist/MarkdownInputField/style.js +8 -0
  35. package/dist/MarkdownInputField/types/MarkdownInputFieldProps.d.ts +1 -1
  36. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -2
  37. package/dist/MarkdownRenderer/useMarkdownToReact.js +2 -2
  38. package/dist/Plugins/chart/DonutChart/index.js +21 -7
  39. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +4 -0
  40. package/dist/Workspace/Browser/index.js +3 -1
  41. package/package.json +1 -1
@@ -174,7 +174,7 @@ import remarkParse from "remark-parse";
174
174
  import remarkRehype from "remark-rehype";
175
175
  import { unified } from "unified";
176
176
  import { visit } from "unist-util-visit";
177
- import { JINJA_DOLLAR_PLACEHOLDER } from "../parser/constants";
177
+ import { JINJA_DOLLAR_PLACEHOLDER, preprocessNormalizeLeafToContainerDirective } from "../parser/constants";
178
178
  import { remarkDirectiveContainer } from "../parser/remarkDirectiveContainer";
179
179
  import remarkDirectiveContainersOnly from "../parser/remarkDirectiveContainersOnly";
180
180
  import { convertParagraphToImage, fixStrongWithSpecialChars, protectJinjaDollarInText } from "../parser/remarkParse";
@@ -462,7 +462,7 @@ var createMarkdownProcessor = function createMarkdownProcessor(plugins, config)
462
462
  * @throws {Error} 当转换过程中发生错误时返回空字符串
463
463
  */ export var markdownToHtml = function markdownToHtml(markdown, plugins, config) {
464
464
  return _async_to_generator(function() {
465
- var _file_value, file, htmlContent, error;
465
+ var _file_value, normalizedMarkdown, file, htmlContent, error;
466
466
  return _ts_generator(this, function(_state) {
467
467
  switch(_state.label){
468
468
  case 0:
@@ -472,9 +472,10 @@ var createMarkdownProcessor = function createMarkdownProcessor(plugins, config)
472
472
  ,
473
473
  3
474
474
  ]);
475
+ normalizedMarkdown = preprocessNormalizeLeafToContainerDirective(markdown);
475
476
  return [
476
477
  4,
477
- createMarkdownProcessor(plugins, config).process(markdown)
478
+ createMarkdownProcessor(plugins, config).process(normalizedMarkdown)
478
479
  ];
479
480
  case 1:
480
481
  file = _state.sent();
@@ -530,7 +531,8 @@ var createMarkdownProcessor = function createMarkdownProcessor(plugins, config)
530
531
  */ export var markdownToHtmlSync = function markdownToHtmlSync(markdown, plugins, config) {
531
532
  try {
532
533
  var _file_value;
533
- var file = createMarkdownProcessor(plugins, config).processSync(markdown);
534
+ var normalizedMarkdown = preprocessNormalizeLeafToContainerDirective(markdown);
535
+ var file = createMarkdownProcessor(plugins, config).processSync(normalizedMarkdown);
534
536
  var htmlContent = file && (typeof file === "undefined" ? "undefined" : _type_of(file)) === 'object' && 'value' in file ? String((_file_value = file.value) !== null && _file_value !== void 0 ? _file_value : '') : String(file);
535
537
  return htmlContent.split(JINJA_DOLLAR_PLACEHOLDER).join('$');
536
538
  } catch (error) {
@@ -2,7 +2,6 @@ import React from 'react';
2
2
  import type { LocalKeys } from '../../I18n';
3
3
  export type SupportedFormat = {
4
4
  type: string;
5
- maxSize: number;
6
5
  extensions: string[];
7
6
  icon: React.ReactNode;
8
7
  content?: React.ReactNode;
@@ -12,32 +11,28 @@ export type AttachmentButtonPopoverProps = {
12
11
  supportedFormat?: SupportedFormat;
13
12
  /** 上传图片的处理函数 */
14
13
  uploadImage?: (forGallery?: boolean) => Promise<void>;
15
- /** 国际化文案,可覆盖 I18n 上下文中的配置。支持 `input.openGallery`、`input.openFile`、`input.supportedFormatMessage`(模板变量:${maxSize}、${extensions})等 */
14
+ /** 国际化文案,可覆盖 I18n 上下文中的配置。支持 `input.openGallery`、`input.openFile`、`input.supportedFormatMessage`(模板变量:${extensions})等 */
16
15
  locale?: Partial<LocalKeys>;
17
16
  };
18
17
  export declare const SupportedFileFormats: {
19
18
  image: {
20
19
  icon: React.JSX.Element;
21
20
  type: string;
22
- maxSize: number;
23
21
  extensions: string[];
24
22
  };
25
23
  document: {
26
24
  icon: React.JSX.Element;
27
25
  type: string;
28
- maxSize: number;
29
26
  extensions: string[];
30
27
  };
31
28
  audio: {
32
29
  icon: React.JSX.Element;
33
30
  type: string;
34
- maxSize: number;
35
31
  extensions: string[];
36
32
  };
37
33
  video: {
38
34
  icon: React.JSX.Element;
39
35
  type: string;
40
- maxSize: number;
41
36
  extensions: string[];
42
37
  };
43
38
  };
@@ -77,12 +77,7 @@ import { Button, Modal, Tooltip } from "antd";
77
77
  import React, { useContext, useMemo, useState } from "react";
78
78
  import { useRefFunction } from "../../Hooks/useRefFunction";
79
79
  import { compileTemplate, I18nContext } from "../../I18n";
80
- import { isMobileDevice, isVivoOrOppoDevice, kbToSize } from "./utils";
81
- var FILE_SIZE_UNITS = {
82
- KB: 1024,
83
- MB: 1024 * 1024
84
- };
85
- var DEFAULT_MAX_SIZE = 5000;
80
+ import { isMobileDevice, isVivoOrOppoDevice } from "./utils";
86
81
  var CONTENT_STYLE = {
87
82
  fontSize: 16,
88
83
  lineHeight: '1.5em',
@@ -92,7 +87,6 @@ export var SupportedFileFormats = {
92
87
  image: {
93
88
  icon: /*#__PURE__*/ React.createElement(FileImageOutlined, null),
94
89
  type: '图片',
95
- maxSize: 10 * FILE_SIZE_UNITS.KB,
96
90
  extensions: [
97
91
  'jpg',
98
92
  'jpeg',
@@ -106,7 +100,6 @@ export var SupportedFileFormats = {
106
100
  document: {
107
101
  icon: /*#__PURE__*/ React.createElement(FileTextFilled, null),
108
102
  type: '文档',
109
- maxSize: 10 * FILE_SIZE_UNITS.KB,
110
103
  extensions: [
111
104
  'pdf',
112
105
  'markdown',
@@ -123,7 +116,6 @@ export var SupportedFileFormats = {
123
116
  audio: {
124
117
  icon: /*#__PURE__*/ React.createElement(AudioOutlined, null),
125
118
  type: '音频',
126
- maxSize: 50 * FILE_SIZE_UNITS.KB,
127
119
  extensions: [
128
120
  'mp3',
129
121
  'wav'
@@ -132,7 +124,6 @@ export var SupportedFileFormats = {
132
124
  video: {
133
125
  icon: /*#__PURE__*/ React.createElement(VideoCameraOutlined, null),
134
126
  type: '视频',
135
- maxSize: 100 * FILE_SIZE_UNITS.KB,
136
127
  extensions: [
137
128
  'mp4',
138
129
  'avi',
@@ -140,15 +131,13 @@ export var SupportedFileFormats = {
140
131
  ]
141
132
  }
142
133
  };
143
- var DEFAULT_FORMAT_MESSAGE = '每个文件不超过 ${maxSize},支持 ${extensions}等格式。';
134
+ var DEFAULT_FORMAT_MESSAGE = '支持 ${extensions}等格式。';
144
135
  var buildFormatMessage = function buildFormatMessage(format, locale) {
145
136
  var _ref;
146
137
  var _format_extensions;
147
- var maxSize = kbToSize(format.maxSize || DEFAULT_MAX_SIZE);
148
138
  var extensions = ((_format_extensions = format.extensions) === null || _format_extensions === void 0 ? void 0 : _format_extensions.join(', ')) || '';
149
139
  var template = (_ref = locale === null || locale === void 0 ? void 0 : locale['input.supportedFormatMessage']) !== null && _ref !== void 0 ? _ref : DEFAULT_FORMAT_MESSAGE;
150
140
  return compileTemplate(template, {
151
- maxSize: maxSize,
152
141
  extensions: extensions
153
142
  });
154
143
  };
@@ -213,6 +213,7 @@ var VideoThumbnail = function VideoThumbnail(param) {
213
213
  return /*#__PURE__*/ React.createElement(Tooltip, {
214
214
  title: file.name
215
215
  }, /*#__PURE__*/ React.createElement("div", {
216
+ "data-testid": "file-meta-placeholder",
216
217
  className: className,
217
218
  style: _object_spread({
218
219
  height: 48,
@@ -225,7 +226,8 @@ var VideoThumbnail = function VideoThumbnail(param) {
225
226
  color: 'var(--color-text-tertiary, rgba(0,0,0,0.45))',
226
227
  lineHeight: 1.2,
227
228
  overflow: 'hidden',
228
- flex: 1,
229
+ // 占位块不应在 flex 容器中自动拉伸为整行宽度
230
+ flex: '0 0 auto',
229
231
  minWidth: 80,
230
232
  padding: 'var(--padding-1x) var(--padding-2x)',
231
233
  flexDirection: 'column'
@@ -122,7 +122,8 @@ export var AttachmentFileListItem = function AttachmentFileListItem(param) {
122
122
  onDelete(file);
123
123
  };
124
124
  // 有 status 但无 url/previewUrl:文件内容未拿到,展示大小与格式占位块
125
- if (isFileMetaPlaceholderState(file)) {
125
+ // 注意:error 状态不走占位符,直接在下面的 file-item 中展示失败 UI
126
+ if (!isErrorStatus && isFileMetaPlaceholderState(file)) {
126
127
  return /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
127
128
  file: file,
128
129
  className: className
@@ -63,6 +63,7 @@ import classNames from "clsx";
63
63
  import { AnimatePresence, motion } from "framer-motion";
64
64
  import React, { useContext } from "react";
65
65
  import { ActionIconBox } from "../../../Components/ActionIconBox";
66
+ import { I18nContext } from "../../../I18n";
66
67
  import { isImageFile } from "../utils";
67
68
  import { AttachmentFileListItem } from "./AttachmentFileListItem";
68
69
  import { useStyle } from "./style";
@@ -112,6 +113,7 @@ var ClearButton = function ClearButton(param) {
112
113
  export var AttachmentFileList = function AttachmentFileList(param) {
113
114
  var fileMap = param.fileMap, onDelete = param.onDelete, onPreview = param.onPreview, onDownload = param.onDownload, onRetry = param.onRetry, onClearFileMap = param.onClearFileMap, dataTestId = param.dataTestId;
114
115
  var context = useContext(ConfigProvider.ConfigContext);
116
+ var locale = useContext(I18nContext).locale;
115
117
  var prefix = context === null || context === void 0 ? void 0 : context.getPrefixCls('agentic-md-editor-attachment-list');
116
118
  var _useStyle = useStyle(prefix), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
117
119
  var _React_useState = _sliced_to_array(React.useState(undefined), 2), imgSrc = _React_useState[0], setImgSrc = _React_useState[1];
@@ -148,7 +150,10 @@ export var AttachmentFileList = function AttachmentFileList(param) {
148
150
  animate: "visible",
149
151
  style: containerStyle,
150
152
  className: classNames(prefix, hashId)
151
- }, /*#__PURE__*/ React.createElement(AnimatePresence, {
153
+ }, hasFiles ? /*#__PURE__*/ React.createElement("div", {
154
+ className: classNames("".concat(prefix, "-title"), hashId),
155
+ "data-testid": "attachment-list-title"
156
+ }, (locale === null || locale === void 0 ? void 0 : locale['input.attachmentListTitle']) || '上传附件') : null, /*#__PURE__*/ React.createElement(AnimatePresence, {
152
157
  initial: false
153
158
  }, fileList.map(function(file, index) {
154
159
  return /*#__PURE__*/ React.createElement(AttachmentFileListItem, {
@@ -106,6 +106,14 @@ var genStyle = function genStyle(token) {
106
106
  transform: 'scale(1.05)'
107
107
  }
108
108
  },
109
+ '&-title': {
110
+ width: '100%',
111
+ flexBasis: '100%',
112
+ color: 'var(--color-gray-text-light)',
113
+ font: 'var(--font-text-body-sm)',
114
+ lineHeight: '20px',
115
+ marginBottom: 'var(--margin-0-5x)'
116
+ },
109
117
  '&-item': {
110
118
  width: '168px',
111
119
  height: '48px',
@@ -48,6 +48,21 @@ export type AttachmentButtonProps = {
48
48
  currentCount: number;
49
49
  selectedCount: number;
50
50
  }) => void;
51
+ /** 文件超出 maxFileSize 大小限制时的回调 */
52
+ onExceedMaxSize?: (info: {
53
+ file: AttachmentFile;
54
+ maxSize: number;
55
+ }) => void;
56
+ /** 文件上传失败时的回调 */
57
+ onUploadError?: (info: {
58
+ file: AttachmentFile;
59
+ error: unknown;
60
+ }) => void;
61
+ /**
62
+ * 上传失败时自动将文件从列表中移除(退回),不显示错误状态
63
+ * @default false
64
+ */
65
+ removeFileOnUploadError?: boolean;
51
66
  };
52
67
  /**
53
68
  * 文件上传配置
@@ -75,6 +90,21 @@ type UploadProps = {
75
90
  currentCount: number;
76
91
  selectedCount: number;
77
92
  }) => void;
93
+ /** 文件超出 maxFileSize 大小限制时的回调 */
94
+ onExceedMaxSize?: (info: {
95
+ file: AttachmentFile;
96
+ maxSize: number;
97
+ }) => void;
98
+ /** 文件上传失败时的回调 */
99
+ onUploadError?: (info: {
100
+ file: AttachmentFile;
101
+ error: unknown;
102
+ }) => void;
103
+ /**
104
+ * 上传失败时自动将文件从列表中移除(退回),不显示错误状态
105
+ * @default false
106
+ */
107
+ removeFileOnUploadError?: boolean;
78
108
  };
79
109
  /**
80
110
  * 上传文件到服务器
@@ -259,14 +259,25 @@ var handleUploadSuccess = function handleUploadSuccess(file, url, map, props) {
259
259
  file.url = url;
260
260
  updateFileMap(map, file, props.onFileMapChange);
261
261
  };
262
- var handleUploadError = function handleUploadError(file, errorMsg, map, props) {
263
- file.status = 'error';
264
- if (errorMsg !== null) file.errorMessage = errorMsg;
265
- updateFileMap(map, file, props.onFileMapChange);
262
+ var handleUploadError = function handleUploadError(file, errorMsg, map, props, rawError) {
263
+ var _props_onUploadError;
264
+ if (props.removeFileOnUploadError) {
265
+ var _props_onFileMapChange;
266
+ if (file.uuid) map.delete(file.uuid);
267
+ (_props_onFileMapChange = props.onFileMapChange) === null || _props_onFileMapChange === void 0 ? void 0 : _props_onFileMapChange.call(props, map);
268
+ } else {
269
+ file.status = 'error';
270
+ if (errorMsg !== null) file.errorMessage = errorMsg;
271
+ updateFileMap(map, file, props.onFileMapChange);
272
+ }
273
+ (_props_onUploadError = props.onUploadError) === null || _props_onUploadError === void 0 ? void 0 : _props_onUploadError.call(props, {
274
+ file: file,
275
+ error: rawError !== null && rawError !== void 0 ? rawError : errorMsg
276
+ });
266
277
  };
267
278
  var processFile = function processFile(file, index, map, props) {
268
279
  return _async_to_generator(function() {
269
- var maxSizeKb, raw, _ref, url, isSuccess, errorMsg, error, errorMessage;
280
+ var _props_onExceedMaxSize, maxSizeKb, raw, _ref, url, isSuccess, errorMsg, error, errorMessage;
270
281
  return _ts_generator(this, function(_state) {
271
282
  switch(_state.label){
272
283
  case 0:
@@ -277,12 +288,17 @@ var processFile = function processFile(file, index, map, props) {
277
288
  case 1:
278
289
  _state.sent();
279
290
  if (!validateFileSize(file, props)) {
291
+ ;
280
292
  maxSizeKb = Math.round((props.maxFileSize || 0) / 1024);
281
293
  raw = getLocaleMessage(props.locale, 'markdownInput.fileSizeExceeded', DEFAULT_MESSAGES.fileSizeExceeded(maxSizeKb));
282
294
  file.errorMessage = raw.includes('${maxSize}') ? raw.replace(/\$\{maxSize\}/g, String(maxSizeKb)) : raw;
283
295
  file.errorCode = 'FILE_SIZE_EXCEEDED';
284
296
  file.status = 'error';
285
297
  updateFileMap(map, file, props.onFileMapChange);
298
+ (_props_onExceedMaxSize = props.onExceedMaxSize) === null || _props_onExceedMaxSize === void 0 ? void 0 : _props_onExceedMaxSize.call(props, {
299
+ file: file,
300
+ maxSize: props.maxFileSize || 0
301
+ });
286
302
  return [
287
303
  2
288
304
  ];
@@ -313,7 +329,7 @@ var processFile = function processFile(file, index, map, props) {
313
329
  case 4:
314
330
  error = _state.sent();
315
331
  errorMessage = _instanceof(error, Error) ? error.message : getLocaleMessage(props.locale, 'uploadFailed', DEFAULT_MESSAGES.uploadFailed);
316
- handleUploadError(file, errorMessage, map, props);
332
+ handleUploadError(file, errorMessage, map, props, error);
317
333
  return [
318
334
  3,
319
335
  5
@@ -1,3 +1,4 @@
1
+ import type { AttachmentFile } from './types';
1
2
  /**
2
3
  * 将KB转换为可读的文件大小格式
3
4
  * 支持从字节(B)到TB的所有单位,最小单位为B
@@ -40,18 +41,14 @@ export declare const isMediaFile: (file: File) => boolean;
40
41
  /**
41
42
  * 是否为「仅元信息占位」状态:有 status 但无 url/previewUrl,内容未拿到时整行以 FileMetaPlaceholder 风格展示
42
43
  */
43
- export declare const isAttachmentFileLoading: (status?: string | null) => boolean;
44
+ export declare const isAttachmentFileLoading: (status?: AttachmentFile['status'] | null) => boolean;
44
45
  /**
45
46
  * 是否应该展示 FileMetaPlaceholder:
46
47
  * - 有状态
47
48
  * - 非 loading(uploading/pending)
48
49
  * - 且没有可预览 URL
49
50
  */
50
- export declare const isFileMetaPlaceholderState: (file: File & {
51
- status?: string;
52
- url?: string;
53
- previewUrl?: string;
54
- }) => boolean;
51
+ export declare const isFileMetaPlaceholderState: (file: AttachmentFile) => boolean;
55
52
  /**
56
53
  * 获取设备品牌
57
54
  *
@@ -46,6 +46,21 @@ function _iterable_to_array_limit(arr, i) {
46
46
  function _non_iterable_rest() {
47
47
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
48
48
  }
49
+ function _object_spread(target) {
50
+ for(var i = 1; i < arguments.length; i++){
51
+ var source = arguments[i] != null ? arguments[i] : {};
52
+ var ownKeys = Object.keys(source);
53
+ if (typeof Object.getOwnPropertySymbols === "function") {
54
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
55
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
56
+ }));
57
+ }
58
+ ownKeys.forEach(function(key) {
59
+ _define_property(target, key, source[key]);
60
+ });
61
+ }
62
+ return target;
63
+ }
49
64
  function _sliced_to_array(arr, i) {
50
65
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
51
66
  }
@@ -169,7 +184,11 @@ import { isFileMetaPlaceholderState, kbToSize } from "../AttachmentButton/utils"
169
184
  // 有 status 但无 url/previewUrl:文件内容未拿到,展示大小与格式占位块(loading 状态除外)
170
185
  if (isFileMetaPlaceholderState(file)) {
171
186
  return /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
172
- file: file
187
+ file: file,
188
+ className: classNames(props.className, props.prefixCls ? "".concat(props.prefixCls, "-meta-placeholder") : undefined),
189
+ style: _object_spread({
190
+ height: 56
191
+ }, props.style)
173
192
  });
174
193
  }
175
194
  return /*#__PURE__*/ React.createElement(Tooltip, {
@@ -190,10 +190,23 @@ import { ConfigProvider, Image, Modal } from "antd";
190
190
  import classNames from "clsx";
191
191
  import { motion } from "framer-motion";
192
192
  import React, { useContext, useMemo, useState } from "react";
193
+ import { I18nContext } from "../../I18n";
193
194
  import { FileMetaPlaceholder } from "../AttachmentButton/AttachmentFileList/AttachmentFileIcon";
194
- import { isImageFile, isVideoFile } from "../AttachmentButton/utils";
195
+ import { isFileMetaPlaceholderState, isImageFile, isVideoFile } from "../AttachmentButton/utils";
195
196
  import { FileMapViewItem } from "./FileMapViewItem";
196
197
  import { useStyle } from "./style";
198
+ var IMAGE_THUMBNAIL_SIZE = 124;
199
+ var SINGLE_VIDEO_THUMBNAIL_SIZE = {
200
+ width: 330,
201
+ height: 188
202
+ };
203
+ var getMediaPlaceholderStyle = function getMediaPlaceholderStyle(size) {
204
+ return {
205
+ width: size.width,
206
+ height: size.height,
207
+ minWidth: size.width
208
+ };
209
+ };
197
210
  /**
198
211
  * FileMapView 组件 - 文件映射视图组件
199
212
  *
@@ -236,6 +249,7 @@ import { useStyle } from "./style";
236
249
  var _props_style;
237
250
  var _props_placement = props.placement, placement = _props_placement === void 0 ? 'left' : _props_placement;
238
251
  var context = useContext(ConfigProvider.ConfigContext);
252
+ var locale = useContext(I18nContext).locale;
239
253
  var prefix = context === null || context === void 0 ? void 0 : context.getPrefixCls('agentic-md-editor-file-view-list');
240
254
  var _useStyle = useStyle(prefix), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
241
255
  var _useState = _sliced_to_array(useState(false), 2), showAllFiles = _useState[0], setShowAllFiles = _useState[1];
@@ -333,6 +347,11 @@ import { useStyle } from "./style";
333
347
  });
334
348
  })();
335
349
  };
350
+ var imagePlaceholderStyle = getMediaPlaceholderStyle({
351
+ width: IMAGE_THUMBNAIL_SIZE,
352
+ height: IMAGE_THUMBNAIL_SIZE
353
+ });
354
+ var hasAnyFiles = fileList.length > 0;
336
355
  var _obj;
337
356
  return wrapSSR(/*#__PURE__*/ React.createElement("div", {
338
357
  "data-testid": "file-view-list",
@@ -345,7 +364,10 @@ import { useStyle } from "./style";
345
364
  alignItems: placement === 'left' ? 'flex-start' : 'flex-end',
346
365
  width: 'max-content'
347
366
  }
348
- }, imgList.length > 0 && /*#__PURE__*/ React.createElement(motion.div, {
367
+ }, hasAnyFiles ? /*#__PURE__*/ React.createElement("div", {
368
+ className: classNames("".concat(prefix, "-title"), hashId),
369
+ "data-testid": "file-view-title"
370
+ }, (locale === null || locale === void 0 ? void 0 : locale['chat.fileMapTitle']) || '结果文件') : null, imgList.length > 0 && /*#__PURE__*/ React.createElement(motion.div, {
349
371
  variants: {
350
372
  visible: {
351
373
  opacity: 1,
@@ -369,10 +391,12 @@ import { useStyle } from "./style";
369
391
  className: classNames(prefix, hashId, props.className, "".concat(prefix, "-").concat(placement), (_obj = {}, _define_property(_obj, "".concat(prefix, "-image-list-view"), imgList.length > 1), _define_property(_obj, "".concat(prefix, "-image-list-view-").concat(placement), imgList.length > 1), _obj))
370
392
  }, /*#__PURE__*/ React.createElement(Image.PreviewGroup, null, imgList.map(function(file, index) {
371
393
  var key = file.uuid || file.name || index;
372
- if (file.status !== undefined && file.status !== null && !file.url && !file.previewUrl) {
394
+ if (isFileMetaPlaceholderState(file)) {
373
395
  var placeholderDom = /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
374
396
  file: file,
375
- key: key
397
+ key: key,
398
+ className: classNames("".concat(prefix, "-image"), hashId),
399
+ style: imagePlaceholderStyle
376
400
  });
377
401
  return props.itemRender ? props.itemRender(file, placeholderDom) : placeholderDom;
378
402
  }
@@ -412,18 +436,17 @@ import { useStyle } from "./style";
412
436
  }, videoList.map(function(file, index) {
413
437
  var videoUrl = file.previewUrl || file.url || '';
414
438
  var isSingleVideo = videoList.length === 1;
415
- var thumbSize = isSingleVideo ? {
416
- width: 330,
417
- height: 188
418
- } : {
419
- width: 124,
420
- height: 124
439
+ var thumbSize = isSingleVideo ? SINGLE_VIDEO_THUMBNAIL_SIZE : {
440
+ width: IMAGE_THUMBNAIL_SIZE,
441
+ height: IMAGE_THUMBNAIL_SIZE
421
442
  };
422
443
  var key = file.uuid || file.name || index;
423
- if (file.status !== undefined && file.status !== null && !file.url && !file.previewUrl) {
444
+ if (isFileMetaPlaceholderState(file)) {
424
445
  var placeholderDom = /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
425
446
  file: file,
426
- key: key
447
+ key: key,
448
+ className: classNames("".concat(prefix, "-image"), "".concat(prefix, "-video-thumb"), hashId),
449
+ style: getMediaPlaceholderStyle(thumbSize)
427
450
  });
428
451
  return props.itemRender ? props.itemRender(file, placeholderDom) : placeholderDom;
429
452
  }
@@ -212,6 +212,12 @@ var genStyle = function genStyle(token) {
212
212
  }), _define_property(_obj1, '&-more-file-name', {
213
213
  font: 'var(--font-size-h6)',
214
214
  color: 'var(--color-gray-text-secondary)'
215
+ }), _define_property(_obj1, '&-title', {
216
+ width: '100%',
217
+ color: 'var(--color-gray-text-light)',
218
+ font: 'var(--font-text-body-sm)',
219
+ lineHeight: '20px',
220
+ marginBottom: 2
215
221
  }), _define_property(_obj1, '&-item', {
216
222
  width: '285px',
217
223
  height: '56px',
@@ -416,30 +416,32 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
416
416
  * 处理文件重试
417
417
  */ var handleFileRetry = useRefFunction(function(file) {
418
418
  return _async_to_generator(function() {
419
- var map, url, isSuccess, uploadResult, error, map1;
419
+ var map, url, isSuccess, uploadResult, _attachment_onUploadError, error, _attachment_onUploadError1;
420
420
  return _ts_generator(this, function(_state) {
421
421
  switch(_state.label){
422
422
  case 0:
423
+ map = new Map(fileMap);
424
+ _state.label = 1;
425
+ case 1:
423
426
  _state.trys.push([
424
- 0,
425
- 5,
427
+ 1,
428
+ 6,
426
429
  ,
427
- 6
430
+ 7
428
431
  ]);
429
432
  file.status = 'uploading';
430
- map = new Map(fileMap);
431
433
  map.set(file.uuid || '', file);
432
434
  updateAttachmentFiles(map);
433
435
  isSuccess = false;
434
436
  if (!(attachment === null || attachment === void 0 ? void 0 : attachment.uploadWithResponse)) return [
435
437
  3,
436
- 2
438
+ 3
437
439
  ];
438
440
  return [
439
441
  4,
440
442
  attachment.uploadWithResponse(file, 0)
441
443
  ];
442
- case 1:
444
+ case 2:
443
445
  uploadResult = _state.sent();
444
446
  url = uploadResult.fileUrl;
445
447
  isSuccess = uploadResult.uploadStatus === 'SUCCESS';
@@ -447,48 +449,61 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
447
449
  file.uploadResponse = uploadResult;
448
450
  return [
449
451
  3,
450
- 4
452
+ 5
451
453
  ];
452
- case 2:
454
+ case 3:
453
455
  if (!(attachment === null || attachment === void 0 ? void 0 : attachment.upload)) return [
454
456
  3,
455
- 4
457
+ 5
456
458
  ];
457
459
  return [
458
460
  4,
459
461
  attachment.upload(file, 0)
460
462
  ];
461
- case 3:
463
+ case 4:
462
464
  url = _state.sent();
463
465
  isSuccess = !!url;
464
- _state.label = 4;
465
- case 4:
466
+ _state.label = 5;
467
+ case 5:
466
468
  if (isSuccess && url) {
467
469
  file.status = 'done';
468
470
  file.url = url;
469
471
  map.set(file.uuid || '', file);
470
472
  updateAttachmentFiles(map);
471
473
  } else {
474
+ ;
472
475
  file.status = 'error';
473
476
  map.set(file.uuid || '', file);
474
477
  updateAttachmentFiles(map);
478
+ attachment === null || attachment === void 0 ? void 0 : (_attachment_onUploadError = attachment.onUploadError) === null || _attachment_onUploadError === void 0 ? void 0 : _attachment_onUploadError.call(attachment, {
479
+ file: file,
480
+ error: null
481
+ });
475
482
  }
476
483
  return [
477
484
  3,
478
- 6
485
+ 7
479
486
  ];
480
- case 5:
487
+ case 6:
481
488
  error = _state.sent();
482
- file.status = 'error';
483
- map1 = new Map(fileMap);
484
- map1.set(file.uuid || '', file);
485
- updateAttachmentFiles(map1);
489
+ if (attachment === null || attachment === void 0 ? void 0 : attachment.removeFileOnUploadError) {
490
+ map.delete(file.uuid || '');
491
+ updateAttachmentFiles(map);
492
+ } else {
493
+ file.status = 'error';
494
+ map.set(file.uuid || '', file);
495
+ updateAttachmentFiles(map);
496
+ }
497
+ attachment === null || attachment === void 0 ? void 0 : (_attachment_onUploadError1 = attachment.onUploadError) === null || _attachment_onUploadError1 === void 0 ? void 0 : _attachment_onUploadError1.call(attachment, {
498
+ file: file,
499
+ error: error
500
+ });
486
501
  console.error('Error retrying file upload:', error);
487
502
  return [
488
503
  3,
489
- 6
504
+ 7
490
505
  ];
491
- case 6:
506
+ case 7:
492
507
  return [
493
508
  2
494
509
  ];
@@ -290,7 +290,7 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
290
290
  stopRecording: stopRecording,
291
291
  isEnlarged: isEnlarged,
292
292
  setIsEnlarged: setIsEnlarged
293
- }), handleEnlargeClick = _useMarkdownInputFieldHandlers.handleEnlargeClick, sendMessage = _useMarkdownInputFieldHandlers.sendMessage, handlePaste = _useMarkdownInputFieldHandlers.handlePaste, handleKeyDown = _useMarkdownInputFieldHandlers.handleKeyDown, activeInput = _useMarkdownInputFieldHandlers.activeInput;
293
+ }), handleEnlargeClick = _useMarkdownInputFieldHandlers.handleEnlargeClick, sendMessage = _useMarkdownInputFieldHandlers.sendMessage, handlePaste = _useMarkdownInputFieldHandlers.handlePaste, handleKeyDown = _useMarkdownInputFieldHandlers.handleKeyDown, handleContainerClick = _useMarkdownInputFieldHandlers.handleContainerClick, activeInput = _useMarkdownInputFieldHandlers.activeInput;
294
294
  // 渲染辅助
295
295
  var attachmentList = useAttachmentList({
296
296
  attachment: attachment,
@@ -370,6 +370,7 @@ var MarkdownInputFieldComponent = function MarkdownInputFieldComponent(_0) {
370
370
  onMouseLeave: function onMouseLeave() {
371
371
  return setHover(false);
372
372
  },
373
+ onClick: handleContainerClick,
373
374
  onKeyDown: handleKeyDown
374
375
  }, /*#__PURE__*/ React.createElement(BorderBeamAnimation, {
375
376
  isVisible: isFocused && !animationComplete,
@@ -27,6 +27,7 @@ export declare const useMarkdownInputFieldHandlers: ({ props, markdownEditorRef,
27
27
  sendMessage: () => Promise<void>;
28
28
  handlePaste: (e: React.ClipboardEvent<HTMLDivElement>) => Promise<void>;
29
29
  handleKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;
30
+ handleContainerClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
30
31
  activeInput: (active: boolean) => void;
31
32
  };
32
33
  export {};