@ant-design/agentic-ui 2.30.11 → 2.30.13

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 (54) hide show
  1. package/dist/Bubble/MessagesContent/MarkdownPreview.js +3 -2
  2. package/dist/Bubble/MessagesContent/style.js +3 -1
  3. package/dist/Bubble/style.js +35 -13
  4. package/dist/ChatLayout/index.js +9 -1
  5. package/dist/History/components/HistoryList.d.ts +2 -12
  6. package/dist/History/components/HistoryList.js +48 -43
  7. package/dist/History/style.d.ts +4 -0
  8. package/dist/History/style.js +1 -0
  9. package/dist/Hooks/useAutoScroll.js +38 -14
  10. package/dist/Hooks/useLanguage.d.ts +1 -0
  11. package/dist/I18n/locales.d.ts +1 -0
  12. package/dist/I18n/locales.js +2 -0
  13. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.d.ts +4 -0
  14. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.js +83 -0
  15. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +14 -0
  16. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +52 -0
  17. package/dist/MarkdownEditor/editor/elements/index.js +3 -0
  18. package/dist/MarkdownEditor/editor/parser/parse/parseCode.js +2 -1
  19. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +1 -0
  20. package/dist/MarkdownEditor/editor/plugins/handlePaste.js +2 -1
  21. package/dist/MarkdownEditor/types.d.ts +6 -0
  22. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +2 -2
  23. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +3 -1
  24. package/dist/MarkdownInputField/AttachmentButton/index.d.ts +12 -0
  25. package/dist/MarkdownInputField/AttachmentButton/index.js +23 -13
  26. package/dist/MarkdownInputField/FileMapView/index.d.ts +13 -1
  27. package/dist/MarkdownInputField/FileMapView/index.js +24 -8
  28. package/dist/MarkdownInputField/FileUploadManager/index.js +4 -26
  29. package/dist/MarkdownRenderer/MarkdownRenderer.js +16 -5
  30. package/dist/MarkdownRenderer/index.d.ts +4 -1
  31. package/dist/MarkdownRenderer/index.js +3 -0
  32. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +8 -0
  33. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +121 -0
  34. package/dist/MarkdownRenderer/renderers/ChartRenderer.js +9 -0
  35. package/dist/MarkdownRenderer/renderers/index.d.ts +3 -0
  36. package/dist/MarkdownRenderer/renderers/index.js +3 -0
  37. package/dist/MarkdownRenderer/types.d.ts +45 -2
  38. package/dist/Plugins/chart/ChartRender.js +30 -9
  39. package/dist/Plugins/chart/HistogramChart/index.d.ts +5 -1
  40. package/dist/Plugins/chart/HistogramChart/index.js +79 -12
  41. package/dist/Plugins/chart/ScatterChart/index.d.ts +8 -0
  42. package/dist/Plugins/chart/ScatterChart/index.js +78 -8
  43. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
  44. package/dist/Plugins/code/components/AceEditor.js +69 -8
  45. package/dist/Plugins/code/components/CodeRenderer.js +22 -7
  46. package/dist/Plugins/code/components/CodeToolbar.d.ts +2 -0
  47. package/dist/Plugins/code/components/CodeToolbar.js +11 -4
  48. package/dist/Plugins/code/hooks/useToolbarConfig.d.ts +3 -1
  49. package/dist/Plugins/code/hooks/useToolbarConfig.js +5 -3
  50. package/dist/Plugins/code/utils/index.d.ts +1 -0
  51. package/dist/Plugins/code/utils/index.js +1 -0
  52. package/dist/Plugins/code/utils/localPreview.d.ts +12 -0
  53. package/dist/Plugins/code/utils/localPreview.js +190 -0
  54. package/package.json +1 -1
@@ -125,7 +125,7 @@ import { MessagesContext } from "./BubbleContext";
125
125
  var _content_includes, _htmlRef_current, _htmlRef_current1, _props_markdownRenderConfig, _props_originData, _props_originData1, _props_originData2, _props_markdownRenderConfig1, _props_markdownRenderConfig2, _props_markdownRenderConfig3;
126
126
  // MarkdownRenderer 渲染路径——轻量,不创建 Slate 实例
127
127
  if (renderMode === 'markdown') {
128
- var _props_originData3, _props_markdownRenderConfig4, _props_markdownRenderConfig5, _props_markdownRenderConfig6, _props_markdownRenderConfig7, _props_markdownRenderConfig8, _props_markdownRenderConfig9;
128
+ var _props_originData3, _props_markdownRenderConfig4, _props_markdownRenderConfig5, _props_markdownRenderConfig6, _props_markdownRenderConfig7, _props_markdownRenderConfig8, _props_markdownRenderConfig9, _props_markdownRenderConfig10;
129
129
  return /*#__PURE__*/ React.createElement(MarkdownRenderer, {
130
130
  content: content,
131
131
  streaming: typing,
@@ -140,7 +140,8 @@ import { MessagesContext } from "./BubbleContext";
140
140
  margin: isPaddingHidden ? 0 : undefined
141
141
  }, ((_props_markdownRenderConfig7 = props.markdownRenderConfig) === null || _props_markdownRenderConfig7 === void 0 ? void 0 : _props_markdownRenderConfig7.style) || {}),
142
142
  codeProps: (_props_markdownRenderConfig8 = props.markdownRenderConfig) === null || _props_markdownRenderConfig8 === void 0 ? void 0 : _props_markdownRenderConfig8.codeProps,
143
- apaasify: (_props_markdownRenderConfig9 = props.markdownRenderConfig) === null || _props_markdownRenderConfig9 === void 0 ? void 0 : _props_markdownRenderConfig9.apaasify
143
+ apaasify: (_props_markdownRenderConfig9 = props.markdownRenderConfig) === null || _props_markdownRenderConfig9 === void 0 ? void 0 : _props_markdownRenderConfig9.apaasify,
144
+ fileMapConfig: (_props_markdownRenderConfig10 = props.markdownRenderConfig) === null || _props_markdownRenderConfig10 === void 0 ? void 0 : _props_markdownRenderConfig10.fileMapConfig
144
145
  });
145
146
  }
146
147
  // Slate 渲染路径——保持向后兼容
@@ -55,6 +55,7 @@ var THINKING_DOT_SIZE = 4;
55
55
  var THINKING_DOT_GAP = 4;
56
56
  var THINKING_DOT_ANIMATION = 'agenticBubbleThinkingDotPulse';
57
57
  var THINKING_DOT_ANIMATION_DURATION = '1.2s';
58
+ var THINKING_LOADING_MARGIN_TOP = 'var(--padding-2x)';
58
59
  var THINKING_LOADING_PADDING = {
59
60
  paddingLeft: 'var(--padding-5x)',
60
61
  paddingRight: 'var(--padding-5x)',
@@ -68,7 +69,8 @@ var genStyle = function genStyle(token) {
68
69
  lineHeight: '24px',
69
70
  display: 'flex',
70
71
  alignItems: 'center',
71
- gap: 'var(--padding-2x)'
72
+ gap: 'var(--padding-2x)',
73
+ marginTop: THINKING_LOADING_MARGIN_TOP
72
74
  }, THINKING_LOADING_PADDING), (_obj = {
73
75
  color: 'rgb(102, 111, 141)'
74
76
  }, _define_property(_obj, "&-dots", {
@@ -52,7 +52,7 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import { resetComponent, useEditorStyleRegister } from "../Hooks/useStyle";
54
54
  var genStyle = function genStyle(token, classNames) {
55
- var _obj;
55
+ var _obj, _obj1, _obj2;
56
56
  return _define_property({}, token.componentCls, {
57
57
  '&-bubble': {
58
58
  position: 'relative',
@@ -186,16 +186,27 @@ var genStyle = function genStyle(token, classNames) {
186
186
  minWidth: '0px',
187
187
  maxWidth: 'min(860px,100%)'
188
188
  },
189
- '&-bubble-content-right': {
189
+ '&-bubble-content-right': (_obj1 = {
190
190
  maxWidth: '75%',
191
191
  borderRadius: '16px 16px 2px 16px',
192
192
  background: 'var(--color-primary-control-fill-secondary-active)',
193
193
  color: 'var(--color-gray-text-default)',
194
- boxShadow: 'none',
195
- '&&-pure': {
196
- background: 'var(--color-primary-control-fill-primary)'
197
- }
198
- },
194
+ boxShadow: 'none'
195
+ }, // inline-code 基础规则用 code.cls(元素+类)选择器,需匹配相同结构才能覆盖
196
+ _define_property(_obj1, "& code".concat(token.antCls, "-agentic-md-editor-content-inline-code"), {
197
+ background: 'var(--color-primary-a7)'
198
+ }), // blockquote 竖条:gray-control-fill-secondary(gray-a2)在蓝色背景上消失
199
+ _define_property(_obj1, "& ".concat(token.antCls, "-agentic-md-editor-content blockquote::before"), {
200
+ backgroundColor: 'var(--color-primary-a7)'
201
+ }), // hr 分割线:gray-border-light(gray-a3)在蓝色背景上不可见
202
+ _define_property(_obj1, "& ".concat(token.antCls, "-agentic-md-editor-content hr"), {
203
+ borderTopColor: 'var(--color-primary-a7)'
204
+ }), // 链接下划线:gray-border-light 在蓝色背景上不可见
205
+ _define_property(_obj1, "& ".concat(token.antCls, "-agentic-md-editor-content a"), {
206
+ textDecorationColor: 'var(--color-primary-a7)'
207
+ }), _define_property(_obj1, '&&-pure', {
208
+ background: 'var(--color-primary-control-fill-primary)'
209
+ }), _obj1),
199
210
  // 用户消息特定样式
200
211
  '&-bubble-user': {
201
212
  marginBlockStart: -20,
@@ -207,15 +218,26 @@ var genStyle = function genStyle(token, classNames) {
207
218
  alignItems: 'flex-end',
208
219
  maxWidth: 'max(668px,75%)'
209
220
  },
210
- '&-content-user': {
221
+ '&-content-user': (_obj2 = {
211
222
  background: 'var(--color-primary-bg-card-light)',
212
223
  color: 'var(--color-gray-text-default)',
213
224
  borderRadius: '12px 12px 2px 12px',
214
- maxWidth: '668px',
215
- '&&-pure': {
216
- background: 'var(--color-primary-control-fill-primary)'
217
- }
218
- },
225
+ maxWidth: '668px'
226
+ }, // inline-code 基础规则用 code.cls(元素+类)选择器,需匹配相同结构才能覆盖
227
+ _define_property(_obj2, "& code".concat(token.antCls, "-agentic-md-editor-content-inline-code"), {
228
+ background: 'var(--color-primary-control-fill-secondary-active)'
229
+ }), // blockquote 竖条:gray-control-fill-secondary(gray-a2)在浅蓝背景上消失
230
+ _define_property(_obj2, "& ".concat(token.antCls, "-agentic-md-editor-content blockquote::before"), {
231
+ backgroundColor: 'var(--color-primary-control-fill-primary)'
232
+ }), // hr 分割线:gray-border-light(gray-a3)在浅蓝背景上不可见
233
+ _define_property(_obj2, "& ".concat(token.antCls, "-agentic-md-editor-content hr"), {
234
+ borderTopColor: 'var(--color-primary-a5)'
235
+ }), // 链接下划线:gray-border-light 在浅蓝背景上不可见
236
+ _define_property(_obj2, "& ".concat(token.antCls, "-agentic-md-editor-content a"), {
237
+ textDecorationColor: 'var(--color-primary-a5)'
238
+ }), _define_property(_obj2, '&&-pure', {
239
+ background: 'var(--color-primary-control-fill-primary)'
240
+ }), _obj2),
219
241
  '&-before-user': {
220
242
  justifyContent: 'flex-end'
221
243
  },
@@ -28,7 +28,7 @@ function _object_spread(target) {
28
28
  }
29
29
  import { ConfigProvider } from "antd";
30
30
  import clsx from "clsx";
31
- import React, { forwardRef, memo, useContext, useImperativeHandle, useRef } from "react";
31
+ import React, { forwardRef, memo, useContext, useEffect, useImperativeHandle, useRef } from "react";
32
32
  import { LayoutHeader } from "../Components/LayoutHeader";
33
33
  import useAutoScroll from "../Hooks/useAutoScroll";
34
34
  import { useElementSize } from "../Hooks/useElementSize";
@@ -117,6 +117,14 @@ import { useStyle } from "./style";
117
117
  scrollToBottom: scrollToBottom
118
118
  };
119
119
  });
120
+ // footer 实际高度变化时(spacer 随之调整),保持列表贴底
121
+ useEffect(function() {
122
+ if (actualFooterHeight > 0) {
123
+ scrollToBottom();
124
+ }
125
+ }, [
126
+ actualFooterHeight
127
+ ]);
120
128
  var rootClassName = clsx(prefixCls, className, classNames === null || classNames === void 0 ? void 0 : classNames.root, hashId);
121
129
  var contentClassName = clsx("".concat(prefixCls, "-content"), classNames === null || classNames === void 0 ? void 0 : classNames.content, hashId);
122
130
  var scrollableClassName = clsx("".concat(prefixCls, "-content-scrollable"), classNames === null || classNames === void 0 ? void 0 : classNames.scrollable, hashId);
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { MenuItemType } from '../menu';
2
2
  import { HistoryListConfig } from '../types/HistoryList';
3
3
  /**
4
4
  * 生成历史记录菜单项
@@ -47,14 +47,4 @@ import { HistoryListConfig } from '../types/HistoryList';
47
47
  * - 支持多选和收藏功能
48
48
  * - 支持运行状态图标显示
49
49
  */
50
- export declare const generateHistoryItems: ({ filteredList, selectedIds, onSelectionChange, onClick, onDeleteItem, agent, onFavorite, extra, customDateFormatter, groupBy, sessionSort, groupLabelRender, type, runningId, customOperationExtra, itemDateFormatter, }: HistoryListConfig) => {
51
- key: string;
52
- type: "group";
53
- label: React.ReactNode;
54
- children: {
55
- key: string;
56
- type: "item";
57
- onClick: () => void;
58
- label: React.JSX.Element;
59
- }[];
60
- }[];
50
+ export declare const generateHistoryItems: ({ filteredList, selectedIds, onSelectionChange, onClick, onDeleteItem, agent, onFavorite, extra, customDateFormatter, groupBy, sessionSort, groupLabelRender, type, runningId, customOperationExtra, itemDateFormatter, }: HistoryListConfig) => MenuItemType[];
@@ -124,55 +124,60 @@ import { HistoryItem } from "./HistoryItem";
124
124
  })))
125
125
  ];
126
126
  }));
127
+ var MIN_GROUP_SIZE = 3;
127
128
  // 按照时间顺序对分组进行排序:今日 > 昨日 > 一周内 > 其他
128
129
  var sortedGroupKeys = Object.keys(groupList).sort(function(keyA, keyB) {
129
130
  return (groupMaxTimes[keyB] || 0) - (groupMaxTimes[keyA] || 0);
130
131
  });
131
- var items = sortedGroupKeys.map(function(key) {
132
- var _list_sort;
132
+ var buildItemNodes = function buildItemNodes(list) {
133
+ return list.sort(function(a, b) {
134
+ if (sessionSort === false) return 0;
135
+ if (sessionSort) {
136
+ var result = sessionSort(a, b);
137
+ return typeof result === 'boolean' ? 0 : result;
138
+ }
139
+ return dayjs(b.gmtCreate).valueOf() - dayjs(a.gmtCreate).valueOf();
140
+ }).map(function(item) {
141
+ return {
142
+ key: item.sessionId || "item-".concat(item.id),
143
+ type: 'item',
144
+ onClick: function onClick1() {
145
+ if (!item.sessionId) return;
146
+ onClick(item.sessionId, item);
147
+ },
148
+ label: /*#__PURE__*/ React.createElement(HistoryItem, {
149
+ item: item,
150
+ selectedIds: selectedIds,
151
+ onSelectionChange: onSelectionChange,
152
+ onClick: onClick,
153
+ onDeleteItem: onDeleteItem,
154
+ agent: agent,
155
+ onFavorite: onFavorite,
156
+ extra: extra,
157
+ type: type,
158
+ runningId: runningId,
159
+ customOperationExtra: customOperationExtra,
160
+ itemDateFormatter: itemDateFormatter
161
+ })
162
+ };
163
+ });
164
+ };
165
+ var items = sortedGroupKeys.flatMap(function(key) {
133
166
  var list = groupList[key];
134
- var firstItem = list === null || list === void 0 ? void 0 : list.at(0);
167
+ // 少于最小数量时,直接平铺为普通条目,不展示分组标题
168
+ if (list.length < MIN_GROUP_SIZE) {
169
+ return buildItemNodes(list);
170
+ }
171
+ var firstItem = list.at(0);
135
172
  var label = customDateFormatter && (firstItem === null || firstItem === void 0 ? void 0 : firstItem.gmtCreate) ? customDateFormatter(firstItem.gmtCreate) : formatTime(firstItem === null || firstItem === void 0 ? void 0 : firstItem.gmtCreate);
136
- return {
137
- key: "group-".concat(key),
138
- type: 'group',
139
- label: groupLabelRender ? groupLabelRender(key, list, label) : label,
140
- children: list === null || list === void 0 ? void 0 : (_list_sort = list.sort(function(a, b) {
141
- if (sessionSort === false) {
142
- return 0;
143
- }
144
- if (sessionSort) {
145
- var result = sessionSort(a, b);
146
- return typeof result === 'boolean' ? 0 : result;
147
- }
148
- return dayjs(b.gmtCreate).valueOf() - dayjs(a.gmtCreate).valueOf();
149
- })) === null || _list_sort === void 0 ? void 0 : _list_sort.map(function(item) {
150
- return {
151
- key: item.sessionId || "item-".concat(item.id),
152
- type: 'item',
153
- onClick: function onClick1() {
154
- if (!item.sessionId) {
155
- return;
156
- }
157
- onClick(item.sessionId, item);
158
- },
159
- label: /*#__PURE__*/ React.createElement(HistoryItem, {
160
- item: item,
161
- selectedIds: selectedIds,
162
- onSelectionChange: onSelectionChange,
163
- onClick: onClick,
164
- onDeleteItem: onDeleteItem,
165
- agent: agent,
166
- onFavorite: onFavorite,
167
- extra: extra,
168
- type: type,
169
- runningId: runningId,
170
- customOperationExtra: customOperationExtra,
171
- itemDateFormatter: itemDateFormatter
172
- })
173
- };
174
- })
175
- };
173
+ return [
174
+ {
175
+ key: "group-".concat(key),
176
+ type: 'group',
177
+ label: groupLabelRender ? groupLabelRender(key, list, label) : label,
178
+ children: buildItemNodes(list)
179
+ }
180
+ ];
176
181
  });
177
182
  return items;
178
183
  };
@@ -1,4 +1,8 @@
1
1
  /// <reference types="react" />
2
+ import { ChatTokenType, GenerateStyle } from '../Hooks/useStyle';
3
+ declare const genStyle: GenerateStyle<ChatTokenType>;
4
+ /** @internal 供单测调用 genStyle 覆盖 token 回退分支 */
5
+ export { genStyle };
2
6
  export declare function useStyle(prefixCls?: string): {
3
7
  hashId: string;
4
8
  wrapSSR: (node: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>) => import("react").JSX.Element;
@@ -292,6 +292,7 @@ var genStyle = function genStyle(token) {
292
292
  }
293
293
  }), _obj2)), _obj3;
294
294
  };
295
+ /** @internal 供单测调用 genStyle 覆盖 token 回退分支 */ export { genStyle };
295
296
  export function useStyle(prefixCls) {
296
297
  return useEditorStyleRegister('history-group-menu', function(token) {
297
298
  var groupMenuToken = _object_spread_props(_object_spread({}, token), {
@@ -153,7 +153,7 @@ function _ts_generator(thisArg, body) {
153
153
  }
154
154
  import { useEffect, useRef } from "react";
155
155
  import { useThrottleFn } from "./useThrottleFn";
156
- var SCROLL_TOLERANCE = 20; // 滚动到底部的容差阈值
156
+ var SCROLL_TOLERANCE = 20;
157
157
  /**
158
158
  * useAutoScroll Hook - 自动滚动 Hook
159
159
  *
@@ -203,15 +203,22 @@ var SCROLL_TOLERANCE = 20; // 滚动到底部的容差阈值
203
203
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {
204
204
  SCROLL_TOLERANCE: SCROLL_TOLERANCE
205
205
  };
206
+ var _ref;
206
207
  var containerRef = useRef(null);
207
208
  var lastScrollHeight = useRef(0);
208
- var isLocked = useRef(false); // 用户滚动锁定状态
209
+ /**
210
+ * 记录自动滚动是否处于激活状态(即用户没有主动向上滚动)。
211
+ * 在 smooth scroll 动画过程中 scrollTop 尚未到达目标值,如果此时有新内容
212
+ * 进来,isNearBottom 可能因 scrollTop 还在动画中途而误判为 false,导致
213
+ * 漏掉最后一次滚动。用此标志可以安全地跨帧维持"应该跟底"的意图。
214
+ */ var isAutoScrollEngaged = useRef(true);
209
215
  var observer = useRef(null);
216
+ var tolerance = (_ref = props === null || props === void 0 ? void 0 : props.SCROLL_TOLERANCE) !== null && _ref !== void 0 ? _ref : SCROLL_TOLERANCE;
210
217
  // 主滚动逻辑
211
218
  var _checkScroll = function _checkScroll() {
212
219
  var force = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false, behavior = arguments.length > 1 ? arguments[1] : void 0;
213
220
  return _async_to_generator(function() {
214
- var _props_onResize, container, currentScrollHeight, prevScrollHeight, isNearBottom, shouldScroll, _container_scrollTo, scrollBehavior;
221
+ var _props_onResize, container, currentScrollHeight, prevScrollHeight, isNearBottom, shouldScroll, scrollBehavior;
215
222
  return _ts_generator(this, function(_state) {
216
223
  container = containerRef.current;
217
224
  if (!container) return [
@@ -223,21 +230,20 @@ var SCROLL_TOLERANCE = 20; // 滚动到底部的容差阈值
223
230
  });
224
231
  currentScrollHeight = container.scrollHeight;
225
232
  prevScrollHeight = lastScrollHeight.current;
226
- // 计算用户是否在底部区域
227
- isNearBottom = container.scrollTop + container.clientHeight >= prevScrollHeight - ((props === null || props === void 0 ? void 0 : props.SCROLL_TOLERANCE) || SCROLL_TOLERANCE);
228
- // 触发滚动的情况:
229
- // 1. 强制滚动(手动触发)
230
- // 2. 内容高度增加且用户原本在底部
231
- shouldScroll = force || currentScrollHeight > prevScrollHeight && (isNearBottom || isLocked.current);
233
+ // 使用当前 scrollHeight 判断是否靠近底部,避免 smooth 动画中 scrollTop
234
+ // 尚未到达目标时的误判。
235
+ isNearBottom = container.scrollTop + container.clientHeight >= currentScrollHeight - tolerance;
236
+ shouldScroll = force || currentScrollHeight > prevScrollHeight && (isNearBottom || isAutoScrollEngaged.current);
232
237
  if (shouldScroll && container.scrollTo) {
233
- ;
234
- // 如果传入了 behavior,使用传入的值;否则使用配置的 scrollBehavior;最后默认为 'smooth'
235
238
  scrollBehavior = behavior !== undefined ? behavior : props.scrollBehavior || 'smooth';
236
- (_container_scrollTo = container.scrollTo) === null || _container_scrollTo === void 0 ? void 0 : _container_scrollTo.call(container, {
239
+ container.scrollTo({
237
240
  top: currentScrollHeight,
238
241
  behavior: scrollBehavior
239
242
  });
240
- isLocked.current = false; // 滚动后解除锁定
243
+ isAutoScrollEngaged.current = true;
244
+ } else if (!isNearBottom) {
245
+ // 用户已经向上滚动远离底部,关闭自动跟随
246
+ isAutoScrollEngaged.current = false;
241
247
  }
242
248
  lastScrollHeight.current = currentScrollHeight;
243
249
  return [
@@ -247,12 +253,30 @@ var SCROLL_TOLERANCE = 20; // 滚动到底部的容差阈值
247
253
  })();
248
254
  };
249
255
  var checkScroll = useThrottleFn(_checkScroll, props.timeout || 160);
256
+ // 监听用户手动滚动,判断其是否离开了底部
257
+ useEffect(function() {
258
+ var container = containerRef.current;
259
+ if (!container) return;
260
+ var handleScroll = function handleScroll() {
261
+ var atBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - tolerance;
262
+ if (atBottom) {
263
+ isAutoScrollEngaged.current = true;
264
+ } else {
265
+ isAutoScrollEngaged.current = false;
266
+ }
267
+ };
268
+ container.addEventListener('scroll', handleScroll, {
269
+ passive: true
270
+ });
271
+ return function() {
272
+ return container.removeEventListener('scroll', handleScroll);
273
+ };
274
+ }, _to_consumable_array(props.deps || []));
250
275
  // DOM 变化监听(MutationObserver)
251
276
  useEffect(function() {
252
277
  var container = containerRef.current;
253
278
  if (!container) return;
254
279
  observer.current = new MutationObserver(function(mutations) {
255
- // 过滤出添加节点的变化
256
280
  var hasAddedNodes = mutations.some(function(m) {
257
281
  return m.addedNodes.length > 0;
258
282
  });
@@ -392,6 +392,7 @@ export declare function useLanguage(): {
392
392
  'browser.searching': string;
393
393
  'layout.header.title': string;
394
394
  theme: string;
395
+ localPreview: string;
395
396
  expandCollapse: string;
396
397
  moreActions: string;
397
398
  clickToRetry: string;
@@ -354,6 +354,7 @@ export declare const cnLabels: {
354
354
  'browser.searching': string;
355
355
  'layout.header.title': string;
356
356
  theme: string;
357
+ localPreview: string;
357
358
  expandCollapse: string;
358
359
  moreActions: string;
359
360
  clickToRetry: string;
@@ -376,6 +376,7 @@
376
376
  'browser.searching': '搜索中...',
377
377
  'layout.header.title': 'AI 助手',
378
378
  theme: '主题',
379
+ localPreview: '本地预览',
379
380
  expandCollapse: '展开/收起',
380
381
  moreActions: '更多操作',
381
382
  clickToRetry: '点击重试',
@@ -801,6 +802,7 @@
801
802
  'browser.searching': 'Searching...',
802
803
  'layout.header.title': 'AI Assistant',
803
804
  theme: 'Theme',
805
+ localPreview: 'Local Preview',
804
806
  expandCollapse: 'Expand/Collapse',
805
807
  moreActions: 'More Actions',
806
808
  clickToRetry: 'Click to Retry',
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { RenderElementProps } from 'slate-react';
3
+ export declare const AgenticUiFileMapBlock: React.FC<RenderElementProps>;
4
+ export declare const ReadonlyAgenticUiFileMapBlock: React.NamedExoticComponent<RenderElementProps>;
@@ -0,0 +1,83 @@
1
+ function _define_property(obj, key, value) {
2
+ if (key in obj) {
3
+ Object.defineProperty(obj, key, {
4
+ value: value,
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true
8
+ });
9
+ } else {
10
+ obj[key] = value;
11
+ }
12
+ return obj;
13
+ }
14
+ function _object_spread(target) {
15
+ for(var i = 1; i < arguments.length; i++){
16
+ var source = arguments[i] != null ? arguments[i] : {};
17
+ var ownKeys = Object.keys(source);
18
+ if (typeof Object.getOwnPropertySymbols === "function") {
19
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
20
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
21
+ }));
22
+ }
23
+ ownKeys.forEach(function(key) {
24
+ _define_property(target, key, source[key]);
25
+ });
26
+ }
27
+ return target;
28
+ }
29
+ function ownKeys(object, enumerableOnly) {
30
+ var keys = Object.keys(object);
31
+ if (Object.getOwnPropertySymbols) {
32
+ var symbols = Object.getOwnPropertySymbols(object);
33
+ if (enumerableOnly) {
34
+ symbols = symbols.filter(function(sym) {
35
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
36
+ });
37
+ }
38
+ keys.push.apply(keys, symbols);
39
+ }
40
+ return keys;
41
+ }
42
+ function _object_spread_props(target, source) {
43
+ source = source != null ? source : {};
44
+ if (Object.getOwnPropertyDescriptors) {
45
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
46
+ } else {
47
+ ownKeys(Object(source)).forEach(function(key) {
48
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
49
+ });
50
+ }
51
+ return target;
52
+ }
53
+ import React from "react";
54
+ import { FileMapView } from "../../../../MarkdownInputField/FileMapView";
55
+ import { normalizeFileMapPropsFromJson } from "./agenticUiEmbedUtils";
56
+ export var AgenticUiFileMapBlock = function AgenticUiFileMapBlock(param) {
57
+ var attributes = param.attributes, children = param.children, element = param.element;
58
+ var _normalizeFileMapPropsFromJson = normalizeFileMapPropsFromJson(element.value), fileList = _normalizeFileMapPropsFromJson.fileList, className = _normalizeFileMapPropsFromJson.className;
59
+ var fileMap = new Map(fileList.map(function(f) {
60
+ return [
61
+ f.uuid || f.name,
62
+ f
63
+ ];
64
+ }));
65
+ return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, attributes), {
66
+ contentEditable: false,
67
+ "data-testid": "agentic-ui-filemap-block",
68
+ style: {
69
+ margin: '0.75em 0'
70
+ }
71
+ }), /*#__PURE__*/ React.createElement(FileMapView, {
72
+ fileMap: fileMap,
73
+ className: className
74
+ }), /*#__PURE__*/ React.createElement("span", {
75
+ "data-testid": "agentic-ui-filemap-hidden-children",
76
+ style: {
77
+ display: 'none'
78
+ }
79
+ }, children));
80
+ };
81
+ AgenticUiFileMapBlock.displayName = 'AgenticUiFileMapBlock';
82
+ export var ReadonlyAgenticUiFileMapBlock = /*#__PURE__*/ React.memo(AgenticUiFileMapBlock);
83
+ ReadonlyAgenticUiFileMapBlock.displayName = 'ReadonlyAgenticUiFileMapBlock';
@@ -1,4 +1,5 @@
1
1
  import type { CSSProperties } from 'react';
2
+ import type { AttachmentFile } from '../../../../MarkdownInputField/AttachmentButton/types';
2
3
  import type { TaskListProps } from '../../../../TaskList/types';
3
4
  import type { ToolCall } from '../../../../ToolUseBar/BarItem';
4
5
  /**
@@ -18,3 +19,16 @@ export interface NormalizedToolUseBarEmbedProps {
18
19
  disableAnimation?: boolean;
19
20
  }
20
21
  export declare function normalizeToolUseBarPropsFromJson(parsed: unknown): NormalizedToolUseBarEmbedProps;
22
+ export interface NormalizedFileMapEmbedProps {
23
+ fileList: AttachmentFile[];
24
+ className?: string;
25
+ style?: CSSProperties;
26
+ }
27
+ /**
28
+ * 将 ```agentic-ui-filemap JSON 规范化为 FileMapView 所需 props
29
+ *
30
+ * @param parsed - 解析后的 JSON 数据
31
+ * @param normalizeFile - 可选的自定义文件规范化函数,接收原始 JSON 条目和默认生成的
32
+ * AttachmentFile,返回最终的 AttachmentFile;返回 null 时该条目被过滤掉
33
+ */
34
+ export declare function normalizeFileMapPropsFromJson(parsed: unknown, normalizeFile?: (raw: Record<string, unknown>, defaultFile: AttachmentFile) => AttachmentFile | null): NormalizedFileMapEmbedProps;
@@ -167,3 +167,55 @@ export function normalizeToolUseBarPropsFromJson(parsed) {
167
167
  disableAnimation: disableAnimation
168
168
  };
169
169
  }
170
+ var fileItemFromRecord = function fileItemFromRecord(x, index) {
171
+ var name = x.name !== undefined && x.name !== null ? String(x.name) : "file-".concat(index);
172
+ var url = x.url !== undefined && x.url !== null ? String(x.url) : undefined;
173
+ var previewUrl = x.previewUrl !== undefined && x.previewUrl !== null ? String(x.previewUrl) : undefined;
174
+ var type = x.type !== undefined && x.type !== null ? String(x.type) : 'application/octet-stream';
175
+ var size = typeof x.size === 'number' ? x.size : undefined;
176
+ var uuid = x.uuid !== undefined && x.uuid !== null ? String(x.uuid) : x.id !== undefined && x.id !== null ? String(x.id) : "file-".concat(index);
177
+ var rawStatus = x.status;
178
+ var status = rawStatus === 'error' || rawStatus === 'uploading' || rawStatus === 'pending' || rawStatus === 'done' ? rawStatus : undefined;
179
+ var errorMessage = typeof x.errorMessage === 'string' ? x.errorMessage : undefined;
180
+ return {
181
+ name: name,
182
+ type: type,
183
+ url: url,
184
+ previewUrl: previewUrl,
185
+ uuid: uuid,
186
+ size: size,
187
+ status: status,
188
+ errorMessage: errorMessage
189
+ };
190
+ };
191
+ /**
192
+ * 将 ```agentic-ui-filemap JSON 规范化为 FileMapView 所需 props
193
+ *
194
+ * @param parsed - 解析后的 JSON 数据
195
+ * @param normalizeFile - 可选的自定义文件规范化函数,接收原始 JSON 条目和默认生成的
196
+ * AttachmentFile,返回最终的 AttachmentFile;返回 null 时该条目被过滤掉
197
+ */ export function normalizeFileMapPropsFromJson(parsed, normalizeFile) {
198
+ var root = parsed && (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && !Array.isArray(parsed) ? parsed : null;
199
+ var rawItems = [];
200
+ if (root && Array.isArray(root.fileList)) {
201
+ rawItems = root.fileList;
202
+ } else if (root && Array.isArray(root.files)) {
203
+ rawItems = root.files;
204
+ } else if (Array.isArray(parsed)) {
205
+ rawItems = parsed;
206
+ }
207
+ var fileList = rawItems.filter(function(x) {
208
+ return !!x && (typeof x === "undefined" ? "undefined" : _type_of(x)) === 'object';
209
+ }).map(function(x, i) {
210
+ var defaultFile = fileItemFromRecord(x, i);
211
+ if (!normalizeFile) return defaultFile;
212
+ return normalizeFile(x, defaultFile);
213
+ }).filter(function(f) {
214
+ return f !== null;
215
+ });
216
+ var className = root && typeof root.className === 'string' ? root.className : undefined;
217
+ return {
218
+ fileList: fileList,
219
+ className: className
220
+ };
221
+ }
@@ -98,6 +98,7 @@ import { useEditorStore } from "../store";
98
98
  import { EditorUtils } from "../utils/editorUtils";
99
99
  import { AgenticUiTaskBlock, ReadonlyAgenticUiTaskBlock } from "./AgenticUiBlocks/AgenticUiTaskBlock";
100
100
  import { AgenticUiToolUseBarBlock, ReadonlyAgenticUiToolUseBarBlock } from "./AgenticUiBlocks/AgenticUiToolUseBarBlock";
101
+ import { AgenticUiFileMapBlock, ReadonlyAgenticUiFileMapBlock } from "./AgenticUiBlocks/AgenticUiFileMapBlock";
101
102
  import { Blockquote } from "./Blockquote";
102
103
  import { ReadonlyBlockquote } from "./Blockquote/ReadonlyBlockquote";
103
104
  import { Break } from "./Break";
@@ -250,6 +251,8 @@ var MElementComponent = function MElementComponent(props) {
250
251
  case 'agentic-ui-toolusebar':
251
252
  case 'agentic-ui-usertoolbar':
252
253
  return props.readonly ? /*#__PURE__*/ React.createElement(ReadonlyAgenticUiToolUseBarBlock, readonlyElementProps) : /*#__PURE__*/ React.createElement(AgenticUiToolUseBarBlock, props);
254
+ case 'agentic-ui-filemap':
255
+ return props.readonly ? /*#__PURE__*/ React.createElement(ReadonlyAgenticUiFileMapBlock, readonlyElementProps) : /*#__PURE__*/ React.createElement(AgenticUiFileMapBlock, props);
253
256
  case 'image':
254
257
  return props.readonly ? /*#__PURE__*/ React.createElement(ReadonlyEditorImage, readonlyElementProps) : /*#__PURE__*/ React.createElement(EditorImage, props);
255
258
  case 'media':
@@ -128,7 +128,8 @@ var processSchemaLanguage = function processSchemaLanguage(element, value) {
128
128
  'agentar-card': processSchemaLanguage,
129
129
  'agentic-ui-task': processAgenticUiJsonBlock('agentic-ui-task'),
130
130
  'agentic-ui-toolusebar': processAgenticUiJsonBlock('agentic-ui-toolusebar'),
131
- /** @deprecated 使用 `agentic-ui-toolusebar`,保留解析以兼容旧内容 */ 'agentic-ui-usertoolbar': processAgenticUiJsonBlock('agentic-ui-toolusebar')
131
+ /** @deprecated 使用 `agentic-ui-toolusebar`,保留解析以兼容旧内容 */ 'agentic-ui-usertoolbar': processAgenticUiJsonBlock('agentic-ui-toolusebar'),
132
+ 'agentic-ui-filemap': processAgenticUiJsonBlock('agentic-ui-filemap')
132
133
  };
133
134
  /**
134
135
  * 处理代码块节点
@@ -287,6 +287,7 @@ var inlineNode = new Set([
287
287
  case 'agentic-ui-task':
288
288
  case 'agentic-ui-toolusebar':
289
289
  case 'agentic-ui-usertoolbar':
290
+ case 'agentic-ui-filemap':
290
291
  str += handleCode(node, preString);
291
292
  break;
292
293
  case 'attach':
@@ -758,7 +758,8 @@ import { parseMarkdownToNodesAndInsert } from "./parseMarkdownToNodesAndInsert";
758
758
  'apaasify',
759
759
  'agentic-ui-task',
760
760
  'agentic-ui-toolusebar',
761
- 'agentic-ui-usertoolbar'
761
+ 'agentic-ui-usertoolbar',
762
+ 'agentic-ui-filemap'
762
763
  ].includes(rangeNode.type);
763
764
  };
764
765
  /**