@ant-design/agentic-ui 2.30.12 → 2.30.14
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/dist/Bubble/AIBubble.js +32 -18
- package/dist/Bubble/ContentFilemapView.d.ts +14 -0
- package/dist/Bubble/ContentFilemapView.js +95 -0
- package/dist/Bubble/MessagesContent/MarkdownPreview.js +3 -2
- package/dist/Bubble/UserBubble.js +48 -6
- package/dist/Bubble/extractFilemapBlocks.d.ts +17 -0
- package/dist/Bubble/extractFilemapBlocks.js +23 -0
- package/dist/Bubble/type.d.ts +3 -0
- package/dist/Hooks/useLanguage.d.ts +2 -0
- package/dist/I18n/locales.d.ts +2 -0
- package/dist/I18n/locales.js +5 -1
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +5 -1
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +10 -2
- package/dist/MarkdownEditor/editor/elements/Code/index.js +22 -14
- package/dist/MarkdownEditor/editor/parser/constants.d.ts +10 -0
- package/dist/MarkdownEditor/editor/parser/constants.js +46 -0
- package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.js +3 -1
- package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +11 -0
- package/dist/MarkdownEditor/editor/utils/markdownToHtml.js +6 -4
- package/dist/MarkdownEditor/types.d.ts +6 -0
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +3 -1
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +2 -2
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.js +6 -1
- package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +11 -1
- package/dist/MarkdownInputField/AttachmentButton/index.d.ts +12 -0
- package/dist/MarkdownInputField/AttachmentButton/index.js +23 -13
- package/dist/MarkdownInputField/FileMapView/FileMapViewItem.js +20 -1
- package/dist/MarkdownInputField/FileMapView/index.d.ts +13 -1
- package/dist/MarkdownInputField/FileMapView/index.js +57 -18
- package/dist/MarkdownInputField/FileMapView/style.js +6 -0
- package/dist/MarkdownInputField/FileUploadManager/index.js +4 -26
- package/dist/MarkdownInputField/style.js +7 -0
- package/dist/MarkdownRenderer/MarkdownRenderer.js +10 -6
- package/dist/MarkdownRenderer/index.d.ts +1 -1
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +4 -2
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +47 -5
- package/dist/MarkdownRenderer/renderers/ChartRenderer.js +9 -0
- package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -2
- package/dist/MarkdownRenderer/types.d.ts +45 -2
- package/dist/MarkdownRenderer/useMarkdownToReact.js +2 -2
- package/dist/Plugins/chart/ChartRender.js +30 -9
- package/dist/Plugins/chart/DonutChart/index.js +21 -7
- package/dist/Plugins/chart/HistogramChart/index.d.ts +5 -1
- package/dist/Plugins/chart/HistogramChart/index.js +79 -12
- package/dist/Plugins/chart/ScatterChart/index.d.ts +8 -0
- package/dist/Plugins/chart/ScatterChart/index.js +78 -8
- package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +4 -0
- package/dist/Plugins/code/components/AceEditor.js +69 -8
- package/dist/Plugins/code/components/CodeRenderer.js +0 -1
- package/dist/Workspace/Browser/index.js +3 -1
- package/package.json +1 -1
|
@@ -1152,6 +1152,17 @@ export var isMix = function isMix(t) {
|
|
|
1152
1152
|
} catch (e) {
|
|
1153
1153
|
console.warn('Invalid code object', e);
|
|
1154
1154
|
}
|
|
1155
|
+
} else if ((node === null || node === void 0 ? void 0 : node.type) === 'code') {
|
|
1156
|
+
var _node_children;
|
|
1157
|
+
// 对于普通代码块(type === 'code'),优先从 Slate children 中读取文本
|
|
1158
|
+
// 因为用户编辑后 Slate 只更新 children,而 value 保留的是初始解析值
|
|
1159
|
+
var childrenText = node === null || node === void 0 ? void 0 : (_node_children = node.children) === null || _node_children === void 0 ? void 0 : _node_children.map(function(child) {
|
|
1160
|
+
var _ref;
|
|
1161
|
+
return (_ref = child === null || child === void 0 ? void 0 : child.text) !== null && _ref !== void 0 ? _ref : '';
|
|
1162
|
+
}).join('');
|
|
1163
|
+
if (childrenText !== undefined && childrenText !== null) {
|
|
1164
|
+
code = childrenText;
|
|
1165
|
+
}
|
|
1155
1166
|
}
|
|
1156
1167
|
// 如果语言是 think,转换为 <think> 标签
|
|
1157
1168
|
if (node.language === 'think') {
|
|
@@ -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(
|
|
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
|
|
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) {
|
|
@@ -647,4 +647,10 @@ export type MarkdownEditorProps = {
|
|
|
647
647
|
* @returns 自定义渲染节点,或 undefined 时回退到 defaultDom
|
|
648
648
|
*/
|
|
649
649
|
eleRender?: (props: import('../MarkdownRenderer/types').MarkdownRendererEleProps, defaultDom: React.ReactNode) => React.ReactNode;
|
|
650
|
+
/**
|
|
651
|
+
* FileMapView 配置(仅 `renderMode: 'markdown'` 时生效)
|
|
652
|
+
* @description 透传给 agentic-ui-filemap 代码块渲染器,
|
|
653
|
+
* 统一配置图片/视频条目的 onPreview 拦截和 itemRender 自定义回显。
|
|
654
|
+
*/
|
|
655
|
+
fileMapConfig?: import('../MarkdownRenderer/types').FileMapConfig;
|
|
650
656
|
};
|
|
@@ -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
|
|
229
|
+
// 占位块不应在 flex 容器中自动拉伸为整行宽度
|
|
230
|
+
flex: '0 0 auto',
|
|
229
231
|
minWidth: 80,
|
|
230
232
|
padding: 'var(--padding-1x) var(--padding-2x)',
|
|
231
233
|
flexDirection: 'column'
|
package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js
CHANGED
|
@@ -105,8 +105,8 @@ export var AttachmentFileListItem = function AttachmentFileListItem(param) {
|
|
|
105
105
|
var file = param.file, prefixCls = param.prefixCls, hashId = param.hashId, onPreview = param.onPreview, onRetry = param.onRetry, onDelete = param.onDelete, className = param.className;
|
|
106
106
|
var locale = useContext(I18nContext).locale;
|
|
107
107
|
var isErrorStatus = file.status === 'error';
|
|
108
|
-
var
|
|
109
|
-
var canRetry = isErrorStatus && !
|
|
108
|
+
var isNonRetryableError = isErrorStatus && (file.errorCode === 'FILE_SIZE_EXCEEDED' || file.errorCode === 'FILE_COUNT_EXCEEDED');
|
|
109
|
+
var canRetry = isErrorStatus && !isNonRetryableError;
|
|
110
110
|
var isDoneStatus = file.status === 'done';
|
|
111
111
|
var canDelete = !isAttachmentFileLoading(file.status);
|
|
112
112
|
var handleFileClick = function handleFileClick() {
|
|
@@ -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(
|
|
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',
|
|
@@ -200,7 +208,9 @@ var genStyle = function genStyle(token) {
|
|
|
200
208
|
alignItems: 'center',
|
|
201
209
|
gap: 4,
|
|
202
210
|
'&-error': {
|
|
203
|
-
color: 'var(--color-red-a10)'
|
|
211
|
+
color: 'var(--color-red-a10)',
|
|
212
|
+
maxWidth: '100%',
|
|
213
|
+
overflow: 'auto'
|
|
204
214
|
},
|
|
205
215
|
'&-item:not(:last-child)': {
|
|
206
216
|
lineHeight: '9px',
|
|
@@ -42,6 +42,12 @@ export type AttachmentButtonProps = {
|
|
|
42
42
|
minFileCount?: number;
|
|
43
43
|
/** 是否允许一次选择多个文件(默认:true) */
|
|
44
44
|
allowMultiple?: boolean;
|
|
45
|
+
/** 文件数量超出 maxFileCount 限制时的回调 */
|
|
46
|
+
onExceedMaxCount?: (info: {
|
|
47
|
+
maxCount: number;
|
|
48
|
+
currentCount: number;
|
|
49
|
+
selectedCount: number;
|
|
50
|
+
}) => void;
|
|
45
51
|
};
|
|
46
52
|
/**
|
|
47
53
|
* 文件上传配置
|
|
@@ -63,6 +69,12 @@ type UploadProps = {
|
|
|
63
69
|
minFileCount?: number;
|
|
64
70
|
/** 国际化文案 */
|
|
65
71
|
locale?: any;
|
|
72
|
+
/** 文件数量超出 maxFileCount 限制时的回调 */
|
|
73
|
+
onExceedMaxCount?: (info: {
|
|
74
|
+
maxCount: number;
|
|
75
|
+
currentCount: number;
|
|
76
|
+
selectedCount: number;
|
|
77
|
+
}) => void;
|
|
66
78
|
};
|
|
67
79
|
/**
|
|
68
80
|
* 上传文件到服务器
|
|
@@ -187,16 +187,6 @@ var prepareFile = function prepareFile(file) {
|
|
|
187
187
|
var getLocaleMessage = function getLocaleMessage(locale, key, defaultMsg) {
|
|
188
188
|
return (locale === null || locale === void 0 ? void 0 : locale[key]) || defaultMsg;
|
|
189
189
|
};
|
|
190
|
-
var validateFileCount = function validateFileCount(newFileCount, existingFileCount, props) {
|
|
191
|
-
var totalFileCount = newFileCount + existingFileCount;
|
|
192
|
-
if (props.maxFileCount && totalFileCount > props.maxFileCount) {
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
if (props.minFileCount && totalFileCount < props.minFileCount) {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
return true;
|
|
199
|
-
};
|
|
200
190
|
var validateFileSize = function validateFileSize(file, props) {
|
|
201
191
|
if (!props.maxFileSize || file.size <= props.maxFileSize) return true;
|
|
202
192
|
return false;
|
|
@@ -351,7 +341,7 @@ var processFile = function processFile(file, index, map, props) {
|
|
|
351
341
|
* @param props.locale - 国际化文案
|
|
352
342
|
*/ export var upLoadFileToServer = function upLoadFileToServer(files, props) {
|
|
353
343
|
return _async_to_generator(function() {
|
|
354
|
-
var map, existingFileCount, hideLoading, fileList, i, error;
|
|
344
|
+
var map, existingFileCount, hideLoading, fileList, totalCount, isMaxExceeded, isMinNotMet, _props_onFileMapChange, _props_onExceedMaxCount, maxCount, rawMessage, errorMessage, i, error;
|
|
355
345
|
return _ts_generator(this, function(_state) {
|
|
356
346
|
switch(_state.label){
|
|
357
347
|
case 0:
|
|
@@ -360,9 +350,29 @@ var processFile = function processFile(file, index, map, props) {
|
|
|
360
350
|
hideLoading = function hideLoading() {};
|
|
361
351
|
fileList = Array.from(files);
|
|
362
352
|
fileList.forEach(prepareFile);
|
|
363
|
-
|
|
364
|
-
|
|
353
|
+
totalCount = fileList.length + existingFileCount;
|
|
354
|
+
isMaxExceeded = typeof props.maxFileCount === 'number' && totalCount > props.maxFileCount;
|
|
355
|
+
isMinNotMet = typeof props.minFileCount === 'number' && totalCount < props.minFileCount;
|
|
356
|
+
if (isMaxExceeded || isMinNotMet) {
|
|
365
357
|
hideLoading();
|
|
358
|
+
if (isMaxExceeded) {
|
|
359
|
+
;
|
|
360
|
+
maxCount = props.maxFileCount;
|
|
361
|
+
rawMessage = getLocaleMessage(props.locale, 'markdownInput.maxFileCountExceeded', DEFAULT_MESSAGES.maxFileCountExceeded(maxCount));
|
|
362
|
+
errorMessage = rawMessage.replace(/\$\{maxFileCount\}/g, String(maxCount));
|
|
363
|
+
fileList.forEach(function(file) {
|
|
364
|
+
file.status = 'error';
|
|
365
|
+
file.errorCode = 'FILE_COUNT_EXCEEDED';
|
|
366
|
+
file.errorMessage = errorMessage;
|
|
367
|
+
if (file.uuid) map.set(file.uuid, file);
|
|
368
|
+
});
|
|
369
|
+
(_props_onFileMapChange = props.onFileMapChange) === null || _props_onFileMapChange === void 0 ? void 0 : _props_onFileMapChange.call(props, map);
|
|
370
|
+
(_props_onExceedMaxCount = props.onExceedMaxCount) === null || _props_onExceedMaxCount === void 0 ? void 0 : _props_onExceedMaxCount.call(props, {
|
|
371
|
+
maxCount: maxCount,
|
|
372
|
+
currentCount: existingFileCount,
|
|
373
|
+
selectedCount: fileList.length
|
|
374
|
+
});
|
|
375
|
+
}
|
|
366
376
|
return [
|
|
367
377
|
2
|
|
368
378
|
];
|
|
@@ -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, {
|
|
@@ -5,7 +5,12 @@ export type FileMapViewProps = {
|
|
|
5
5
|
showMoreButton?: boolean;
|
|
6
6
|
/** 文件映射表 */
|
|
7
7
|
fileMap?: Map<string, AttachmentFile>;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* 预览文件回调。
|
|
10
|
+
* - 对于非图片/视频文件:点击预览按钮时触发,传入时阻止默认的 window.open 行为。
|
|
11
|
+
* - 对于图片文件:点击缩略图时触发,传入时阻止 antd Image 内置灯箱预览。
|
|
12
|
+
* - 对于视频文件:点击缩略图时触发,传入时阻止内置弹窗播放。
|
|
13
|
+
*/
|
|
9
14
|
onPreview?: (file: AttachmentFile) => void;
|
|
10
15
|
/** 下载文件回调 */
|
|
11
16
|
onDownload?: (file: AttachmentFile) => void;
|
|
@@ -22,6 +27,13 @@ export type FileMapViewProps = {
|
|
|
22
27
|
/** 最多展示的非图片文件数量,传入则开启溢出控制并在超出时显示"查看所有文件"按钮,不传则展示所有文件且不显示按钮 */
|
|
23
28
|
maxDisplayCount?: number;
|
|
24
29
|
placement?: 'left' | 'right';
|
|
30
|
+
/**
|
|
31
|
+
* 自定义每个媒体(图片/视频)条目的渲染。
|
|
32
|
+
* 接收文件对象和默认渲染节点,返回自定义节点即可替换默认展示,常用于回显场景。
|
|
33
|
+
* @param file - 当前文件
|
|
34
|
+
* @param defaultDom - 默认渲染的 React 节点
|
|
35
|
+
*/
|
|
36
|
+
itemRender?: (file: AttachmentFile, defaultDom: React.ReactNode) => React.ReactNode;
|
|
25
37
|
};
|
|
26
38
|
/**
|
|
27
39
|
* FileMapView 组件 - 文件映射视图组件
|
|
@@ -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
|
-
},
|
|
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,
|
|
@@ -368,19 +390,34 @@ import { useStyle } from "./style";
|
|
|
368
390
|
"data-testid": "file-view-image-list",
|
|
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
|
-
|
|
372
|
-
|
|
393
|
+
var key = file.uuid || file.name || index;
|
|
394
|
+
if (isFileMetaPlaceholderState(file)) {
|
|
395
|
+
var placeholderDom = /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
|
|
373
396
|
file: file,
|
|
374
|
-
key:
|
|
397
|
+
key: key,
|
|
398
|
+
className: classNames("".concat(prefix, "-image"), hashId),
|
|
399
|
+
style: imagePlaceholderStyle
|
|
375
400
|
});
|
|
401
|
+
return props.itemRender ? props.itemRender(file, placeholderDom) : placeholderDom;
|
|
376
402
|
}
|
|
377
|
-
|
|
403
|
+
var defaultImageDom = /*#__PURE__*/ React.createElement(Image, {
|
|
378
404
|
rootClassName: classNames("".concat(prefix, "-image"), hashId),
|
|
379
405
|
width: 124,
|
|
380
406
|
height: 124,
|
|
381
407
|
src: file.previewUrl || file.url,
|
|
382
|
-
key:
|
|
408
|
+
key: key,
|
|
409
|
+
preview: props.onPreview ? {
|
|
410
|
+
visible: false,
|
|
411
|
+
onVisibleChange: function onVisibleChange() {
|
|
412
|
+
var _props_onPreview;
|
|
413
|
+
return (_props_onPreview = props.onPreview) === null || _props_onPreview === void 0 ? void 0 : _props_onPreview.call(props, file);
|
|
414
|
+
},
|
|
415
|
+
mask: /*#__PURE__*/ React.createElement("div", {
|
|
416
|
+
className: classNames("".concat(prefix, "-image-mask"), hashId)
|
|
417
|
+
})
|
|
418
|
+
} : undefined
|
|
383
419
|
});
|
|
420
|
+
return props.itemRender ? props.itemRender(file, defaultImageDom) : defaultImageDom;
|
|
384
421
|
}))), videoList.length > 0 && /*#__PURE__*/ React.createElement(motion.div, {
|
|
385
422
|
variants: {
|
|
386
423
|
visible: {
|
|
@@ -399,24 +436,25 @@ import { useStyle } from "./style";
|
|
|
399
436
|
}, videoList.map(function(file, index) {
|
|
400
437
|
var videoUrl = file.previewUrl || file.url || '';
|
|
401
438
|
var isSingleVideo = videoList.length === 1;
|
|
402
|
-
var thumbSize = isSingleVideo ? {
|
|
403
|
-
width:
|
|
404
|
-
height:
|
|
405
|
-
} : {
|
|
406
|
-
width: 124,
|
|
407
|
-
height: 124
|
|
439
|
+
var thumbSize = isSingleVideo ? SINGLE_VIDEO_THUMBNAIL_SIZE : {
|
|
440
|
+
width: IMAGE_THUMBNAIL_SIZE,
|
|
441
|
+
height: IMAGE_THUMBNAIL_SIZE
|
|
408
442
|
};
|
|
409
|
-
|
|
410
|
-
|
|
443
|
+
var key = file.uuid || file.name || index;
|
|
444
|
+
if (isFileMetaPlaceholderState(file)) {
|
|
445
|
+
var placeholderDom = /*#__PURE__*/ React.createElement(FileMetaPlaceholder, {
|
|
411
446
|
file: file,
|
|
412
|
-
key:
|
|
447
|
+
key: key,
|
|
448
|
+
className: classNames("".concat(prefix, "-image"), "".concat(prefix, "-video-thumb"), hashId),
|
|
449
|
+
style: getMediaPlaceholderStyle(thumbSize)
|
|
413
450
|
});
|
|
451
|
+
return props.itemRender ? props.itemRender(file, placeholderDom) : placeholderDom;
|
|
414
452
|
}
|
|
415
|
-
|
|
453
|
+
var defaultVideoDom = /*#__PURE__*/ React.createElement("div", {
|
|
416
454
|
role: "button",
|
|
417
455
|
tabIndex: 0,
|
|
418
456
|
className: classNames("".concat(prefix, "-image"), "".concat(prefix, "-video-thumb"), hashId),
|
|
419
|
-
key:
|
|
457
|
+
key: key,
|
|
420
458
|
onClick: function onClick() {
|
|
421
459
|
return handleVideoClick(file);
|
|
422
460
|
},
|
|
@@ -443,6 +481,7 @@ import { useStyle } from "./style";
|
|
|
443
481
|
className: classNames("".concat(prefix, "-video-play-overlay"), hashId),
|
|
444
482
|
"aria-hidden": true
|
|
445
483
|
}, /*#__PURE__*/ React.createElement(Play, null)));
|
|
484
|
+
return props.itemRender ? props.itemRender(file, defaultVideoDom) : defaultVideoDom;
|
|
446
485
|
})), /*#__PURE__*/ React.createElement(Modal, {
|
|
447
486
|
open: videoModalOpen,
|
|
448
487
|
onCancel: handleVideoModalClose,
|
|
@@ -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',
|
|
@@ -252,7 +252,7 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
|
|
|
252
252
|
* 上传图片
|
|
253
253
|
*/ var uploadImage = useRefFunction(function(forGallery) {
|
|
254
254
|
return _async_to_generator(function() {
|
|
255
|
-
var _ref, isUploading, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, file,
|
|
255
|
+
var _ref, isUploading, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, file, accept, input;
|
|
256
256
|
return _ts_generator(this, function(_state) {
|
|
257
257
|
// 检查是否有文件正在上传中
|
|
258
258
|
isUploading = false;
|
|
@@ -284,13 +284,6 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
|
|
|
284
284
|
2
|
|
285
285
|
];
|
|
286
286
|
}
|
|
287
|
-
// 检查是否已达到最大文件数量限制
|
|
288
|
-
currentFileCount = (fileMap === null || fileMap === void 0 ? void 0 : fileMap.size) || 0;
|
|
289
|
-
if ((attachment === null || attachment === void 0 ? void 0 : attachment.maxFileCount) && currentFileCount >= attachment.maxFileCount) {
|
|
290
|
-
return [
|
|
291
|
-
2
|
|
292
|
-
];
|
|
293
|
-
}
|
|
294
287
|
accept = getAcceptValue(forGallery || false);
|
|
295
288
|
input = document.createElement('input');
|
|
296
289
|
input.id = 'uploadImage' + '_' + Math.random();
|
|
@@ -300,7 +293,7 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
|
|
|
300
293
|
input.style.display = 'none';
|
|
301
294
|
input.onchange = function(e) {
|
|
302
295
|
return _async_to_generator(function() {
|
|
303
|
-
var selectedFiles,
|
|
296
|
+
var selectedFiles, error;
|
|
304
297
|
return _ts_generator(this, function(_state) {
|
|
305
298
|
switch(_state.label){
|
|
306
299
|
case 0:
|
|
@@ -324,23 +317,8 @@ import { isMobileDevice, isVivoOrOppoDevice, isWeChat } from "../AttachmentButto
|
|
|
324
317
|
2
|
|
325
318
|
];
|
|
326
319
|
}
|
|
327
|
-
//
|
|
328
|
-
|
|
329
|
-
if (attachment === null || attachment === void 0 ? void 0 : attachment.maxFileCount) {
|
|
330
|
-
// 如果一次选择的文件数量超过最大限制,完全拒绝
|
|
331
|
-
if (selectedFiles.length > attachment.maxFileCount) {
|
|
332
|
-
return [
|
|
333
|
-
2
|
|
334
|
-
];
|
|
335
|
-
}
|
|
336
|
-
// 如果选择的文件数量加上已有文件数量超过限制,完全拒绝
|
|
337
|
-
totalFileCount = selectedFiles.length + currentFileCount;
|
|
338
|
-
if (totalFileCount > attachment.maxFileCount) {
|
|
339
|
-
return [
|
|
340
|
-
2
|
|
341
|
-
];
|
|
342
|
-
}
|
|
343
|
-
}
|
|
320
|
+
// 检查选择的文件数量是否超过限制——超限时交由 upLoadFileToServer 统一处理
|
|
321
|
+
// (upLoadFileToServer 内 validateFileCount 失败时会把文件以 error 状态入 map 并触发 onExceedMaxCount)
|
|
344
322
|
return [
|
|
345
323
|
4,
|
|
346
324
|
upLoadFileToServer(selectedFiles, _object_spread_props(_object_spread({}, attachment), {
|
|
@@ -94,6 +94,8 @@ var INPUT_FIELD_PADDING = {
|
|
|
94
94
|
NONE: '0px',
|
|
95
95
|
SMALL: "".concat(GLOW_BORDER_OFFSET, "px")
|
|
96
96
|
};
|
|
97
|
+
// MarkdownInputField 中 code block 的默认高度,避免初始占位过高
|
|
98
|
+
var DEFAULT_INPUT_CODE_BLOCK_HEIGHT = 120;
|
|
97
99
|
// 定义旋转动画
|
|
98
100
|
var stopIconRotate = new Keyframes('stopIconRotate', {
|
|
99
101
|
'0%': {
|
|
@@ -183,6 +185,11 @@ var genStyle = function genStyle(token) {
|
|
|
183
185
|
padding: '0 !important'
|
|
184
186
|
}
|
|
185
187
|
},
|
|
188
|
+
// 仅覆盖 MarkdownInputField 内的代码块默认高度
|
|
189
|
+
'& [data-language][data-is-unclosed]': {
|
|
190
|
+
height: "".concat(DEFAULT_INPUT_CODE_BLOCK_HEIGHT, "px !important"),
|
|
191
|
+
minHeight: "".concat(DEFAULT_INPUT_CODE_BLOCK_HEIGHT, "px !important")
|
|
192
|
+
},
|
|
186
193
|
'&-editor-content': _define_property({
|
|
187
194
|
display: 'flex',
|
|
188
195
|
flexDirection: 'column',
|
|
@@ -187,10 +187,11 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
187
187
|
/**
|
|
188
188
|
* 默认的代码块路由——根据语言分发到对应渲染器
|
|
189
189
|
*/ var DefaultCodeRouter = function DefaultCodeRouter(props) {
|
|
190
|
-
var language = props.language, pluginComponents = props.pluginComponents, apaasifyRender = props.apaasifyRender, rest = _object_without_properties(props, [
|
|
190
|
+
var language = props.language, pluginComponents = props.pluginComponents, apaasifyRender = props.apaasifyRender, fileMapConfig = props.fileMapConfig, rest = _object_without_properties(props, [
|
|
191
191
|
"language",
|
|
192
192
|
"pluginComponents",
|
|
193
|
-
"apaasifyRender"
|
|
193
|
+
"apaasifyRender",
|
|
194
|
+
"fileMapConfig"
|
|
194
195
|
]);
|
|
195
196
|
if (language === 'mermaid') {
|
|
196
197
|
var MermaidComp = pluginComponents.mermaid || MermaidBlockRenderer;
|
|
@@ -219,7 +220,8 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
219
220
|
if (language === 'agentic-ui-filemap') {
|
|
220
221
|
var FileMapComp = pluginComponents['agentic-ui-filemap'] || AgenticUiFileMapBlockRenderer;
|
|
221
222
|
return /*#__PURE__*/ React.createElement(FileMapComp, _object_spread_props(_object_spread({}, rest), {
|
|
222
|
-
language: language
|
|
223
|
+
language: language,
|
|
224
|
+
fileMapConfig: fileMapConfig
|
|
223
225
|
}));
|
|
224
226
|
}
|
|
225
227
|
if (SCHEMA_LANGUAGES.has(language)) {
|
|
@@ -243,7 +245,7 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
243
245
|
* - Markdown → hast → React 元素树(hast-util-to-jsx-runtime)
|
|
244
246
|
* - 特殊块(code / mermaid / chart / katex)通过组件映射拦截渲染
|
|
245
247
|
*/ var InternalMarkdownRenderer = /*#__PURE__*/ forwardRef(function(props, ref) {
|
|
246
|
-
var content = props.content, _props_streaming = props.streaming, streaming = _props_streaming === void 0 ? false : _props_streaming, isFinished = props.isFinished, queueOptions = props.queueOptions, plugins = props.plugins, remarkPlugins = props.remarkPlugins, htmlConfig = props.htmlConfig, className = props.className, style = props.style, customPrefixCls = props.prefixCls, linkConfig = props.linkConfig, streamingParagraphAnimation = props.streamingParagraphAnimation, apaasify = props.apaasify, eleRender = props.eleRender;
|
|
248
|
+
var content = props.content, _props_streaming = props.streaming, streaming = _props_streaming === void 0 ? false : _props_streaming, isFinished = props.isFinished, queueOptions = props.queueOptions, plugins = props.plugins, remarkPlugins = props.remarkPlugins, htmlConfig = props.htmlConfig, className = props.className, style = props.style, customPrefixCls = props.prefixCls, linkConfig = props.linkConfig, streamingParagraphAnimation = props.streamingParagraphAnimation, apaasify = props.apaasify, eleRender = props.eleRender, fileMapConfig = props.fileMapConfig;
|
|
247
249
|
var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
|
|
248
250
|
// 复用 MarkdownEditor 的 CSS 前缀和样式,保持渲染一致性
|
|
249
251
|
var prefixCls = getPrefixCls('agentic-md-editor', customPrefixCls);
|
|
@@ -344,7 +346,8 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
344
346
|
var codeRouter = function codeRouter(codeProps) {
|
|
345
347
|
return /*#__PURE__*/ React.createElement(DefaultCodeRouter, _object_spread_props(_object_spread({}, codeProps), {
|
|
346
348
|
pluginComponents: pluginComponents,
|
|
347
|
-
apaasifyRender: apaasifyRender
|
|
349
|
+
apaasifyRender: apaasifyRender,
|
|
350
|
+
fileMapConfig: fileMapConfig
|
|
348
351
|
}));
|
|
349
352
|
};
|
|
350
353
|
codeRouter.displayName = 'CodeRouter';
|
|
@@ -353,7 +356,8 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
353
356
|
}, pluginComponents);
|
|
354
357
|
}, [
|
|
355
358
|
pluginComponents,
|
|
356
|
-
apaasifyRender
|
|
359
|
+
apaasifyRender,
|
|
360
|
+
fileMapConfig
|
|
357
361
|
]);
|
|
358
362
|
// 流式缓存:将不完整的 Markdown token 暂缓,避免 parser 错误解析
|
|
359
363
|
var safeContent = useStreaming(displayedContent, streaming);
|
|
@@ -9,7 +9,7 @@ export { ChartBlockRenderer } from './renderers/ChartRenderer';
|
|
|
9
9
|
export { CodeBlockRenderer } from './renderers/CodeRenderer';
|
|
10
10
|
export { MermaidBlockRenderer } from './renderers/MermaidRenderer';
|
|
11
11
|
export { SchemaBlockRenderer } from './renderers/SchemaRenderer';
|
|
12
|
-
export type { CharacterQueueOptions, MarkdownRendererEleProps, MarkdownRendererProps, MarkdownRendererRef, RenderMode, RendererBlockProps, } from './types';
|
|
12
|
+
export type { CharacterQueueOptions, FileMapConfig, MarkdownRendererEleProps, MarkdownRendererProps, MarkdownRendererRef, RenderMode, RendererBlockProps, } from './types';
|
|
13
13
|
export type { UseMarkdownToReactOptions } from './markdownReactShared';
|
|
14
14
|
export { markdownToReactSync, useMarkdownToReact } from './useMarkdownToReact';
|
|
15
15
|
export { useStreamingMarkdownReact } from './streaming/useStreamingMarkdownReact';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { RendererBlockProps } from '../types';
|
|
2
|
+
import type { FileMapConfig, RendererBlockProps } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* ```agentic-ui-filemap``` 代码块 → FileMapView
|
|
5
5
|
*/
|
|
6
|
-
export declare const AgenticUiFileMapBlockRenderer: React.FC<RendererBlockProps
|
|
6
|
+
export declare const AgenticUiFileMapBlockRenderer: React.FC<RendererBlockProps & {
|
|
7
|
+
fileMapConfig?: FileMapConfig;
|
|
8
|
+
}>;
|