@ant-design/agentic-ui 2.30.11 → 2.30.12
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/MessagesContent/style.js +3 -1
- package/dist/Bubble/style.js +35 -13
- package/dist/ChatLayout/index.js +9 -1
- package/dist/History/components/HistoryList.d.ts +2 -12
- package/dist/History/components/HistoryList.js +48 -43
- package/dist/History/style.d.ts +4 -0
- package/dist/History/style.js +1 -0
- package/dist/Hooks/useAutoScroll.js +38 -14
- package/dist/Hooks/useLanguage.d.ts +1 -0
- package/dist/I18n/locales.d.ts +1 -0
- package/dist/I18n/locales.js +2 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.d.ts +4 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/AgenticUiFileMapBlock.js +83 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +10 -0
- package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +44 -0
- package/dist/MarkdownEditor/editor/elements/index.js +3 -0
- package/dist/MarkdownEditor/editor/parser/parse/parseCode.js +2 -1
- package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +1 -0
- package/dist/MarkdownEditor/editor/plugins/handlePaste.js +2 -1
- package/dist/MarkdownRenderer/MarkdownRenderer.js +7 -0
- package/dist/MarkdownRenderer/index.d.ts +3 -0
- package/dist/MarkdownRenderer/index.js +3 -0
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +6 -0
- package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +79 -0
- package/dist/MarkdownRenderer/renderers/index.d.ts +3 -0
- package/dist/MarkdownRenderer/renderers/index.js +3 -0
- package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
- package/dist/Plugins/code/components/CodeRenderer.js +22 -6
- package/dist/Plugins/code/components/CodeToolbar.d.ts +2 -0
- package/dist/Plugins/code/components/CodeToolbar.js +11 -4
- package/dist/Plugins/code/hooks/useToolbarConfig.d.ts +3 -1
- package/dist/Plugins/code/hooks/useToolbarConfig.js +5 -3
- package/dist/Plugins/code/utils/index.d.ts +1 -0
- package/dist/Plugins/code/utils/index.js +1 -0
- package/dist/Plugins/code/utils/localPreview.d.ts +12 -0
- package/dist/Plugins/code/utils/localPreview.js +190 -0
- package/package.json +1 -2
|
@@ -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", {
|
package/dist/Bubble/style.js
CHANGED
|
@@ -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
|
-
|
|
196
|
-
|
|
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
|
-
|
|
216
|
-
|
|
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
|
},
|
package/dist/ChatLayout/index.js
CHANGED
|
@@ -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
|
|
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
|
|
132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
};
|
package/dist/History/style.d.ts
CHANGED
|
@@ -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;
|
package/dist/History/style.js
CHANGED
|
@@ -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
|
-
|
|
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,
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
239
|
+
container.scrollTo({
|
|
237
240
|
top: currentScrollHeight,
|
|
238
241
|
behavior: scrollBehavior
|
|
239
242
|
});
|
|
240
|
-
|
|
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
|
});
|
package/dist/I18n/locales.d.ts
CHANGED
package/dist/I18n/locales.js
CHANGED
|
@@ -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,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,12 @@ 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
|
+
export declare function normalizeFileMapPropsFromJson(parsed: unknown): NormalizedFileMapEmbedProps;
|
|
@@ -167,3 +167,47 @@ 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
|
+
*/ export function normalizeFileMapPropsFromJson(parsed) {
|
|
194
|
+
var root = parsed && (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && !Array.isArray(parsed) ? parsed : null;
|
|
195
|
+
var rawItems = [];
|
|
196
|
+
if (root && Array.isArray(root.fileList)) {
|
|
197
|
+
rawItems = root.fileList;
|
|
198
|
+
} else if (root && Array.isArray(root.files)) {
|
|
199
|
+
rawItems = root.files;
|
|
200
|
+
} else if (Array.isArray(parsed)) {
|
|
201
|
+
rawItems = parsed;
|
|
202
|
+
}
|
|
203
|
+
var fileList = rawItems.filter(function(x) {
|
|
204
|
+
return !!x && (typeof x === "undefined" ? "undefined" : _type_of(x)) === 'object';
|
|
205
|
+
}).map(function(x, i) {
|
|
206
|
+
return fileItemFromRecord(x, i);
|
|
207
|
+
});
|
|
208
|
+
var className = root && typeof root.className === 'string' ? root.className : undefined;
|
|
209
|
+
return {
|
|
210
|
+
fileList: fileList,
|
|
211
|
+
className: className
|
|
212
|
+
};
|
|
213
|
+
}
|
|
@@ -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
|
* 处理代码块节点
|
|
@@ -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
|
/**
|
|
@@ -140,6 +140,7 @@ import { useStyle as useEditorStyle } from "../MarkdownEditor/style";
|
|
|
140
140
|
import { CharacterQueue } from "./CharacterQueue";
|
|
141
141
|
import { AgenticUiTaskBlockRenderer } from "./renderers/AgenticUiTaskBlockRenderer";
|
|
142
142
|
import { AgenticUiToolUseBarBlockRenderer } from "./renderers/AgenticUiToolUseBarBlockRenderer";
|
|
143
|
+
import { AgenticUiFileMapBlockRenderer } from "./renderers/AgenticUiFileMapBlockRenderer";
|
|
143
144
|
import { ChartBlockRenderer } from "./renderers/ChartRenderer";
|
|
144
145
|
import { CodeBlockRenderer } from "./renderers/CodeRenderer";
|
|
145
146
|
import { MermaidBlockRenderer } from "./renderers/MermaidRenderer";
|
|
@@ -215,6 +216,12 @@ var SCHEMA_LANGUAGES = new Set([
|
|
|
215
216
|
language: language
|
|
216
217
|
}));
|
|
217
218
|
}
|
|
219
|
+
if (language === 'agentic-ui-filemap') {
|
|
220
|
+
var FileMapComp = pluginComponents['agentic-ui-filemap'] || AgenticUiFileMapBlockRenderer;
|
|
221
|
+
return /*#__PURE__*/ React.createElement(FileMapComp, _object_spread_props(_object_spread({}, rest), {
|
|
222
|
+
language: language
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
218
225
|
if (SCHEMA_LANGUAGES.has(language)) {
|
|
219
226
|
var SchemaComp = pluginComponents.schema || SchemaBlockRenderer;
|
|
220
227
|
return /*#__PURE__*/ React.createElement(SchemaComp, _object_spread_props(_object_spread({}, rest), {
|
|
@@ -2,6 +2,9 @@ export { default as AnimationText } from './AnimationText';
|
|
|
2
2
|
export type { AnimationConfig, AnimationTextProps } from './AnimationText';
|
|
3
3
|
export { CharacterQueue } from './CharacterQueue';
|
|
4
4
|
export { default as MarkdownRenderer } from './MarkdownRenderer';
|
|
5
|
+
export { AgenticUiFileMapBlockRenderer } from './renderers/AgenticUiFileMapBlockRenderer';
|
|
6
|
+
export { AgenticUiTaskBlockRenderer } from './renderers/AgenticUiTaskBlockRenderer';
|
|
7
|
+
export { AgenticUiToolUseBarBlockRenderer } from './renderers/AgenticUiToolUseBarBlockRenderer';
|
|
5
8
|
export { ChartBlockRenderer } from './renderers/ChartRenderer';
|
|
6
9
|
export { CodeBlockRenderer } from './renderers/CodeRenderer';
|
|
7
10
|
export { MermaidBlockRenderer } from './renderers/MermaidRenderer';
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export { default as AnimationText } from "./AnimationText";
|
|
2
2
|
export { CharacterQueue } from "./CharacterQueue";
|
|
3
3
|
export { default as MarkdownRenderer } from "./MarkdownRenderer";
|
|
4
|
+
export { AgenticUiFileMapBlockRenderer } from "./renderers/AgenticUiFileMapBlockRenderer";
|
|
5
|
+
export { AgenticUiTaskBlockRenderer } from "./renderers/AgenticUiTaskBlockRenderer";
|
|
6
|
+
export { AgenticUiToolUseBarBlockRenderer } from "./renderers/AgenticUiToolUseBarBlockRenderer";
|
|
4
7
|
export { ChartBlockRenderer } from "./renderers/ChartRenderer";
|
|
5
8
|
export { CodeBlockRenderer } from "./renderers/CodeRenderer";
|
|
6
9
|
export { MermaidBlockRenderer } from "./renderers/MermaidRenderer";
|
|
@@ -0,0 +1,79 @@
|
|
|
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 extractTextContent = function extractTextContent1(children) {
|
|
7
|
+
var _children_props;
|
|
8
|
+
if (typeof children === 'string') return children;
|
|
9
|
+
if (typeof children === 'number') return String(children);
|
|
10
|
+
if (Array.isArray(children)) return children.map(extractTextContent).join('');
|
|
11
|
+
if (/*#__PURE__*/ React.isValidElement(children) && ((_children_props = children.props) === null || _children_props === void 0 ? void 0 : _children_props.children)) {
|
|
12
|
+
return extractTextContent(children.props.children);
|
|
13
|
+
}
|
|
14
|
+
return '';
|
|
15
|
+
};
|
|
16
|
+
var parseJsonBody = function parseJsonBody(code) {
|
|
17
|
+
try {
|
|
18
|
+
return json5.parse(code || '{}');
|
|
19
|
+
} catch (unused) {
|
|
20
|
+
try {
|
|
21
|
+
return partialParse(code || '{}');
|
|
22
|
+
} catch (unused) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* ```agentic-ui-filemap``` 代码块 → FileMapView
|
|
29
|
+
*/ export var AgenticUiFileMapBlockRenderer = function AgenticUiFileMapBlockRenderer(props) {
|
|
30
|
+
var code = useMemo(function() {
|
|
31
|
+
return extractTextContent(props.children);
|
|
32
|
+
}, [
|
|
33
|
+
props.children
|
|
34
|
+
]);
|
|
35
|
+
var parsed = useMemo(function() {
|
|
36
|
+
return parseJsonBody(code);
|
|
37
|
+
}, [
|
|
38
|
+
code
|
|
39
|
+
]);
|
|
40
|
+
var _useMemo = useMemo(function() {
|
|
41
|
+
return normalizeFileMapPropsFromJson(parsed);
|
|
42
|
+
}, [
|
|
43
|
+
parsed
|
|
44
|
+
]), fileList = _useMemo.fileList, className = _useMemo.className;
|
|
45
|
+
var fileMap = useMemo(function() {
|
|
46
|
+
return new Map(fileList.map(function(f) {
|
|
47
|
+
return [
|
|
48
|
+
f.uuid || f.name,
|
|
49
|
+
f
|
|
50
|
+
];
|
|
51
|
+
}));
|
|
52
|
+
}, [
|
|
53
|
+
fileList
|
|
54
|
+
]);
|
|
55
|
+
if (parsed === null) {
|
|
56
|
+
return /*#__PURE__*/ React.createElement("pre", {
|
|
57
|
+
"data-testid": "agentic-ui-filemap-fallback",
|
|
58
|
+
style: {
|
|
59
|
+
background: 'rgb(242, 241, 241)',
|
|
60
|
+
padding: '1em',
|
|
61
|
+
borderRadius: '0.5em',
|
|
62
|
+
margin: '0.75em 0',
|
|
63
|
+
fontSize: '0.8em',
|
|
64
|
+
whiteSpace: 'pre-wrap',
|
|
65
|
+
wordBreak: 'break-all'
|
|
66
|
+
}
|
|
67
|
+
}, /*#__PURE__*/ React.createElement("code", null, code));
|
|
68
|
+
}
|
|
69
|
+
return /*#__PURE__*/ React.createElement("div", {
|
|
70
|
+
"data-testid": "agentic-ui-filemap-block",
|
|
71
|
+
style: {
|
|
72
|
+
margin: '0.75em 0'
|
|
73
|
+
}
|
|
74
|
+
}, /*#__PURE__*/ React.createElement(FileMapView, {
|
|
75
|
+
fileMap: fileMap,
|
|
76
|
+
className: className
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
AgenticUiFileMapBlockRenderer.displayName = 'AgenticUiFileMapBlockRenderer';
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export { AgenticUiFileMapBlockRenderer } from './AgenticUiFileMapBlockRenderer';
|
|
2
|
+
export { AgenticUiTaskBlockRenderer } from './AgenticUiTaskBlockRenderer';
|
|
3
|
+
export { AgenticUiToolUseBarBlockRenderer } from './AgenticUiToolUseBarBlockRenderer';
|
|
1
4
|
export { ChartBlockRenderer } from './ChartRenderer';
|
|
2
5
|
export { CodeBlockRenderer } from './CodeRenderer';
|
|
3
6
|
export { MermaidBlockRenderer } from './MermaidRenderer';
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export { AgenticUiFileMapBlockRenderer } from "./AgenticUiFileMapBlockRenderer";
|
|
2
|
+
export { AgenticUiTaskBlockRenderer } from "./AgenticUiTaskBlockRenderer";
|
|
3
|
+
export { AgenticUiToolUseBarBlockRenderer } from "./AgenticUiToolUseBarBlockRenderer";
|
|
1
4
|
export { ChartBlockRenderer } from "./ChartRenderer";
|
|
2
5
|
export { CodeBlockRenderer } from "./CodeRenderer";
|
|
3
6
|
export { MermaidBlockRenderer } from "./MermaidRenderer";
|
|
@@ -393,6 +393,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
|
|
|
393
393
|
'browser.searching': string;
|
|
394
394
|
'layout.header.title': string;
|
|
395
395
|
theme: string;
|
|
396
|
+
localPreview: string;
|
|
396
397
|
expandCollapse: string;
|
|
397
398
|
moreActions: string;
|
|
398
399
|
clickToRetry: string;
|
|
@@ -786,6 +787,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
|
|
|
786
787
|
'browser.searching': string;
|
|
787
788
|
'layout.header.title': string;
|
|
788
789
|
theme: string;
|
|
790
|
+
localPreview: string;
|
|
789
791
|
expandCollapse: string;
|
|
790
792
|
moreActions: string;
|
|
791
793
|
clickToRetry: string;
|
|
@@ -100,10 +100,11 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
100
100
|
* @fileoverview 代码渲染器组件
|
|
101
101
|
* 封装代码编辑器的所有渲染逻辑
|
|
102
102
|
*/ import { ConfigProvider, Skeleton, theme as antdTheme } from "antd";
|
|
103
|
-
import React, { useEffect, useMemo, useState } from "react";
|
|
103
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
104
104
|
import { MarkdownEditor } from "../../../MarkdownEditor";
|
|
105
105
|
import { useEditorStore } from "../../../MarkdownEditor/editor/store";
|
|
106
106
|
import { useCodeEditorState, useRenderConditions, useToolbarConfig } from "../hooks";
|
|
107
|
+
import { openHtmlLocalPreview, openMarkdownLocalPreview } from "../utils/localPreview";
|
|
107
108
|
import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview, ThinkBlock } from "./index";
|
|
108
109
|
/**
|
|
109
110
|
* 检测 HTML 代码中是否包含 JavaScript
|
|
@@ -154,7 +155,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
|
|
|
154
155
|
* - 支持代码框选中状态管理
|
|
155
156
|
*/ export function CodeRenderer(props) {
|
|
156
157
|
var _ref;
|
|
157
|
-
var _editorProps_codeProps, _props_element_language, _props_element, _props_element1, _props_element_otherProps,
|
|
158
|
+
var _editorProps_codeProps, _props_element_language, _props_element, _props_element1, _props_element2, _props_element_otherProps, _props_element3, _props_element_otherProps1, _props_element4, _editorProps_codeProps1, _editorProps_codeProps2;
|
|
158
159
|
var _useEditorStore = useEditorStore(), editorProps = _useEditorStore.editorProps, readonly = _useEditorStore.readonly;
|
|
159
160
|
// 使用状态管理Hook
|
|
160
161
|
var _useCodeEditorState = useCodeEditorState(props.element), state = _useCodeEditorState.state, update = _useCodeEditorState.update, path = _useCodeEditorState.path, handleCloseClick = _useCodeEditorState.handleCloseClick, handleHtmlPreviewClose = _useCodeEditorState.handleHtmlPreviewClose, handleShowBorderChange = _useCodeEditorState.handleShowBorderChange, handleHideChange = _useCodeEditorState.handleHideChange;
|
|
@@ -203,6 +204,19 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
|
|
|
203
204
|
return prev === 'preview' ? 'code' : 'preview';
|
|
204
205
|
});
|
|
205
206
|
};
|
|
207
|
+
// 本地预览处理函数
|
|
208
|
+
var handleLocalPreview = useCallback(function() {
|
|
209
|
+
var _props_element;
|
|
210
|
+
var value = ((_props_element = props.element) === null || _props_element === void 0 ? void 0 : _props_element.value) || '';
|
|
211
|
+
if (language === 'markdown') {
|
|
212
|
+
openMarkdownLocalPreview(value);
|
|
213
|
+
} else if (language === 'html') {
|
|
214
|
+
openHtmlLocalPreview(value);
|
|
215
|
+
}
|
|
216
|
+
}, [
|
|
217
|
+
language,
|
|
218
|
+
(_props_element2 = props.element) === null || _props_element2 === void 0 ? void 0 : _props_element2.value
|
|
219
|
+
]);
|
|
206
220
|
// 使用工具栏配置Hook
|
|
207
221
|
var toolbarProps = useToolbarConfig({
|
|
208
222
|
element: props.element,
|
|
@@ -211,10 +225,11 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
|
|
|
211
225
|
setLanguage: setLanguage,
|
|
212
226
|
onSelectionChange: setIsSelected,
|
|
213
227
|
onViewModeToggle: handleViewModeToggle,
|
|
214
|
-
viewMode: viewMode
|
|
228
|
+
viewMode: viewMode,
|
|
229
|
+
onLocalPreview: handleLocalPreview
|
|
215
230
|
}).toolbarProps;
|
|
216
231
|
// 检查代码块是否未闭合
|
|
217
|
-
var isUnclosed = ((
|
|
232
|
+
var isUnclosed = ((_props_element3 = props.element) === null || _props_element3 === void 0 ? void 0 : (_props_element_otherProps = _props_element3.otherProps) === null || _props_element_otherProps === void 0 ? void 0 : _props_element_otherProps.finished) === false;
|
|
218
233
|
// 5 秒超时机制:如果代码块未闭合,5 秒后自动设置为完成
|
|
219
234
|
useEffect(function() {
|
|
220
235
|
if (isUnclosed && !readonly) {
|
|
@@ -237,7 +252,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
|
|
|
237
252
|
}, [
|
|
238
253
|
isUnclosed,
|
|
239
254
|
readonly,
|
|
240
|
-
(
|
|
255
|
+
(_props_element4 = props.element) === null || _props_element4 === void 0 ? void 0 : (_props_element_otherProps1 = _props_element4.otherProps) === null || _props_element_otherProps1 === void 0 ? void 0 : _props_element_otherProps1.finished,
|
|
241
256
|
update
|
|
242
257
|
]);
|
|
243
258
|
// 如果禁用了 HTML 预览或包含 JavaScript,强制使用代码模式
|
|
@@ -342,6 +357,7 @@ import { AceEditor, AceEditorContainer, CodeContainer, CodeToolbar, HtmlPreview,
|
|
|
342
357
|
handleHtmlPreviewClose,
|
|
343
358
|
viewMode,
|
|
344
359
|
handleViewModeToggle,
|
|
345
|
-
disableHtmlPreview
|
|
360
|
+
disableHtmlPreview,
|
|
361
|
+
handleLocalPreview
|
|
346
362
|
]);
|
|
347
363
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 提供代码块的各种操作功能,包括语言切换、复制、运行等
|
|
4
4
|
* @author Code Plugin Team
|
|
5
5
|
*/ import { CloseCircleOutlined } from "@ant-design/icons";
|
|
6
|
-
import { ChevronsUpDown, Copy, Moon } from "@sofa-design/icons";
|
|
6
|
+
import { ArrowUpRight, ChevronsUpDown, Copy, Moon } from "@sofa-design/icons";
|
|
7
7
|
import { Segmented } from "antd";
|
|
8
8
|
import copy from "copy-to-clipboard";
|
|
9
9
|
import React, { useContext, useMemo } from "react";
|
|
@@ -77,14 +77,14 @@ import { LoadImage } from "./LoadImage";
|
|
|
77
77
|
* ```
|
|
78
78
|
*/ export var CodeToolbar = function CodeToolbar(props) {
|
|
79
79
|
var _ref;
|
|
80
|
-
var _editorProps_codeProps, _editorProps_codeProps1, _element_language, _element_language1, _i18n_locale, _i18n_locale1, _i18n_locale2, _i18n_locale3;
|
|
80
|
+
var _editorProps_codeProps, _editorProps_codeProps1, _element_language, _element_language1, _i18n_locale, _i18n_locale1, _i18n_locale2, _i18n_locale3, _i18n_locale4;
|
|
81
81
|
// 获取国际化上下文
|
|
82
82
|
var i18n = useContext(I18nContext);
|
|
83
83
|
// 获取编辑器配置
|
|
84
84
|
var editorProps = useEditorStore().editorProps;
|
|
85
85
|
var disableHtmlPreview = (_ref = (_editorProps_codeProps = editorProps.codeProps) === null || _editorProps_codeProps === void 0 ? void 0 : _editorProps_codeProps.disableHtmlPreview) !== null && _ref !== void 0 ? _ref : false;
|
|
86
86
|
var viewModeLabels = (_editorProps_codeProps1 = editorProps.codeProps) === null || _editorProps_codeProps1 === void 0 ? void 0 : _editorProps_codeProps1.viewModeLabels;
|
|
87
|
-
var element = props.element, readonly = props.readonly, onCloseClick = props.onCloseClick, languageSelectorProps = props.languageSelectorProps, onViewModeToggle = props.onViewModeToggle, theme = props.theme, isExpanded = props.isExpanded, onExpandToggle = props.onExpandToggle, setTheme = props.setTheme, _props_viewMode = props.viewMode, viewMode = _props_viewMode === void 0 ? 'code' : _props_viewMode;
|
|
87
|
+
var element = props.element, readonly = props.readonly, onCloseClick = props.onCloseClick, languageSelectorProps = props.languageSelectorProps, onViewModeToggle = props.onViewModeToggle, theme = props.theme, isExpanded = props.isExpanded, onExpandToggle = props.onExpandToggle, setTheme = props.setTheme, _props_viewMode = props.viewMode, viewMode = _props_viewMode === void 0 ? 'code' : _props_viewMode, onLocalPreview = props.onLocalPreview;
|
|
88
88
|
// 检测 HTML 代码中是否包含 JavaScript
|
|
89
89
|
var hasJavaScript = useMemo(function() {
|
|
90
90
|
var _element_language;
|
|
@@ -216,5 +216,12 @@ import { LoadImage } from "./LoadImage";
|
|
|
216
216
|
onClick: function onClick() {
|
|
217
217
|
onExpandToggle === null || onExpandToggle === void 0 ? void 0 : onExpandToggle();
|
|
218
218
|
}
|
|
219
|
-
}, /*#__PURE__*/ React.createElement(ChevronsUpDown, null))))
|
|
219
|
+
}, /*#__PURE__*/ React.createElement(ChevronsUpDown, null)), ((element === null || element === void 0 ? void 0 : element.language) === 'html' || (element === null || element === void 0 ? void 0 : element.language) === 'markdown') && onLocalPreview && /*#__PURE__*/ React.createElement(ActionIconBox, {
|
|
220
|
+
title: (i18n === null || i18n === void 0 ? void 0 : (_i18n_locale4 = i18n.locale) === null || _i18n_locale4 === void 0 ? void 0 : _i18n_locale4.localPreview) || '本地预览',
|
|
221
|
+
theme: theme === 'chaos' ? 'dark' : 'light',
|
|
222
|
+
onClick: function onClick(e) {
|
|
223
|
+
e.stopPropagation();
|
|
224
|
+
onLocalPreview();
|
|
225
|
+
}
|
|
226
|
+
}, /*#__PURE__*/ React.createElement(ArrowUpRight, null))));
|
|
220
227
|
};
|
|
@@ -13,8 +13,9 @@ interface UseToolbarConfigProps {
|
|
|
13
13
|
onSelectionChange?: (selected: boolean) => void;
|
|
14
14
|
onViewModeToggle?: () => void;
|
|
15
15
|
viewMode?: 'preview' | 'code';
|
|
16
|
+
onLocalPreview?: () => void;
|
|
16
17
|
}
|
|
17
|
-
export declare function useToolbarConfig({ element, readonly, onCloseClick, setLanguage, isSelected, onSelectionChange, onViewModeToggle, viewMode, }: UseToolbarConfigProps): {
|
|
18
|
+
export declare function useToolbarConfig({ element, readonly, onCloseClick, setLanguage, isSelected, onSelectionChange, onViewModeToggle, viewMode, onLocalPreview, }: UseToolbarConfigProps): {
|
|
18
19
|
toolbarProps: {
|
|
19
20
|
element: CodeNode;
|
|
20
21
|
readonly: boolean;
|
|
@@ -24,6 +25,7 @@ export declare function useToolbarConfig({ element, readonly, onCloseClick, setL
|
|
|
24
25
|
onSelectionChange: ((selected: boolean) => void) | undefined;
|
|
25
26
|
onViewModeToggle: (() => void) | undefined;
|
|
26
27
|
viewMode: "code" | "preview" | undefined;
|
|
28
|
+
onLocalPreview: (() => void) | undefined;
|
|
27
29
|
};
|
|
28
30
|
};
|
|
29
31
|
export {};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 负责组装工具栏的属性和事件处理
|
|
4
4
|
*/ import { useCallback } from "react";
|
|
5
5
|
export function useToolbarConfig(param) {
|
|
6
|
-
var element = param.element, readonly = param.readonly, onCloseClick = param.onCloseClick, setLanguage = param.setLanguage, isSelected = param.isSelected, onSelectionChange = param.onSelectionChange, onViewModeToggle = param.onViewModeToggle, viewMode = param.viewMode;
|
|
6
|
+
var element = param.element, readonly = param.readonly, onCloseClick = param.onCloseClick, setLanguage = param.setLanguage, isSelected = param.isSelected, onSelectionChange = param.onSelectionChange, onViewModeToggle = param.onViewModeToggle, viewMode = param.viewMode, onLocalPreview = param.onLocalPreview;
|
|
7
7
|
// 组装语言选择器属性
|
|
8
8
|
var languageSelectorProps = useCallback(function() {
|
|
9
9
|
return {
|
|
@@ -27,7 +27,8 @@ export function useToolbarConfig(param) {
|
|
|
27
27
|
isSelected: isSelected,
|
|
28
28
|
onSelectionChange: onSelectionChange,
|
|
29
29
|
onViewModeToggle: onViewModeToggle,
|
|
30
|
-
viewMode: viewMode
|
|
30
|
+
viewMode: viewMode,
|
|
31
|
+
onLocalPreview: onLocalPreview
|
|
31
32
|
};
|
|
32
33
|
}, [
|
|
33
34
|
element,
|
|
@@ -37,7 +38,8 @@ export function useToolbarConfig(param) {
|
|
|
37
38
|
isSelected,
|
|
38
39
|
onSelectionChange,
|
|
39
40
|
onViewModeToggle,
|
|
40
|
-
viewMode
|
|
41
|
+
viewMode,
|
|
42
|
+
onLocalPreview
|
|
41
43
|
])();
|
|
42
44
|
return {
|
|
43
45
|
toolbarProps: toolbarProps
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 本地预览工具函数
|
|
3
|
+
* 支持在新窗口打开 HTML 或 Markdown(转为 HTML 后)内容
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 在新标签页打开 HTML 内容的本地预览(允许执行 JavaScript)
|
|
7
|
+
*/
|
|
8
|
+
export declare function openHtmlLocalPreview(htmlCode: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* 将 Markdown 转换为 HTML 后在新标签页打开本地预览
|
|
11
|
+
*/
|
|
12
|
+
export declare function openMarkdownLocalPreview(markdownCode: string): Promise<void>;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) {
|
|
10
|
+
resolve(value);
|
|
11
|
+
} else {
|
|
12
|
+
Promise.resolve(value).then(_next, _throw);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function _async_to_generator(fn) {
|
|
16
|
+
return function() {
|
|
17
|
+
var self = this, args = arguments;
|
|
18
|
+
return new Promise(function(resolve, reject) {
|
|
19
|
+
var gen = fn.apply(self, args);
|
|
20
|
+
function _next(value) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
22
|
+
}
|
|
23
|
+
function _throw(err) {
|
|
24
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
25
|
+
}
|
|
26
|
+
_next(undefined);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function _ts_generator(thisArg, body) {
|
|
31
|
+
var f, y, t, _ = {
|
|
32
|
+
label: 0,
|
|
33
|
+
sent: function() {
|
|
34
|
+
if (t[0] & 1) throw t[1];
|
|
35
|
+
return t[1];
|
|
36
|
+
},
|
|
37
|
+
trys: [],
|
|
38
|
+
ops: []
|
|
39
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
|
40
|
+
return d(g, "next", {
|
|
41
|
+
value: verb(0)
|
|
42
|
+
}), d(g, "throw", {
|
|
43
|
+
value: verb(1)
|
|
44
|
+
}), d(g, "return", {
|
|
45
|
+
value: verb(2)
|
|
46
|
+
}), typeof Symbol === "function" && d(g, Symbol.iterator, {
|
|
47
|
+
value: function() {
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
}), g;
|
|
51
|
+
function verb(n) {
|
|
52
|
+
return function(v) {
|
|
53
|
+
return step([
|
|
54
|
+
n,
|
|
55
|
+
v
|
|
56
|
+
]);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function step(op) {
|
|
60
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
61
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
62
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
63
|
+
if (y = 0, t) op = [
|
|
64
|
+
op[0] & 2,
|
|
65
|
+
t.value
|
|
66
|
+
];
|
|
67
|
+
switch(op[0]){
|
|
68
|
+
case 0:
|
|
69
|
+
case 1:
|
|
70
|
+
t = op;
|
|
71
|
+
break;
|
|
72
|
+
case 4:
|
|
73
|
+
_.label++;
|
|
74
|
+
return {
|
|
75
|
+
value: op[1],
|
|
76
|
+
done: false
|
|
77
|
+
};
|
|
78
|
+
case 5:
|
|
79
|
+
_.label++;
|
|
80
|
+
y = op[1];
|
|
81
|
+
op = [
|
|
82
|
+
0
|
|
83
|
+
];
|
|
84
|
+
continue;
|
|
85
|
+
case 7:
|
|
86
|
+
op = _.ops.pop();
|
|
87
|
+
_.trys.pop();
|
|
88
|
+
continue;
|
|
89
|
+
default:
|
|
90
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
91
|
+
_ = 0;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
95
|
+
_.label = op[1];
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
99
|
+
_.label = t[1];
|
|
100
|
+
t = op;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (t && _.label < t[2]) {
|
|
104
|
+
_.label = t[2];
|
|
105
|
+
_.ops.push(op);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (t[2]) _.ops.pop();
|
|
109
|
+
_.trys.pop();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
op = body.call(thisArg, _);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
op = [
|
|
115
|
+
6,
|
|
116
|
+
e
|
|
117
|
+
];
|
|
118
|
+
y = 0;
|
|
119
|
+
} finally{
|
|
120
|
+
f = t = 0;
|
|
121
|
+
}
|
|
122
|
+
if (op[0] & 5) throw op[1];
|
|
123
|
+
return {
|
|
124
|
+
value: op[0] ? op[1] : void 0,
|
|
125
|
+
done: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* @fileoverview 本地预览工具函数
|
|
131
|
+
* 支持在新窗口打开 HTML 或 Markdown(转为 HTML 后)内容
|
|
132
|
+
*/ import { markdownToHtml } from "../../../MarkdownEditor/editor/utils/markdownToHtml";
|
|
133
|
+
var MARKDOWN_PREVIEW_STYLE = "\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.6;\n color: #24292e;\n max-width: 900px;\n margin: 0 auto;\n padding: 32px 24px;\n background: #fff;\n }\n h1, h2, h3, h4, h5, h6 {\n border-bottom: 1px solid #eaecef;\n padding-bottom: 0.3em;\n margin-top: 24px;\n margin-bottom: 16px;\n font-weight: 600;\n line-height: 1.25;\n }\n pre {\n background: #f6f8fa;\n border-radius: 6px;\n padding: 16px;\n overflow: auto;\n font-size: 85%;\n line-height: 1.45;\n }\n code {\n background: rgba(175, 184, 193, 0.2);\n border-radius: 3px;\n font-size: 85%;\n padding: 0.2em 0.4em;\n }\n pre code {\n background: transparent;\n padding: 0;\n font-size: inherit;\n }\n blockquote {\n border-left: 4px solid #d0d7de;\n color: #57606a;\n margin: 0;\n padding: 0 1em;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n th, td {\n border: 1px solid #d0d7de;\n padding: 6px 13px;\n }\n tr:nth-child(even) {\n background: #f6f8fa;\n }\n img {\n max-width: 100%;\n }\n a {\n color: #0969da;\n text-decoration: none;\n }\n a:hover {\n text-decoration: underline;\n }\n hr {\n border: none;\n border-top: 1px solid #d0d7de;\n }\n";
|
|
134
|
+
function buildHtmlDocument(body, title) {
|
|
135
|
+
return '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>'.concat(title, '</title>\n <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous" />\n</head>\n<body>\n').concat(body, "\n</body>\n</html>");
|
|
136
|
+
}
|
|
137
|
+
function openBlobInNewTab(html) {
|
|
138
|
+
var blob = new Blob([
|
|
139
|
+
html
|
|
140
|
+
], {
|
|
141
|
+
type: 'text/html'
|
|
142
|
+
});
|
|
143
|
+
var url = URL.createObjectURL(blob);
|
|
144
|
+
var win = window.open(url, '_blank');
|
|
145
|
+
if (win) {
|
|
146
|
+
// 在新窗口加载完毕后释放 Blob URL
|
|
147
|
+
win.addEventListener('load', function() {
|
|
148
|
+
return URL.revokeObjectURL(url);
|
|
149
|
+
}, {
|
|
150
|
+
once: true
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
// 弹窗被拦截时延迟释放
|
|
154
|
+
setTimeout(function() {
|
|
155
|
+
return URL.revokeObjectURL(url);
|
|
156
|
+
}, 10000);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 在新标签页打开 HTML 内容的本地预览(允许执行 JavaScript)
|
|
161
|
+
*/ export function openHtmlLocalPreview(htmlCode) {
|
|
162
|
+
var needsDocumentWrapper = !/<html[\s>]/i.test(htmlCode) && !/<!DOCTYPE/i.test(htmlCode);
|
|
163
|
+
var fullHtml = needsDocumentWrapper ? buildHtmlDocument(htmlCode, 'HTML Preview') : htmlCode;
|
|
164
|
+
openBlobInNewTab(fullHtml);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 将 Markdown 转换为 HTML 后在新标签页打开本地预览
|
|
168
|
+
*/ export function openMarkdownLocalPreview(markdownCode) {
|
|
169
|
+
return _async_to_generator(function() {
|
|
170
|
+
var bodyHtml, fullHtml;
|
|
171
|
+
return _ts_generator(this, function(_state) {
|
|
172
|
+
switch(_state.label){
|
|
173
|
+
case 0:
|
|
174
|
+
return [
|
|
175
|
+
4,
|
|
176
|
+
markdownToHtml(markdownCode, undefined, {
|
|
177
|
+
openLinksInNewTab: true
|
|
178
|
+
})
|
|
179
|
+
];
|
|
180
|
+
case 1:
|
|
181
|
+
bodyHtml = _state.sent();
|
|
182
|
+
fullHtml = '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>Markdown Preview</title>\n <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" crossorigin="anonymous" />\n <style>'.concat(MARKDOWN_PREVIEW_STYLE, "</style>\n</head>\n<body>\n").concat(bodyHtml, "\n</body>\n</html>");
|
|
183
|
+
openBlobInNewTab(fullHtml);
|
|
184
|
+
return [
|
|
185
|
+
2
|
|
186
|
+
];
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
})();
|
|
190
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ant-design/agentic-ui",
|
|
3
|
-
"version": "2.30.
|
|
3
|
+
"version": "2.30.12",
|
|
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",
|