@ant-design/agentic-ui 2.29.45 → 2.29.47

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.
@@ -368,9 +368,10 @@ var getTaskList = function getTaskList(originData) {
368
368
  }, /*#__PURE__*/ React.createElement("div", {
369
369
  style: style,
370
370
  className: clsx("".concat(prefixClass, "-bubble-container"), "".concat(prefixClass, "-bubble-container-").concat(placement), _define_property({}, "".concat(prefixClass, "-bubble-container-pure"), props.pure), hashId)
371
- }, preMessageSameRole ? null : /*#__PURE__*/ React.createElement("div", {
371
+ }, !preMessageSameRole && (avatarDom || titleDom) ? /*#__PURE__*/ React.createElement("div", {
372
+ "data-testid": "bubble-avatar-title",
372
373
  className: clsx("".concat(prefixClass, "-bubble-avatar-title"), "".concat(prefixClass, "-bubble-avatar-title-").concat(placement), "".concat(prefixClass, "-bubble-avatar-title-ai"), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleAvatarTitleClassName, hashId, _define_property({}, "".concat(prefixClass, "-bubble-avatar-title-pure"), props.pure))
373
- }, avatarDom, titleDom), /*#__PURE__*/ React.createElement("div", {
374
+ }, avatarDom, titleDom) : null, /*#__PURE__*/ React.createElement("div", {
374
375
  style: {
375
376
  display: 'flex',
376
377
  gap: 4,
@@ -383,14 +384,14 @@ var getTaskList = function getTaskList(originData) {
383
384
  style: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
384
385
  className: clsx("".concat(prefixClass, "-bubble-before"), "".concat(prefixClass, "-bubble-before-").concat(placement), "".concat(prefixClass, "-bubble-before-ai"), hashId),
385
386
  "data-testid": "message-before"
386
- }, contentBeforeDom) : null, /*#__PURE__*/ React.createElement("div", {
387
+ }, contentBeforeDom) : null, childrenDom ? /*#__PURE__*/ React.createElement("div", {
387
388
  style: _object_spread({
388
389
  minWidth: standalone ? 'min(16px,100%)' : '0px'
389
390
  }, styles === null || styles === void 0 ? void 0 : styles.bubbleListItemContentStyle),
390
391
  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),
391
392
  onDoubleClick: props.onDoubleClick,
392
393
  "data-testid": "message-content"
393
- }, childrenDom), contentAfterDom)))));
394
+ }, childrenDom) : null, contentAfterDom)))));
394
395
  if ((bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.render) === false) return null;
395
396
  return /*#__PURE__*/ React.createElement(MessagesContext.Provider, {
396
397
  value: {
@@ -196,18 +196,19 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
196
196
  style: contentContainerStyle,
197
197
  className: clsx("".concat(prefixClass, "-bubble-container"), "".concat(prefixClass, "-bubble-container-").concat(placement), "".concat(prefixClass, "-bubble-container-user"), _define_property({}, "".concat(prefixClass, "-bubble-container-pure"), props.pure), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleContainerClassName, hashId),
198
198
  "data-testid": "chat-message"
199
- }, /*#__PURE__*/ React.createElement("div", {
199
+ }, titleDom ? /*#__PURE__*/ React.createElement("div", {
200
+ "data-testid": "bubble-avatar-title",
200
201
  className: clsx("".concat(prefixClass, "-bubble-avatar-title"), "".concat(prefixClass, "-bubble-avatar-title-").concat(placement), "".concat(prefixClass, "-bubble-avatar-title-ai"), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleAvatarTitleClassName, hashId, (_obj = {}, _define_property(_obj, "".concat(prefixClass, "-bubble-avatar-title-pure"), props.pure), _define_property(_obj, "".concat(prefixClass, "-bubble-avatar-title-quote"), quote === null || quote === void 0 ? void 0 : quote.quoteDescription), _obj))
201
- }, titleDom), contentBeforeDom && /*#__PURE__*/ React.createElement("div", {
202
+ }, titleDom) : null, contentBeforeDom && /*#__PURE__*/ React.createElement("div", {
202
203
  style: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
203
204
  className: clsx("".concat(prefixClass, "-bubble-before"), "".concat(prefixClass, "-bubble-before-").concat(placement), "".concat(prefixClass, "-bubble-before-user"), hashId),
204
205
  "data-testid": "message-before"
205
- }, contentBeforeDom), /*#__PURE__*/ React.createElement("div", {
206
+ }, contentBeforeDom), childrenDom ? /*#__PURE__*/ React.createElement("div", {
206
207
  style: contentStyle,
207
208
  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),
208
209
  onDoubleClick: props.onDoubleClick,
209
210
  "data-testid": "message-content"
210
- }, childrenDom), hasFileMap && /*#__PURE__*/ React.createElement("div", {
211
+ }, childrenDom) : null, hasFileMap && /*#__PURE__*/ React.createElement("div", {
211
212
  style: fileViewStyle,
212
213
  className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
213
214
  "data-testid": "message-after"
@@ -3,8 +3,8 @@ import type { ReactNode } from 'react';
3
3
  * 布局头部配置接口
4
4
  */
5
5
  export interface LayoutHeaderConfig {
6
- /** 标题文本 */
7
- title?: string;
6
+ /** 标题,支持文本或自定义 React 节点 */
7
+ title?: ReactNode;
8
8
  /** 是否显示分享按钮 */
9
9
  showShare?: boolean;
10
10
  /** 左侧是否可折叠 */
@@ -251,20 +251,28 @@ import { useEditorStore } from "../store";
251
251
  return Element.isElement(n) && n.type === 'paragraph';
252
252
  },
253
253
  mode: 'lowest'
254
- }), 1), node3 = _Editor_nodes3[0];
255
- if (node3 && node3[0].children.length === 1 && !EditorUtils.isDirtLeaf(node3[0].children[0]) && (e.key === 'Backspace' || /^[^\n]$/.test(e.key))) {
256
- var str = Node.string(node3[0]) || '';
257
- var codeMatch = str.match(/^```([\w+\-#]+)$/i);
258
- if (codeMatch) {} else {
259
- var strAfterKey = str + (e.key.length === 1 ? e.key : '');
260
- // 在实际输入一个字符且补全 trigger 时打开面板,支持在文本后输入(如 "hello {}")
261
- if (jinjaTemplatePanelEnabled && e.key.length === 1 && strAfterKey.endsWith(jinjaTrigger) && setOpenJinjaTemplate && setJinjaAnchorPath) {
254
+ }), 1), paraNode = _Editor_nodes3[0];
255
+ var node3 = paraNode;
256
+ if (node3) {
257
+ var _e_nativeEvent1;
258
+ var sel = markdownEditorRef.current.selection;
259
+ // Jinja 触发:基于光标位置检测,支持在任意位置输入 {}(含两个模板中间)
260
+ if (jinjaTemplatePanelEnabled && e.key.length === 1 && !((_e_nativeEvent1 = e.nativeEvent) === null || _e_nativeEvent1 === void 0 ? void 0 : _e_nativeEvent1.isComposing) && sel && Range.isCollapsed(sel) && Path.isAncestor(node3[1], sel.anchor.path) && setOpenJinjaTemplate && setJinjaAnchorPath) {
261
+ var strBeforeCursor = Editor.string(markdownEditorRef.current, Editor.range(markdownEditorRef.current, Editor.start(markdownEditorRef.current, node3[1]), sel.anchor));
262
+ var strAfterKeyAtCursor = strBeforeCursor + (e.key.length === 1 ? e.key : '');
263
+ if (strAfterKeyAtCursor.endsWith(jinjaTrigger)) {
262
264
  setJinjaAnchorPath(node3[1]);
263
265
  setTimeout(function() {
264
266
  return setOpenJinjaTemplate(true);
265
267
  });
266
268
  return;
267
269
  }
270
+ }
271
+ }
272
+ if (node3 && node3[0].children.length === 1 && !EditorUtils.isDirtLeaf(node3[0].children[0]) && (e.key === 'Backspace' || /^[^\n]$/.test(e.key))) {
273
+ var str = Node.string(node3[0]) || '';
274
+ var codeMatch = str.match(/^```([\w+\-#]+)$/i);
275
+ if (codeMatch) {} else {
268
276
  var insertMatch = str.match(/^\/([^\n]+)?$/i);
269
277
  if (insertMatch && !(!Path.hasPrevious(node3[1]) && Node.parent(markdownEditorRef.current, node3[1]).type === 'list-item')) {
270
278
  setOpenInsertCompletion === null || setOpenInsertCompletion === void 0 ? void 0 : setOpenInsertCompletion(true);
@@ -123,6 +123,7 @@ export var JinjaTemplatePanel = function JinjaTemplatePanel() {
123
123
  position: 'fixed'
124
124
  }), 2), position = _useState3[0], setPosition = _useState3[1];
125
125
  var domRef = useRef(null);
126
+ var openTimeRef = useRef(0);
126
127
  var context = React.useContext(ConfigProvider.ConfigContext);
127
128
  var prefixCls = (_ref3 = context === null || context === void 0 ? void 0 : (_context_getPrefixCls = context.getPrefixCls) === null || _context_getPrefixCls === void 0 ? void 0 : _context_getPrefixCls.call(context, 'agentic-md-editor-jinja-panel')) !== null && _ref3 !== void 0 ? _ref3 : JINJA_PANEL_PREFIX_CLS;
128
129
  var _useJinjaTemplatePanelStyle = useJinjaTemplatePanelStyle(prefixCls), wrapSSR = _useJinjaTemplatePanelStyle.wrapSSR, hashId = _useJinjaTemplatePanelStyle.hashId;
@@ -137,6 +138,10 @@ export var JinjaTemplatePanel = function JinjaTemplatePanel() {
137
138
  var handleClickOutside = useCallback(function(e) {
138
139
  var target = e.target;
139
140
  if (domRef.current && !domRef.current.contains(target)) {
141
+ // 忽略弹窗打开后短时间内的点击,避免「点击聚焦编辑器后快速输入 {}」
142
+ // 触发的陈旧 click 事件立即关闭弹窗
143
+ var elapsed = Date.now() - openTimeRef.current;
144
+ if (elapsed < 150) return;
140
145
  close();
141
146
  }
142
147
  }, [
@@ -196,6 +201,7 @@ export var JinjaTemplatePanel = function JinjaTemplatePanel() {
196
201
  useEffect(function() {
197
202
  if (!openJinjaTemplate) return;
198
203
  if (typeof window === 'undefined') return;
204
+ openTimeRef.current = Date.now();
199
205
  window.addEventListener('click', handleClickOutside);
200
206
  return function() {
201
207
  return window.removeEventListener('click', handleClickOutside);
@@ -343,6 +343,7 @@ import { useVoiceInputManager } from "./VoiceInputManager";
343
343
  }, tagInputProps)
344
344
  }, /*#__PURE__*/ React.createElement("div", {
345
345
  ref: inputRef,
346
+ "data-testid": "markdown-input-field",
346
347
  className: classNames(baseCls, hashId, props.className, (_obj = {}, _define_property(_obj, "".concat(baseCls, "-disabled"), props.disabled), _define_property(_obj, "".concat(baseCls, "-skill-mode"), (_props_skillMode = props.skillMode) === null || _props_skillMode === void 0 ? void 0 : _props_skillMode.open), _define_property(_obj, "".concat(baseCls, "-typing"), false), _define_property(_obj, "".concat(baseCls, "-loading"), isLoading), _define_property(_obj, "".concat(baseCls, "-is-multi-row"), isMultiRowLayout), _define_property(_obj, "".concat(baseCls, "-enlarged"), isEnlarged), _define_property(_obj, "".concat(baseCls, "-focused"), isFocused), _define_property(_obj, "".concat(baseCls, "-has-tools-wrapper"), !!props.toolsRender), _obj)),
347
348
  style: _object_spread_props(_object_spread({}, props.style, enlargedStyle), {
348
349
  height: isEnlarged ? "".concat((_ref = (_props_enlargeable = props.enlargeable) === null || _props_enlargeable === void 0 ? void 0 : _props_enlargeable.height) !== null && _ref !== void 0 ? _ref : 980, "px") : "min(".concat(collapsedHeightPx, "px,100%)"),
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { TaskListProps } from './types';
3
+ export declare const TaskList: React.MemoExoticComponent<({ items, className, expandedKeys, onExpandedKeysChange, variant, open, onOpenChange, }: TaskListProps) => any>;
@@ -0,0 +1,210 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _array_without_holes(arr) {
10
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
11
+ }
12
+ function _iterable_to_array(iter) {
13
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
14
+ }
15
+ function _iterable_to_array_limit(arr, i) {
16
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
17
+ if (_i == null) return;
18
+ var _arr = [];
19
+ var _n = true;
20
+ var _d = false;
21
+ var _s, _e;
22
+ try {
23
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
24
+ _arr.push(_s.value);
25
+ if (i && _arr.length === i) break;
26
+ }
27
+ } catch (err) {
28
+ _d = true;
29
+ _e = err;
30
+ } finally{
31
+ try {
32
+ if (!_n && _i["return"] != null) _i["return"]();
33
+ } finally{
34
+ if (_d) throw _e;
35
+ }
36
+ }
37
+ return _arr;
38
+ }
39
+ function _non_iterable_rest() {
40
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
41
+ }
42
+ function _non_iterable_spread() {
43
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
44
+ }
45
+ function _sliced_to_array(arr, i) {
46
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
47
+ }
48
+ function _to_consumable_array(arr) {
49
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
50
+ }
51
+ function _unsupported_iterable_to_array(o, minLen) {
52
+ if (!o) return;
53
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
54
+ var n = Object.prototype.toString.call(o).slice(8, -1);
55
+ if (n === "Object" && o.constructor) n = o.constructor.name;
56
+ if (n === "Map" || n === "Set") return Array.from(n);
57
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
58
+ }
59
+ import { ChevronUp } from "@sofa-design/icons";
60
+ import { ConfigProvider } from "antd";
61
+ import classNames from "clsx";
62
+ import { AnimatePresence, motion } from "framer-motion";
63
+ import { useMergedState } from "rc-util";
64
+ import React, { memo, useContext, useMemo } from "react";
65
+ import { ActionIconBox } from "../Components/ActionIconBox";
66
+ import { useRefFunction } from "../Hooks/useRefFunction";
67
+ import { I18nContext } from "../I18n";
68
+ import { StatusIcon } from "./components/StatusIcon";
69
+ import { TaskListItem } from "./components/TaskListItem";
70
+ import { COLLAPSE_TRANSITION, COLLAPSE_VARIANTS, getArrowRotation } from "./constants";
71
+ import { useStyle } from "./style";
72
+ var getDefaultExpandedKeys = function getDefaultExpandedKeys(items, isControlled) {
73
+ return isControlled ? [] : items.map(function(item) {
74
+ return item.key;
75
+ });
76
+ };
77
+ export var TaskList = /*#__PURE__*/ memo(function(param) {
78
+ var items = param.items, className = param.className, expandedKeys = param.expandedKeys, onExpandedKeysChange = param.onExpandedKeysChange, _param_variant = param.variant, variant = _param_variant === void 0 ? 'default' : _param_variant, open = param.open, onOpenChange = param.onOpenChange;
79
+ var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
80
+ var prefixCls = getPrefixCls('task-list');
81
+ var _useStyle = useStyle(prefixCls), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
82
+ var locale = useContext(I18nContext).locale;
83
+ var isControlled = expandedKeys !== undefined;
84
+ var _useMergedState = _sliced_to_array(useMergedState(getDefaultExpandedKeys(items, isControlled), {
85
+ value: expandedKeys,
86
+ onChange: onExpandedKeysChange
87
+ }), 2), internalExpandedKeys = _useMergedState[0], setInternalExpandedKeys = _useMergedState[1];
88
+ var handleToggle = useRefFunction(function(key) {
89
+ var currentExpanded = isControlled ? expandedKeys : internalExpandedKeys;
90
+ var newExpandedKeys = currentExpanded.includes(key) ? currentExpanded.filter(function(k) {
91
+ return k !== key;
92
+ }) : _to_consumable_array(currentExpanded).concat([
93
+ key
94
+ ]);
95
+ setInternalExpandedKeys(newExpandedKeys);
96
+ });
97
+ var _useMergedState1 = _sliced_to_array(useMergedState(false, {
98
+ value: open,
99
+ onChange: function onChange(val) {
100
+ return onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(val);
101
+ }
102
+ }), 2), simpleExpanded = _useMergedState1[0], setSimpleExpanded = _useMergedState1[1];
103
+ var handleSimpleToggle = useRefFunction(function() {
104
+ setSimpleExpanded(function(prev) {
105
+ return !prev;
106
+ });
107
+ });
108
+ var _useMemo = useMemo(function() {
109
+ var completedCount = items.filter(function(i) {
110
+ return i.status === 'success';
111
+ }).length;
112
+ var loadingItem = items.find(function(i) {
113
+ return i.status === 'loading';
114
+ });
115
+ var hasError = items.some(function(i) {
116
+ return i.status === 'error';
117
+ });
118
+ var allDone = completedCount === items.length && items.length > 0;
119
+ var status = 'pending';
120
+ var text = (locale === null || locale === void 0 ? void 0 : locale['taskList.taskList']) || '任务列表';
121
+ if (allDone) {
122
+ status = 'success';
123
+ text = (locale === null || locale === void 0 ? void 0 : locale['taskList.taskComplete']) || '任务完成';
124
+ } else if (loadingItem === null || loadingItem === void 0 ? void 0 : loadingItem.title) {
125
+ status = 'loading';
126
+ var tpl = (locale === null || locale === void 0 ? void 0 : locale['taskList.taskInProgress']) || '正在进行${taskName}任务';
127
+ var title = loadingItem.title;
128
+ var taskName = typeof title === 'string' || typeof title === 'number' ? String(title) : '';
129
+ text = tpl.replace('${taskName}', taskName);
130
+ } else if (hasError) {
131
+ status = 'error';
132
+ text = (locale === null || locale === void 0 ? void 0 : locale['taskList.taskAborted']) || '任务已取消';
133
+ }
134
+ return {
135
+ summaryStatus: status,
136
+ summaryText: text,
137
+ progressText: "".concat(completedCount, "/").concat(items.length)
138
+ };
139
+ }, [
140
+ items,
141
+ locale
142
+ ]), summaryStatus = _useMemo.summaryStatus, summaryText = _useMemo.summaryText, progressText = _useMemo.progressText;
143
+ var renderItems = function renderItems() {
144
+ return items.map(function(item, index) {
145
+ return /*#__PURE__*/ React.createElement(TaskListItem, {
146
+ key: item.key,
147
+ item: item,
148
+ isLast: index === items.length - 1,
149
+ prefixCls: prefixCls,
150
+ hashId: hashId,
151
+ expandedKeys: internalExpandedKeys,
152
+ onToggle: handleToggle
153
+ });
154
+ });
155
+ };
156
+ if (variant !== 'simple') {
157
+ return wrapSSR(/*#__PURE__*/ React.createElement("div", {
158
+ className: className
159
+ }, renderItems()));
160
+ }
161
+ var simpleCls = "".concat(prefixCls, "-simple");
162
+ var simpleArrowTitle = simpleExpanded ? (locale === null || locale === void 0 ? void 0 : locale['taskList.collapse']) || '收起' : (locale === null || locale === void 0 ? void 0 : locale['taskList.expand']) || '展开';
163
+ return wrapSSR(/*#__PURE__*/ React.createElement("div", {
164
+ className: classNames("".concat(simpleCls, "-wrapper"), hashId, className),
165
+ "data-testid": "task-list-simple-wrapper"
166
+ }, /*#__PURE__*/ React.createElement("div", {
167
+ className: classNames(simpleCls, hashId),
168
+ onClick: handleSimpleToggle,
169
+ role: "button",
170
+ tabIndex: 0,
171
+ "aria-expanded": simpleExpanded,
172
+ "aria-label": simpleArrowTitle,
173
+ "data-testid": "task-list-simple-bar"
174
+ }, /*#__PURE__*/ React.createElement("div", {
175
+ className: classNames("".concat(simpleCls, "-status"), hashId)
176
+ }, /*#__PURE__*/ React.createElement(StatusIcon, {
177
+ status: summaryStatus,
178
+ prefixCls: prefixCls,
179
+ hashId: hashId
180
+ })), /*#__PURE__*/ React.createElement("div", {
181
+ className: classNames("".concat(simpleCls, "-text"), hashId)
182
+ }, summaryText), /*#__PURE__*/ React.createElement("div", {
183
+ className: classNames("".concat(simpleCls, "-progress"), hashId)
184
+ }, progressText), /*#__PURE__*/ React.createElement("div", {
185
+ className: classNames("".concat(simpleCls, "-arrow"), hashId)
186
+ }, /*#__PURE__*/ React.createElement(ActionIconBox, {
187
+ title: simpleArrowTitle,
188
+ iconStyle: getArrowRotation(!simpleExpanded),
189
+ loading: false,
190
+ onClick: function onClick(e) {
191
+ e.stopPropagation();
192
+ handleSimpleToggle();
193
+ }
194
+ }, /*#__PURE__*/ React.createElement(ChevronUp, {
195
+ "data-testid": "task-list-simple-arrow"
196
+ })))), /*#__PURE__*/ React.createElement(AnimatePresence, {
197
+ initial: false
198
+ }, simpleExpanded && /*#__PURE__*/ React.createElement(motion.div, {
199
+ key: "simple-task-list-content",
200
+ variants: COLLAPSE_VARIANTS,
201
+ initial: "collapsed",
202
+ animate: "expanded",
203
+ exit: "collapsed",
204
+ transition: COLLAPSE_TRANSITION,
205
+ className: classNames("".concat(simpleCls, "-content"), hashId)
206
+ }, /*#__PURE__*/ React.createElement("div", {
207
+ className: classNames("".concat(simpleCls, "-list"), hashId)
208
+ }, renderItems())))));
209
+ });
210
+ TaskList.displayName = 'TaskList';
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { TaskStatus } from '../types';
3
+ interface StatusIconProps {
4
+ status: TaskStatus;
5
+ prefixCls: string;
6
+ hashId: string;
7
+ }
8
+ export declare const StatusIcon: React.FC<StatusIconProps>;
9
+ export {};
@@ -0,0 +1,23 @@
1
+ import { CircleDashed, SuccessFill, X } from "@sofa-design/icons";
2
+ import classNames from "clsx";
3
+ import React, { memo } from "react";
4
+ import { Loading } from "../../Components/Loading";
5
+ import { LOADING_SIZE } from "../constants";
6
+ export var StatusIcon = /*#__PURE__*/ memo(function(param) {
7
+ var status = param.status, prefixCls = param.prefixCls, hashId = param.hashId;
8
+ var statusMap = {
9
+ success: /*#__PURE__*/ React.createElement(SuccessFill, null),
10
+ loading: /*#__PURE__*/ React.createElement(Loading, {
11
+ size: LOADING_SIZE
12
+ }),
13
+ pending: /*#__PURE__*/ React.createElement("div", {
14
+ className: classNames("".concat(prefixCls, "-status-idle"), hashId)
15
+ }, /*#__PURE__*/ React.createElement(CircleDashed, null)),
16
+ error: /*#__PURE__*/ React.createElement(X, null)
17
+ };
18
+ return /*#__PURE__*/ React.createElement("div", {
19
+ className: classNames("".concat(prefixCls, "-status"), "".concat(prefixCls, "-status-").concat(status), hashId),
20
+ "data-testid": "task-list-status-".concat(status)
21
+ }, statusMap[status]);
22
+ });
23
+ StatusIcon.displayName = 'StatusIcon';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { TaskItem } from '../types';
3
+ interface TaskListItemProps {
4
+ item: TaskItem;
5
+ isLast: boolean;
6
+ prefixCls: string;
7
+ hashId: string;
8
+ expandedKeys: string[];
9
+ onToggle: (key: string) => void;
10
+ }
11
+ export declare const TaskListItem: React.FC<TaskListItemProps>;
12
+ export {};
@@ -0,0 +1,68 @@
1
+ import { ChevronUp } from "@sofa-design/icons";
2
+ import classNames from "clsx";
3
+ import { AnimatePresence, motion } from "framer-motion";
4
+ import React, { memo, useCallback, useContext } from "react";
5
+ import { ActionIconBox } from "../../Components/ActionIconBox";
6
+ import { I18nContext } from "../../I18n";
7
+ import { COLLAPSE_TRANSITION, COLLAPSE_VARIANTS, getArrowRotation, hasTaskContent } from "../constants";
8
+ import { StatusIcon } from "./StatusIcon";
9
+ export var TaskListItem = /*#__PURE__*/ memo(function(param) {
10
+ var item = param.item, isLast = param.isLast, prefixCls = param.prefixCls, hashId = param.hashId, expandedKeys = param.expandedKeys, onToggle = param.onToggle;
11
+ var locale = useContext(I18nContext).locale;
12
+ var isCollapsed = !expandedKeys.includes(item.key);
13
+ var hasContent = hasTaskContent(item.content);
14
+ var handleToggle = useCallback(function() {
15
+ onToggle(item.key);
16
+ }, [
17
+ item.key,
18
+ onToggle
19
+ ]);
20
+ var arrowTitle = isCollapsed ? (locale === null || locale === void 0 ? void 0 : locale['taskList.expand']) || '展开' : (locale === null || locale === void 0 ? void 0 : locale['taskList.collapse']) || '收起';
21
+ return /*#__PURE__*/ React.createElement("div", {
22
+ key: item.key,
23
+ className: classNames("".concat(prefixCls, "-thoughtChainItem"), hashId),
24
+ "data-testid": "task-list-thoughtChainItem"
25
+ }, /*#__PURE__*/ React.createElement("div", {
26
+ className: classNames("".concat(prefixCls, "-left"), hashId),
27
+ onClick: handleToggle,
28
+ "data-testid": "task-list-left"
29
+ }, /*#__PURE__*/ React.createElement(StatusIcon, {
30
+ status: item.status,
31
+ prefixCls: prefixCls,
32
+ hashId: hashId
33
+ }), /*#__PURE__*/ React.createElement("div", {
34
+ className: classNames("".concat(prefixCls, "-content-left"), hashId)
35
+ }, !isLast && /*#__PURE__*/ React.createElement("div", {
36
+ className: classNames("".concat(prefixCls, "-dash-line"), hashId),
37
+ "data-testid": "task-list-dash-line"
38
+ }))), /*#__PURE__*/ React.createElement("div", {
39
+ className: classNames("".concat(prefixCls, "-right"), hashId)
40
+ }, /*#__PURE__*/ React.createElement("div", {
41
+ className: classNames("".concat(prefixCls, "-top"), hashId),
42
+ onClick: handleToggle
43
+ }, /*#__PURE__*/ React.createElement("div", {
44
+ className: classNames("".concat(prefixCls, "-title"), hashId)
45
+ }, item.title), hasContent && /*#__PURE__*/ React.createElement("div", {
46
+ className: classNames("".concat(prefixCls, "-arrowContainer"), hashId),
47
+ "data-testid": "task-list-arrowContainer"
48
+ }, /*#__PURE__*/ React.createElement(ActionIconBox, {
49
+ title: arrowTitle,
50
+ iconStyle: getArrowRotation(isCollapsed),
51
+ loading: false
52
+ }, /*#__PURE__*/ React.createElement(ChevronUp, {
53
+ "data-testid": "task-list-arrow"
54
+ })))), /*#__PURE__*/ React.createElement(AnimatePresence, {
55
+ initial: false
56
+ }, !isCollapsed && /*#__PURE__*/ React.createElement(motion.div, {
57
+ key: "task-content",
58
+ variants: COLLAPSE_VARIANTS,
59
+ initial: "collapsed",
60
+ animate: "expanded",
61
+ exit: "collapsed",
62
+ transition: COLLAPSE_TRANSITION,
63
+ className: classNames("".concat(prefixCls, "-body"), hashId)
64
+ }, /*#__PURE__*/ React.createElement("div", {
65
+ className: classNames("".concat(prefixCls, "-content"), hashId)
66
+ }, item.content)))));
67
+ });
68
+ TaskListItem.displayName = 'TaskListItem';
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ export declare const LOADING_SIZE = 16;
3
+ export declare const COLLAPSE_VARIANTS: {
4
+ expanded: {
5
+ height: string;
6
+ opacity: number;
7
+ };
8
+ collapsed: {
9
+ height: number;
10
+ opacity: number;
11
+ };
12
+ };
13
+ export declare const COLLAPSE_TRANSITION: {
14
+ height: {
15
+ duration: number;
16
+ ease: number[];
17
+ };
18
+ opacity: {
19
+ duration: number;
20
+ ease: string;
21
+ };
22
+ };
23
+ export declare const getArrowRotation: (collapsed: boolean) => React.CSSProperties;
24
+ export declare const hasTaskContent: (content: React.ReactNode | React.ReactNode[]) => boolean;
@@ -0,0 +1,38 @@
1
+ export var LOADING_SIZE = 16;
2
+ export var COLLAPSE_VARIANTS = {
3
+ expanded: {
4
+ height: 'auto',
5
+ opacity: 1
6
+ },
7
+ collapsed: {
8
+ height: 0,
9
+ opacity: 0
10
+ }
11
+ };
12
+ export var COLLAPSE_TRANSITION = {
13
+ height: {
14
+ duration: 0.26,
15
+ ease: [
16
+ 0.4,
17
+ 0,
18
+ 0.2,
19
+ 1
20
+ ]
21
+ },
22
+ opacity: {
23
+ duration: 0.2,
24
+ ease: 'linear'
25
+ }
26
+ };
27
+ export var getArrowRotation = function getArrowRotation(collapsed) {
28
+ return {
29
+ transform: collapsed ? 'rotate(0deg)' : 'rotate(180deg)',
30
+ transition: 'transform 0.3s ease'
31
+ };
32
+ };
33
+ export var hasTaskContent = function hasTaskContent(content) {
34
+ if (Array.isArray(content)) {
35
+ return content.length > 0;
36
+ }
37
+ return !!content;
38
+ };
@@ -1,50 +1,2 @@
1
- import React from 'react';
2
- type TaskStatus = 'success' | 'pending' | 'loading' | 'error';
3
- type TaskItem = {
4
- key: string;
5
- title?: React.ReactNode;
6
- content: React.ReactNode | React.ReactNode[];
7
- status: TaskStatus;
8
- };
9
- /**
10
- * TaskList 组件属性
11
- */
12
- export type TaskListProps = {
13
- /** 任务列表数据 */
14
- items: TaskItem[];
15
- /** 自定义类名 */
16
- className?: string;
17
- /** 受控模式:指定当前展开的任务项 key 数组 */
18
- expandedKeys?: string[];
19
- /** 受控模式:展开状态变化时的回调函数 */
20
- onExpandedKeysChange?: (expandedKeys: string[]) => void;
21
- };
22
- /**
23
- * @deprecated @since 2.30.0 请使用 TaskListProps 替代
24
- */
25
- export type ThoughtChainProps = TaskListProps;
26
- /**
27
- * TaskList 组件
28
- *
29
- * 显示任务列表,支持展开/折叠、状态管理等功能
30
- * 支持受控和非受控两种模式
31
- *
32
- * @example
33
- * ```tsx
34
- * // 非受控模式
35
- * <TaskList
36
- * items={[
37
- * { key: 'task1', title: '任务1', content: '内容', status: 'success' }
38
- * ]}
39
- * />
40
- *
41
- * // 受控模式
42
- * <TaskList
43
- * items={tasks}
44
- * expandedKeys={expandedKeys}
45
- * onExpandedKeysChange={setExpandedKeys}
46
- * />
47
- * ```
48
- */
49
- export declare const TaskList: React.MemoExoticComponent<({ items, className, expandedKeys, onExpandedKeysChange }: TaskListProps) => any>;
50
- export {};
1
+ export { TaskList } from './TaskList';
2
+ export type { TaskItem, TaskListProps, TaskListVariant, TaskStatus, ThoughtChainProps, } from './types';