@ant-design/agentic-ui 2.30.13 → 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.
Files changed (29) 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 +5 -1
  11. package/dist/MarkdownEditor/editor/elements/Code/index.js +22 -14
  12. package/dist/MarkdownEditor/editor/parser/constants.d.ts +10 -0
  13. package/dist/MarkdownEditor/editor/parser/constants.js +46 -0
  14. package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.js +3 -1
  15. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +11 -0
  16. package/dist/MarkdownEditor/editor/utils/markdownToHtml.js +6 -4
  17. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +3 -1
  18. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.js +6 -1
  19. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +8 -0
  20. package/dist/MarkdownInputField/FileMapView/FileMapViewItem.js +20 -1
  21. package/dist/MarkdownInputField/FileMapView/index.js +35 -12
  22. package/dist/MarkdownInputField/FileMapView/style.js +6 -0
  23. package/dist/MarkdownInputField/style.js +7 -0
  24. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -2
  25. package/dist/MarkdownRenderer/useMarkdownToReact.js +2 -2
  26. package/dist/Plugins/chart/DonutChart/index.js +21 -7
  27. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +4 -0
  28. package/dist/Workspace/Browser/index.js +3 -1
  29. package/package.json +1 -2
@@ -212,7 +212,7 @@ function _ts_generator(thisArg, body) {
212
212
  };
213
213
  }
214
214
  }
215
- import { memo, useContext, useRef } from "react";
215
+ import { memo, useContext, useMemo, useRef } from "react";
216
216
  import { ConfigProvider, Flex } from "antd";
217
217
  import clsx from "clsx";
218
218
  import { nanoid } from "nanoid";
@@ -220,11 +220,13 @@ import React from "react";
220
220
  import { BubbleAvatar } from "./Avatar";
221
221
  import { BubbleBeforeNode } from "./BubbleBeforeNode";
222
222
  import { BubbleConfigContext } from "./BubbleConfigProvide";
223
+ import { ContentFilemapView } from "./ContentFilemapView";
223
224
  import { BubbleFileView } from "./FileView";
224
225
  import { BubbleMessageDisplay } from "./MessagesContent";
225
226
  import { MessagesContext } from "./MessagesContent/BubbleContext";
226
227
  import { LOADING_FLAT } from "./MessagesContent";
227
228
  import { BubbleExtra } from "./MessagesContent/BubbleExtra";
229
+ import { extractFilemapBlocks } from "./extractFilemapBlocks";
228
230
  import { useStyle } from "./style";
229
231
  import { BubbleTitle } from "./Title";
230
232
  var AI_PLACEMENT = 'left';
@@ -310,13 +312,20 @@ var getTaskList = function getTaskList(originData) {
310
312
  }
311
313
  }
312
314
  var messageDisplayKey = (_ref = (_messageDisplayKeyRef_current = messageDisplayKeyRef.current) !== null && _messageDisplayKeyRef_current !== void 0 ? _messageDisplayKeyRef_current : id) !== null && _ref !== void 0 ? _ref : nanoid();
315
+ var rawContent = props === null || props === void 0 ? void 0 : (_props_originData1 = props.originData) === null || _props_originData1 === void 0 ? void 0 : _props_originData1.content;
316
+ var _useMemo = useMemo(function() {
317
+ return extractFilemapBlocks(typeof rawContent === 'string' ? rawContent : '');
318
+ }, [
319
+ rawContent
320
+ ]), filemapBlocks = _useMemo.blocks, strippedContent = _useMemo.stripped;
321
+ var contentForDisplay = filemapBlocks.length > 0 ? strippedContent : rawContent;
313
322
  var messageContent = /*#__PURE__*/ React.createElement(BubbleMessageDisplay, {
314
323
  markdownRenderConfig: props.markdownRenderConfig,
315
324
  docListProps: props.docListProps,
316
325
  bubbleListRef: props.bubbleListRef,
317
326
  bubbleListItemExtraStyle: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
318
327
  bubbleRef: props.bubbleRef,
319
- content: props === null || props === void 0 ? void 0 : (_props_originData1 = props.originData) === null || _props_originData1 === void 0 ? void 0 : _props_originData1.content,
328
+ content: contentForDisplay,
320
329
  key: messageDisplayKey,
321
330
  "data-id": props === null || props === void 0 ? void 0 : (_props_originData2 = props.originData) === null || _props_originData2 === void 0 ? void 0 : _props_originData2.id,
322
331
  avatar: props === null || props === void 0 ? void 0 : (_props_originData3 = props.originData) === null || _props_originData3 === void 0 ? void 0 : _props_originData3.meta,
@@ -338,22 +347,22 @@ var getTaskList = function getTaskList(originData) {
338
347
  fileViewConfig: props.fileViewConfig,
339
348
  renderFileMoreAction: props.renderFileMoreAction,
340
349
  shouldShowVoice: props.shouldShowVoice,
341
- bubbleRenderConfig: props.bubbleRenderConfig,
342
- contentAfterDom: ((props === null || props === void 0 ? void 0 : (_props_originData6 = props.originData) === null || _props_originData6 === void 0 ? void 0 : (_props_originData_fileMap = _props_originData6.fileMap) === null || _props_originData_fileMap === void 0 ? void 0 : _props_originData_fileMap.size) || 0) > 0 ? /*#__PURE__*/ React.createElement("div", {
343
- style: _object_spread({
344
- minWidth: standalone ? 'min(296px,100%)' : '0px',
345
- paddingLeft: 12,
346
- maxWidth: '100%',
347
- width: '100%'
348
- }, styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle),
349
- className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
350
- "data-testid": "message-after"
351
- }, /*#__PURE__*/ React.createElement(BubbleFileView, {
352
- placement: placement,
353
- bubbleListRef: props.bubbleListRef,
354
- bubble: props
355
- })) : null
350
+ bubbleRenderConfig: props.bubbleRenderConfig
356
351
  });
352
+ var hasFileMap = ((props === null || props === void 0 ? void 0 : (_props_originData6 = props.originData) === null || _props_originData6 === void 0 ? void 0 : (_props_originData_fileMap = _props_originData6.fileMap) === null || _props_originData_fileMap === void 0 ? void 0 : _props_originData_fileMap.size) || 0) > 0;
353
+ var fileViewDom = hasFileMap ? /*#__PURE__*/ React.createElement("div", {
354
+ style: _object_spread({
355
+ minWidth: standalone ? 'min(296px,100%)' : '0px',
356
+ paddingLeft: 12,
357
+ maxWidth: '100%'
358
+ }, styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle),
359
+ className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
360
+ "data-testid": "message-after"
361
+ }, /*#__PURE__*/ React.createElement(BubbleFileView, {
362
+ placement: placement,
363
+ bubbleListRef: props.bubbleListRef,
364
+ bubble: props
365
+ })) : null;
357
366
  var childrenDom = runRender(bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.contentRender, props, messageContent);
358
367
  var taskList = getTaskList(originData);
359
368
  var shouldShowBeforeContent = shouldRenderBeforeContent(placement, originData === null || originData === void 0 ? void 0 : originData.role, context === null || context === void 0 ? void 0 : context.thoughtChain, taskList.length);
@@ -402,7 +411,12 @@ var getTaskList = function getTaskList(originData) {
402
411
  className: clsx("".concat(prefixClass, "-bubble-content"), "".concat(prefixClass, "-bubble-content-").concat(placement), "".concat(prefixClass, "-bubble-content-ai"), _define_property({}, "".concat(prefixClass, "-bubble-content-pure"), props.pure), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleListItemContentClassName, hashId),
403
412
  onDoubleClick: props.onDoubleClick,
404
413
  "data-testid": "message-content"
405
- }, childrenDom) : null, contentAfterDom)))));
414
+ }, childrenDom) : null, fileViewDom, contentAfterDom)), filemapBlocks.length > 0 && /*#__PURE__*/ React.createElement(ContentFilemapView, {
415
+ blocks: filemapBlocks,
416
+ fileViewConfig: props.fileViewConfig,
417
+ fileViewEvents: props.fileViewEvents,
418
+ placement: placement
419
+ }))));
406
420
  if ((bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.render) === false) return null;
407
421
  return /*#__PURE__*/ React.createElement(MessagesContext.Provider, {
408
422
  value: {
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import type { FilemapBlock } from './extractFilemapBlocks';
3
+ import type { BubbleProps } from './type';
4
+ /**
5
+ * 将从 markdown content 中提取出的 agentic-ui-filemap 块渲染为 FileMapView 列表。
6
+ * 渲染在气泡内容框外部,避免图片被包在带样式的气泡背景里。
7
+ */
8
+ export declare const ContentFilemapView: React.FC<{
9
+ blocks: FilemapBlock[];
10
+ fileViewConfig?: BubbleProps['fileViewConfig'];
11
+ fileViewEvents?: BubbleProps['fileViewEvents'];
12
+ placement?: 'left' | 'right';
13
+ style?: React.CSSProperties;
14
+ }>;
@@ -0,0 +1,95 @@
1
+ import json5 from "json5";
2
+ import React, { useMemo } from "react";
3
+ import { normalizeFileMapPropsFromJson } from "../MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils";
4
+ import partialParse from "../MarkdownEditor/editor/parser/json-parse";
5
+ import { FileMapView } from "../MarkdownInputField/FileMapView";
6
+ var parseBody = function parseBody(body) {
7
+ try {
8
+ return json5.parse(body || '{}');
9
+ } catch (unused) {
10
+ try {
11
+ return partialParse(body || '{}');
12
+ } catch (unused) {
13
+ return null;
14
+ }
15
+ }
16
+ };
17
+ var FilemapItem = function FilemapItem(param) {
18
+ var body = param.body, fileViewConfig = param.fileViewConfig, fileViewEvents = param.fileViewEvents, placement = param.placement;
19
+ var parsed = useMemo(function() {
20
+ return parseBody(body);
21
+ }, [
22
+ body
23
+ ]);
24
+ var _useMemo = useMemo(function() {
25
+ return normalizeFileMapPropsFromJson(parsed);
26
+ }, [
27
+ parsed
28
+ ]), fileList = _useMemo.fileList, className = _useMemo.className;
29
+ var fileMap = useMemo(function() {
30
+ return new Map(fileList.map(function(f) {
31
+ return [
32
+ f.uuid || f.name,
33
+ f
34
+ ];
35
+ }));
36
+ }, [
37
+ fileList
38
+ ]);
39
+ var defaultHandlers = useMemo(function() {
40
+ return {
41
+ onPreview: function onPreview(file) {
42
+ var url = (file === null || file === void 0 ? void 0 : file.previewUrl) || (file === null || file === void 0 ? void 0 : file.url);
43
+ if (url && typeof window !== 'undefined') window.open(url, '_blank');
44
+ },
45
+ onDownload: function onDownload(file) {
46
+ var url = (file === null || file === void 0 ? void 0 : file.url) || (file === null || file === void 0 ? void 0 : file.previewUrl);
47
+ if (!url || typeof document === 'undefined') return;
48
+ var link = document.createElement('a');
49
+ link.href = url;
50
+ link.download = (file === null || file === void 0 ? void 0 : file.name) || 'download';
51
+ document.body.appendChild(link);
52
+ link.click();
53
+ document.body.removeChild(link);
54
+ },
55
+ onViewAll: function onViewAll() {}
56
+ };
57
+ }, []);
58
+ var events = {};
59
+ try {
60
+ events = (fileViewEvents === null || fileViewEvents === void 0 ? void 0 : fileViewEvents(defaultHandlers)) || {};
61
+ } catch (unused) {}
62
+ if (parsed === null || fileMap.size === 0) return null;
63
+ return /*#__PURE__*/ React.createElement(FileMapView, {
64
+ fileMap: fileMap,
65
+ className: className !== null && className !== void 0 ? className : fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.className,
66
+ style: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.style,
67
+ placement: placement,
68
+ onPreview: events === null || events === void 0 ? void 0 : events.onPreview,
69
+ onDownload: events === null || events === void 0 ? void 0 : events.onDownload,
70
+ itemRender: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.itemRender,
71
+ maxDisplayCount: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.maxDisplayCount,
72
+ showMoreButton: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.showMoreButton,
73
+ customSlot: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.customSlot,
74
+ renderMoreAction: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.renderFileMoreAction
75
+ });
76
+ };
77
+ /**
78
+ * 将从 markdown content 中提取出的 agentic-ui-filemap 块渲染为 FileMapView 列表。
79
+ * 渲染在气泡内容框外部,避免图片被包在带样式的气泡背景里。
80
+ */ export var ContentFilemapView = function ContentFilemapView(param) {
81
+ var blocks = param.blocks, fileViewConfig = param.fileViewConfig, fileViewEvents = param.fileViewEvents, placement = param.placement, style = param.style;
82
+ if (blocks.length === 0) return null;
83
+ return /*#__PURE__*/ React.createElement("div", {
84
+ style: style,
85
+ "data-testid": "content-filemap-view"
86
+ }, blocks.map(function(block, i) {
87
+ return /*#__PURE__*/ React.createElement(FilemapItem, {
88
+ key: i,
89
+ body: block.body,
90
+ fileViewConfig: fileViewConfig,
91
+ fileViewEvents: fileViewEvents,
92
+ placement: placement
93
+ });
94
+ }));
95
+ };
@@ -61,6 +61,30 @@ function _object_spread(target) {
61
61
  }
62
62
  return target;
63
63
  }
64
+ function ownKeys(object, enumerableOnly) {
65
+ var keys = Object.keys(object);
66
+ if (Object.getOwnPropertySymbols) {
67
+ var symbols = Object.getOwnPropertySymbols(object);
68
+ if (enumerableOnly) {
69
+ symbols = symbols.filter(function(sym) {
70
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
71
+ });
72
+ }
73
+ keys.push.apply(keys, symbols);
74
+ }
75
+ return keys;
76
+ }
77
+ function _object_spread_props(target, source) {
78
+ source = source != null ? source : {};
79
+ if (Object.getOwnPropertyDescriptors) {
80
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
81
+ } else {
82
+ ownKeys(Object(source)).forEach(function(key) {
83
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
84
+ });
85
+ }
86
+ return target;
87
+ }
64
88
  function _sliced_to_array(arr, i) {
65
89
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
66
90
  }
@@ -72,15 +96,17 @@ function _unsupported_iterable_to_array(o, minLen) {
72
96
  if (n === "Map" || n === "Set") return Array.from(n);
73
97
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
74
98
  }
75
- import { memo, useContext } from "react";
99
+ import { memo, useContext, useMemo } from "react";
76
100
  import { ConfigProvider, Flex } from "antd";
77
101
  import clsx from "clsx";
78
102
  import React from "react";
79
103
  import { Quote } from "../Quote";
80
104
  import { BubbleConfigContext } from "./BubbleConfigProvide";
105
+ import { ContentFilemapView } from "./ContentFilemapView";
81
106
  import { BubbleMessageDisplay } from "./MessagesContent";
82
107
  import { MessagesContext } from "./MessagesContent/BubbleContext";
83
108
  import { BubbleExtra } from "./MessagesContent/BubbleExtra";
109
+ import { extractFilemapBlocks } from "./extractFilemapBlocks";
84
110
  import { useStyle } from "./style";
85
111
  import { runRender } from "./AIBubble";
86
112
  import { BubbleFileView } from "./FileView";
@@ -134,6 +160,12 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
134
160
  var time = (originData === null || originData === void 0 ? void 0 : originData.createAt) || props.time;
135
161
  var placement = USER_PLACEMENT;
136
162
  var hasFileMap = ((originData === null || originData === void 0 ? void 0 : (_originData_fileMap = originData.fileMap) === null || _originData_fileMap === void 0 ? void 0 : _originData_fileMap.size) || 0) > 0;
163
+ var rawContent = originData === null || originData === void 0 ? void 0 : originData.content;
164
+ var _useMemo = useMemo(function() {
165
+ return extractFilemapBlocks(typeof rawContent === 'string' ? rawContent : '');
166
+ }, [
167
+ rawContent
168
+ ]), filemapBlocks = _useMemo.blocks, strippedContent = _useMemo.stripped;
137
169
  var quoteElement = (quote === null || quote === void 0 ? void 0 : quote.quoteDescription) ? /*#__PURE__*/ React.createElement(Quote, quote) : null;
138
170
  var titleDom = runRender(bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.titleRender, props, /*#__PURE__*/ React.createElement(BubbleTitle, {
139
171
  quote: quoteElement,
@@ -151,7 +183,7 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
151
183
  bubbleListRef: props.bubbleListRef,
152
184
  bubbleListItemExtraStyle: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
153
185
  bubbleRef: props.bubbleRef,
154
- content: originData === null || originData === void 0 ? void 0 : originData.content,
186
+ content: filemapBlocks.length > 0 ? strippedContent : originData === null || originData === void 0 ? void 0 : originData.content,
155
187
  key: originData === null || originData === void 0 ? void 0 : originData.id,
156
188
  "data-id": originData === null || originData === void 0 ? void 0 : originData.id,
157
189
  avatar: originData === null || originData === void 0 ? void 0 : originData.meta,
@@ -211,15 +243,25 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
211
243
  className: clsx("".concat(prefixClass, "-bubble-content"), "".concat(prefixClass, "-bubble-content-").concat(placement), "".concat(prefixClass, "-bubble-content-user"), _define_property({}, "".concat(prefixClass, "-bubble-content-pure"), props.pure), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleListItemContentClassName, hashId),
212
244
  onDoubleClick: props.onDoubleClick,
213
245
  "data-testid": "message-content"
214
- }, childrenDom) : null, hasFileMap && /*#__PURE__*/ React.createElement("div", {
215
- style: fileViewStyle,
216
- className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
246
+ }, childrenDom) : null, contentAfterDom)), hasFileMap && /*#__PURE__*/ React.createElement("div", {
247
+ style: _object_spread_props(_object_spread({}, fileViewStyle), {
248
+ alignSelf: 'flex-end'
249
+ }),
250
+ className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-user"), hashId),
217
251
  "data-testid": "message-after"
218
252
  }, /*#__PURE__*/ React.createElement(BubbleFileView, {
219
253
  bubbleListRef: props.bubbleListRef,
220
254
  bubble: props,
221
255
  placement: placement
222
- })), contentAfterDom)))));
256
+ })), filemapBlocks.length > 0 && /*#__PURE__*/ React.createElement(ContentFilemapView, {
257
+ blocks: filemapBlocks,
258
+ fileViewConfig: props.fileViewConfig,
259
+ fileViewEvents: props.fileViewEvents,
260
+ placement: placement,
261
+ style: {
262
+ alignSelf: 'flex-end'
263
+ }
264
+ }))));
223
265
  if ((bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.render) === false) return null;
224
266
  return /*#__PURE__*/ React.createElement(MessagesContext.Provider, {
225
267
  value: {
@@ -0,0 +1,17 @@
1
+ export interface FilemapBlock {
2
+ raw: string;
3
+ body: string;
4
+ }
5
+ /**
6
+ * 从 markdown 字符串中提取所有 ```agentic-ui-filemap 代码块。
7
+ *
8
+ * 返回:
9
+ * - `blocks`:提取到的代码块列表,每项包含原始文本和内部 JSON body
10
+ * - `stripped`:移除了所有 filemap 块之后的干净 markdown 字符串
11
+ *
12
+ * 当消息内容中只含 filemap 块、没有其他文字时 `stripped` 为空字符串。
13
+ */
14
+ export declare const extractFilemapBlocks: (content: string) => {
15
+ blocks: FilemapBlock[];
16
+ stripped: string;
17
+ };
@@ -0,0 +1,23 @@
1
+ var FILEMAP_FENCE_RE = /^```agentic-ui-filemap[ \t]*\r?\n([\s\S]*?)^```[ \t]*$/gm;
2
+ /**
3
+ * 从 markdown 字符串中提取所有 ```agentic-ui-filemap 代码块。
4
+ *
5
+ * 返回:
6
+ * - `blocks`:提取到的代码块列表,每项包含原始文本和内部 JSON body
7
+ * - `stripped`:移除了所有 filemap 块之后的干净 markdown 字符串
8
+ *
9
+ * 当消息内容中只含 filemap 块、没有其他文字时 `stripped` 为空字符串。
10
+ */ export var extractFilemapBlocks = function extractFilemapBlocks(content) {
11
+ var blocks = [];
12
+ var stripped = content.replace(FILEMAP_FENCE_RE, function(raw, body) {
13
+ blocks.push({
14
+ raw: raw,
15
+ body: body.trim()
16
+ });
17
+ return '';
18
+ });
19
+ return {
20
+ blocks: blocks,
21
+ stripped: stripped.trim()
22
+ };
23
+ };
@@ -2,6 +2,7 @@ import { TooltipProps } from 'antd';
2
2
  import { ReactNode } from 'react';
3
3
  import { MarkdownEditorProps } from '../MarkdownEditor/types';
4
4
  import { AttachmentFile } from '../MarkdownInputField/AttachmentButton/types';
5
+ import type { FileMapViewProps } from '../MarkdownInputField/FileMapView';
5
6
  import { BaseStyleProps, BubbleMetaData, MessageBubbleData, MultiClassNameProps, MultiStyleProps, WithFalse } from '../Types';
6
7
  import type { UseSpeechAdapter } from './MessagesContent/VoiceButton';
7
8
  import { BubbleExtraProps } from './types/BubbleExtra';
@@ -406,6 +407,8 @@ export interface BubbleProps<T = Record<string, any>> extends BubbleItemStylePro
406
407
  className?: string;
407
408
  /** 自定义根容器样式 */
408
409
  style?: React.CSSProperties;
410
+ /** 自定义每个媒体(图片/视频)条目的渲染,透传 FileMapView */
411
+ itemRender?: FileMapViewProps['itemRender'];
409
412
  /** 最大展示条目数(默认 3) */
410
413
  maxDisplayCount?: number;
411
414
  /** 是否显示"查看更多"按钮 */
@@ -350,6 +350,8 @@ export declare function useLanguage(): {
350
350
  'suggestion.select': string;
351
351
  'suggestion.followUp': string;
352
352
  'input.fileUpload': string;
353
+ 'input.attachmentListTitle': string;
354
+ 'chat.fileMapTitle': string;
353
355
  'input.voiceInput': string;
354
356
  'input.voiceInputting': string;
355
357
  'input.placeholder': string;
@@ -312,6 +312,8 @@ export declare const cnLabels: {
312
312
  'suggestion.select': string;
313
313
  'suggestion.followUp': string;
314
314
  'input.fileUpload': string;
315
+ 'input.attachmentListTitle': string;
316
+ 'chat.fileMapTitle': string;
315
317
  'input.voiceInput': string;
316
318
  'input.voiceInputting': string;
317
319
  'input.placeholder': string;
@@ -332,6 +332,8 @@
332
332
  'suggestion.followUp': '追问',
333
333
  // MarkdownInputField related
334
334
  'input.fileUpload': '文件上传',
335
+ 'input.attachmentListTitle': '上传附件',
336
+ 'chat.fileMapTitle': '结果文件',
335
337
  'input.voiceInput': '语音输入',
336
338
  'input.voiceInputting': '语音输入中,点击可停止。',
337
339
  'input.placeholder': '请输入',
@@ -757,7 +759,9 @@
757
759
  'suggestion.select': 'Select suggestion',
758
760
  'suggestion.followUp': 'Follow-up',
759
761
  // MarkdownInputField related
760
- 'input.fileUpload': 'File upload',
762
+ 'input.fileUpload': 'Upload attachments',
763
+ 'input.attachmentListTitle': 'Uploaded attachments',
764
+ 'chat.fileMapTitle': 'Result files',
761
765
  'input.voiceInput': 'Voice input',
762
766
  'input.voiceInputting': 'Voice input in progress, click to stop.',
763
767
  'input.placeholder': 'Please input',
@@ -55,7 +55,7 @@ import React from "react";
55
55
  import { debugInfo } from "../../../../Utils/debugUtils";
56
56
  export var Code = function Code(param) {
57
57
  var attributes = param.attributes, children = param.children, element = param.element;
58
- var _element_value, _element_otherProps, _element_otherProps1, _element_otherProps2, _element_otherProps3, _element_value1;
58
+ var _element_value, _element_otherProps, _element_otherProps1, _element_otherProps2;
59
59
  debugInfo('Code - 渲染代码块', {
60
60
  language: element === null || element === void 0 ? void 0 : element.language,
61
61
  valueLength: element === null || element === void 0 ? void 0 : (_element_value = element.value) === null || _element_value === void 0 ? void 0 : _element_value.length,
@@ -63,24 +63,31 @@ export var Code = function Code(param) {
63
63
  finished: element === null || element === void 0 ? void 0 : (_element_otherProps1 = element.otherProps) === null || _element_otherProps1 === void 0 ? void 0 : _element_otherProps1.finished
64
64
  });
65
65
  if ((element === null || element === void 0 ? void 0 : element.language) === 'html') {
66
- var _element_otherProps4, _element_otherProps5, _element_otherProps6, _element_value2;
66
+ var _element_otherProps3, _element_otherProps4, _element_otherProps5, _element_value1;
67
67
  debugInfo('Code - HTML 代码块', {
68
- isConfig: element === null || element === void 0 ? void 0 : (_element_otherProps4 = element.otherProps) === null || _element_otherProps4 === void 0 ? void 0 : _element_otherProps4.isConfig
68
+ isConfig: element === null || element === void 0 ? void 0 : (_element_otherProps3 = element.otherProps) === null || _element_otherProps3 === void 0 ? void 0 : _element_otherProps3.isConfig
69
69
  });
70
70
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, attributes), {
71
71
  style: {
72
- display: (element === null || element === void 0 ? void 0 : (_element_otherProps5 = element.otherProps) === null || _element_otherProps5 === void 0 ? void 0 : _element_otherProps5.isConfig) ? 'none' : 'block'
72
+ display: (element === null || element === void 0 ? void 0 : (_element_otherProps4 = element.otherProps) === null || _element_otherProps4 === void 0 ? void 0 : _element_otherProps4.isConfig) ? 'none' : 'block'
73
73
  }
74
- }), (element === null || element === void 0 ? void 0 : (_element_otherProps6 = element.otherProps) === null || _element_otherProps6 === void 0 ? void 0 : _element_otherProps6.isConfig) ? '' : DOMPurify.sanitize(element === null || element === void 0 ? void 0 : (_element_value2 = element.value) === null || _element_value2 === void 0 ? void 0 : _element_value2.trim()));
74
+ }), (element === null || element === void 0 ? void 0 : (_element_otherProps5 = element.otherProps) === null || _element_otherProps5 === void 0 ? void 0 : _element_otherProps5.isConfig) ? null : /*#__PURE__*/ React.createElement("div", {
75
+ contentEditable: false,
76
+ dangerouslySetInnerHTML: {
77
+ __html: DOMPurify.sanitize((element === null || element === void 0 ? void 0 : (_element_value1 = element.value) === null || _element_value1 === void 0 ? void 0 : _element_value1.trim()) || '')
78
+ }
79
+ }), /*#__PURE__*/ React.createElement("span", {
80
+ style: {
81
+ display: 'none'
82
+ }
83
+ }, children));
75
84
  }
76
85
  // 检查代码块是否未闭合
77
86
  var isUnclosed = (element === null || element === void 0 ? void 0 : (_element_otherProps2 = element.otherProps) === null || _element_otherProps2 === void 0 ? void 0 : _element_otherProps2.finished) === false;
78
87
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, attributes), {
79
88
  "data-is-unclosed": isUnclosed,
80
89
  "data-language": element === null || element === void 0 ? void 0 : element.language,
81
- style: (element === null || element === void 0 ? void 0 : element.language) === 'html' ? {
82
- display: (element === null || element === void 0 ? void 0 : (_element_otherProps3 = element.otherProps) === null || _element_otherProps3 === void 0 ? void 0 : _element_otherProps3.isConfig) ? 'none' : 'block'
83
- } : {
90
+ style: {
84
91
  height: '240px',
85
92
  minWidth: '398px',
86
93
  maxWidth: '800px',
@@ -93,17 +100,18 @@ export var Code = function Code(param) {
93
100
  color: 'rgb(27, 27, 27)',
94
101
  padding: '1em',
95
102
  margin: '1em 0',
96
- fontSize: '0.8em',
103
+ fontSize: '1em',
97
104
  lineHeight: '1.5',
98
105
  overflowX: 'auto',
99
- whiteSpace: 'pre-wrap',
100
- wordBreak: 'break-all',
101
- fontFamily: "'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace",
102
- wordWrap: 'break-word',
103
106
  borderRadius: '12px',
104
107
  background: '#FFFFFF',
105
108
  boxShadow: 'var(--shadow-control-base)',
106
109
  position: 'relative'
107
110
  }
108
- }), (element === null || element === void 0 ? void 0 : (_element_value1 = element.value) === null || _element_value1 === void 0 ? void 0 : _element_value1.trim()) || children);
111
+ }), /*#__PURE__*/ React.createElement("div", {
112
+ style: {
113
+ width: '100%',
114
+ height: '100%'
115
+ }
116
+ }, children));
109
117
  };
@@ -3,6 +3,16 @@
3
3
  * 在 markdown 解析前替换,渲染与序列化时还原为 $。
4
4
  */
5
5
  export declare const JINJA_DOLLAR_PLACEHOLDER = "\uE01A";
6
+ /**
7
+ * 将行首的双冒号写法规范化为三冒号,使其能被 remarkDirectiveContainersOnly 正确解析。
8
+ *
9
+ * 处理两种模式:
10
+ * - `::name` → `:::name`(开启行,后跟合法标识符字母)
11
+ * - `::` 单独一行 → `:::`(关闭行,行首恰好两个冒号且后无非空字符)
12
+ *
13
+ * 代码围栏内的行不处理。
14
+ */
15
+ export declare function preprocessNormalizeLeafToContainerDirective(markdown: string): string;
6
16
  /**
7
17
  * 保护时间格式(如 02:20:31)不被 remark-directive 误解析为 textDirective。
8
18
  * remark-directive 会将 ":20"、":31" 等解析为指令,导致 "Cannot handle unknown node textDirective"。
@@ -58,6 +58,52 @@ function protectLineFromDirectiveTime(markdownLine) {
58
58
  }
59
59
  return result;
60
60
  }
61
+ /**
62
+ * 将行首的双冒号写法规范化为三冒号,使其能被 remarkDirectiveContainersOnly 正确解析。
63
+ *
64
+ * 处理两种模式:
65
+ * - `::name` → `:::name`(开启行,后跟合法标识符字母)
66
+ * - `::` 单独一行 → `:::`(关闭行,行首恰好两个冒号且后无非空字符)
67
+ *
68
+ * 代码围栏内的行不处理。
69
+ */ export function preprocessNormalizeLeafToContainerDirective(markdown) {
70
+ if (!markdown || markdown.length === 0) return markdown;
71
+ var lines = markdown.split('\n');
72
+ var inFence = false;
73
+ var out = [];
74
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
75
+ try {
76
+ for(var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
77
+ var line = _step.value;
78
+ if (FENCE_DELIMITER_LINE.test(line)) {
79
+ inFence = !inFence;
80
+ out.push(line);
81
+ continue;
82
+ }
83
+ if (!inFence && /^:{2}(?!:)[a-zA-Z]/.test(line)) {
84
+ out.push(':' + line);
85
+ } else if (!inFence && /^:{2}\s*$/.test(line)) {
86
+ out.push(':::');
87
+ } else {
88
+ out.push(line);
89
+ }
90
+ }
91
+ } catch (err) {
92
+ _didIteratorError = true;
93
+ _iteratorError = err;
94
+ } finally{
95
+ try {
96
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
97
+ _iterator.return();
98
+ }
99
+ } finally{
100
+ if (_didIteratorError) {
101
+ throw _iteratorError;
102
+ }
103
+ }
104
+ }
105
+ return out.join('\n');
106
+ }
61
107
  /**
62
108
  * 保护时间格式(如 02:20:31)不被 remark-directive 误解析为 textDirective。
63
109
  * remark-directive 会将 ":20"、":31" 等解析为指令,导致 "Cannot handle unknown node textDirective"。
@@ -108,6 +108,7 @@ import { handleHtml, preprocessNonStandardHtmlTags, preprocessThinkTags } from "
108
108
  import { handleInlineMath, handleMath } from "./parse/parseMath";
109
109
  import { handleImage } from "./parse/parseMedia";
110
110
  import { parseTableOrChart, preprocessMarkdownTableNewlines } from "./parse/parseTable";
111
+ import { preprocessNormalizeLeafToContainerDirective } from "./constants";
111
112
  import mdastParser from "./remarkParse";
112
113
  // 全局解析缓存
113
114
  var parseCache = new Map();
@@ -237,7 +238,8 @@ var removeAnswerTags = function removeAnswerTags(text) {
237
238
  value: function preprocessMarkdown(md) {
238
239
  var thinkProcessed = removeAnswerTags(preprocessThinkTags(md || ''));
239
240
  var nonStandardProcessed = removeAnswerTags(preprocessNonStandardHtmlTags(thinkProcessed));
240
- return preprocessMarkdownTableNewlines(nonStandardProcessed);
241
+ var tableProcessed = preprocessMarkdownTableNewlines(nonStandardProcessed);
242
+ return preprocessNormalizeLeafToContainerDirective(tableProcessed);
241
243
  }
242
244
  },
243
245
  {
@@ -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(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) {
@@ -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'
@@ -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',
@@ -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',
@@ -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',
@@ -1,4 +1,4 @@
1
- import { JINJA_DOLLAR_PLACEHOLDER } from "../../MarkdownEditor/editor/parser/constants";
1
+ import { JINJA_DOLLAR_PLACEHOLDER, preprocessNormalizeLeafToContainerDirective } from "../../MarkdownEditor/editor/parser/constants";
2
2
  import React, { useMemo, useRef } from "react";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
4
  import { buildEditorAlignedComponents, createHastProcessor, splitMarkdownBlocks } from "../markdownReactShared";
@@ -38,7 +38,7 @@ import { shouldResetRevisionProgress } from "./revisionPolicy";
38
38
  }
39
39
  prevRevisionRef.current = revisionSource;
40
40
  try {
41
- var preprocessed = content.replace(new RegExp(JINJA_DOLLAR_PLACEHOLDER, 'g'), '$');
41
+ var preprocessed = preprocessNormalizeLeafToContainerDirective(content.replace(new RegExp(JINJA_DOLLAR_PLACEHOLDER, 'g'), '$'));
42
42
  var blocks = splitMarkdownBlocks(preprocessed);
43
43
  if (blocks.length === 0) return null;
44
44
  var gen = revisionGenerationRef.current;
@@ -1,6 +1,6 @@
1
1
  import { toJsxRuntime } from "hast-util-to-jsx-runtime";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { JINJA_DOLLAR_PLACEHOLDER } from "../MarkdownEditor/editor/parser/constants";
3
+ import { JINJA_DOLLAR_PLACEHOLDER, preprocessNormalizeLeafToContainerDirective } from "../MarkdownEditor/editor/parser/constants";
4
4
  import { buildEditorAlignedComponents, createHastProcessor } from "./markdownReactShared";
5
5
  import { useStreamingMarkdownReact } from "./streaming/useStreamingMarkdownReact";
6
6
  export var useMarkdownToReact = useStreamingMarkdownReact;
@@ -10,7 +10,7 @@ export var useMarkdownToReact = useStreamingMarkdownReact;
10
10
  if (!content) return null;
11
11
  try {
12
12
  var processor = createHastProcessor(remarkPlugins, htmlConfig);
13
- var preprocessed = content.replace(new RegExp(JINJA_DOLLAR_PLACEHOLDER, 'g'), '$');
13
+ var preprocessed = preprocessNormalizeLeafToContainerDirective(content.replace(new RegExp(JINJA_DOLLAR_PLACEHOLDER, 'g'), '$'));
14
14
  var mdast = processor.parse(preprocessed);
15
15
  var hast = processor.runSync(mdast);
16
16
  var userComps = components || {};
@@ -476,8 +476,22 @@ import { useStyle } from "./style";
476
476
  ];
477
477
  }
478
478
  var hiddenSetForChart = hiddenDataIndicesByChart[idx] || new Set();
479
- var visibleData = chartData.filter(function(_, index) {
480
- return !hiddenSetForChart.has(index);
479
+ var visibleDataWithIndex = chartData.map(function(d, index) {
480
+ return {
481
+ d: d,
482
+ originalIndex: index
483
+ };
484
+ }).filter(function(param) {
485
+ var originalIndex = param.originalIndex;
486
+ return !hiddenSetForChart.has(originalIndex);
487
+ });
488
+ var visibleData = visibleDataWithIndex.map(function(param) {
489
+ var d = param.d;
490
+ return d;
491
+ });
492
+ var visibleOriginalIndices = visibleDataWithIndex.map(function(param) {
493
+ var originalIndex = param.originalIndex;
494
+ return originalIndex;
481
495
  });
482
496
  var toNum = function toNum(v) {
483
497
  return typeof v === 'number' ? v : Number(v);
@@ -498,9 +512,9 @@ import { useStyle } from "./style";
498
512
  return sum + (Number.isFinite(v) ? v : 0);
499
513
  }, 0);
500
514
  var backgroundColors = cfg.backgroundColor || defaultColorList;
501
- // 解析 CSS 变量为实际颜色值(Canvas 需要实际颜色值)
502
- var resolvedBackgroundColors = backgroundColors.map(function(color) {
503
- return resolveCssVariable(color);
515
+ // 解析 CSS 变量为实际颜色值(Canvas 需要实际颜色值),按原始索引取色保证与图例颜色一致
516
+ var resolvedVisibleBackgroundColors = visibleOriginalIndices.map(function(originalIndex) {
517
+ return resolveCssVariable(backgroundColors[originalIndex % backgroundColors.length]);
504
518
  });
505
519
  var mainColor = (_ref = (_cfg_backgroundColor = cfg.backgroundColor) === null || _cfg_backgroundColor === void 0 ? void 0 : _cfg_backgroundColor[0]) !== null && _ref !== void 0 ? _ref : defaultColorList[idx % defaultColorList.length];
506
520
  var resolvedMainColor = resolveCssVariable(mainColor);
@@ -557,12 +571,12 @@ import { useStyle } from "./style";
557
571
  backgroundColor: isSingleValueMode ? [
558
572
  resolvedMainColor,
559
573
  'transparent'
560
- ] : resolvedBackgroundColors.slice(0, values.length),
574
+ ] : resolvedVisibleBackgroundColors.slice(0, values.length),
561
575
  borderColor: chartBorderColor,
562
576
  hoverBackgroundColor: isSingleValueMode ? [
563
577
  resolvedMainColor,
564
578
  'transparent'
565
- ] : resolvedBackgroundColors.slice(0, values.length),
579
+ ] : resolvedVisibleBackgroundColors.slice(0, values.length),
566
580
  hoverBorderColor: chartHoverBorderColor,
567
581
  borderWidth: cfg.chartStyle === 'pie' ? 0 : isMobile ? 1 : 1,
568
582
  spacing: isSingleValueMode ? 0 : cfg.chartStyle === 'pie' ? 0 : isDarkTheme ? isMobile ? 4 : 8 : isMobile ? 3 : 6,
@@ -351,6 +351,8 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
351
351
  'suggestion.select': string;
352
352
  'suggestion.followUp': string;
353
353
  'input.fileUpload': string;
354
+ 'input.attachmentListTitle': string;
355
+ 'chat.fileMapTitle': string;
354
356
  'input.voiceInput': string;
355
357
  'input.voiceInputting': string;
356
358
  'input.placeholder': string;
@@ -745,6 +747,8 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
745
747
  'suggestion.select': string;
746
748
  'suggestion.followUp': string;
747
749
  'input.fileUpload': string;
750
+ 'input.attachmentListTitle': string;
751
+ 'chat.fileMapTitle': string;
748
752
  'input.voiceInput': string;
749
753
  'input.voiceInputting': string;
750
754
  'input.placeholder': string;
@@ -151,14 +151,16 @@ export var BrowserItemComponent = function BrowserItemComponent(param) {
151
151
  var _useBrowserContext = useBrowserContext(), prefixCls = _useBrowserContext.prefixCls, wrapSSR = _useBrowserContext.wrapSSR, hashId = _useBrowserContext.hashId;
152
152
  var locale = useContext(I18nContext).locale;
153
153
  var handleOpen = function handleOpen(e) {
154
+ e.preventDefault();
155
+ e.stopPropagation();
154
156
  if (onOpen) {
155
- e.preventDefault();
156
157
  onOpen(item);
157
158
  return;
158
159
  }
159
160
  window.open(item.url, '_blank', 'noopener,noreferrer');
160
161
  };
161
162
  var handleLocate = function handleLocate(e) {
163
+ e.preventDefault();
162
164
  e.stopPropagation();
163
165
  onLocate === null || onLocate === void 0 ? void 0 : onLocate(item);
164
166
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.30.13",
3
+ "version": "2.30.14",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",
@@ -24,7 +24,6 @@
24
24
  "lint:css": "stylelint \"{src,test}/**/*.{css,less}\"",
25
25
  "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
26
26
  "prepare": "husky install && dumi setup",
27
- "prepublishOnly": "npm run build && npm run test",
28
27
  "prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
29
28
  "preview": "pnpm dumi preview",
30
29
  "report:demo": "node scripts/generateDemoReport.js",