@ant-design/agentic-ui 2.30.26 → 2.30.27

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.
@@ -231,6 +231,8 @@ var I18nBoundary = function I18nBoundary(param) {
231
231
  // markdown 编辑器实例
232
232
  var markdownEditorRef = useRef(composeEditors(withMarkdown(withReact(withHistory(createEditor()))), props.plugins || []));
233
233
  var markdownContainerRef = useRef(null);
234
+ var pluginsForInitParseRef = useRef(props.plugins);
235
+ pluginsForInitParseRef.current = props.plugins;
234
236
  // 错误捕获
235
237
  useEffect(function() {
236
238
  withErrorReporting(markdownEditorRef.current);
@@ -282,7 +284,7 @@ var I18nBoundary = function I18nBoundary(param) {
282
284
  * 初始化 schema
283
285
  */ var initSchemaValue = useMemo(function() {
284
286
  // 安全地获取解析结果,确保 list 始终是数组
285
- var parseResult = parserMdToSchema(initValue || '', props.plugins);
287
+ var parseResult = parserMdToSchema(initValue || '', pluginsForInitParseRef.current || []);
286
288
  var list = (parseResult === null || parseResult === void 0 ? void 0 : parseResult.schema) || [];
287
289
  // 非只读时保证末尾有可编辑块:解析结果常已含空段落(如空 initValue),
288
290
  // 再追加会导致 Slate 根下两个空段,Paragraph 的占位符依赖 children.length===1 而失效
@@ -296,7 +298,7 @@ var I18nBoundary = function I18nBoundary(param) {
296
298
  EditorUtils.p
297
299
  ])));
298
300
  // 过滤掉无效的空节点
299
- return schema === null || schema === void 0 ? void 0 : schema.filter(function(item) {
301
+ var filtered = (schema === null || schema === void 0 ? void 0 : schema.filter(function(item) {
300
302
  if (item.type === 'paragraph' && item.children.length === 0) {
301
303
  return false;
302
304
  }
@@ -310,8 +312,13 @@ var I18nBoundary = function I18nBoundary(param) {
310
312
  return false;
311
313
  }
312
314
  return true;
313
- });
314
- }, []);
315
+ })) || [];
316
+ return EditorUtils.coalesceRootAllEmptyParagraphs(filtered);
317
+ }, [
318
+ initValue,
319
+ props.readonly,
320
+ props.initSchemaValue
321
+ ]);
315
322
  // 初始化实例
316
323
  var instance = useMemo(function() {
317
324
  return {
@@ -347,6 +354,12 @@ var I18nBoundary = function I18nBoundary(param) {
347
354
  var _useState2 = _sliced_to_array(useState([]), 2), showCommentList = _useState2[0], setShowComment = _useState2[1];
348
355
  // schema 数据
349
356
  var _useState3 = _sliced_to_array(useState(initSchemaValue), 2), schema = _useState3[0], setSchema = _useState3[1];
357
+ // initSchemaValue 随 initValue / initSchemaValue prop 变化时同步到 state,供 Toc 等与编辑器树一致
358
+ useEffect(function() {
359
+ setSchema(initSchemaValue);
360
+ }, [
361
+ initSchemaValue
362
+ ]);
350
363
  var _useState4 = _sliced_to_array(useState(false), 2), openInsertCompletion = _useState4[0], setOpenInsertCompletion = _useState4[1];
351
364
  var _useState5 = _sliced_to_array(useState(false), 2), refreshFloatBar = _useState5[0], setRefreshFloatBar = _useState5[1];
352
365
  var insertCompletionText$ = useMemo(function() {
@@ -8,7 +8,7 @@ import { ElementProps, ParagraphNode } from '../../../el';
8
8
  *
9
9
  * @component
10
10
  * @description 只读段落预览组件,用于预览模式下的段落渲染
11
- * @param {ElementProps<ParagraphNode>} props - 组件属性
11
+ * @param {ElementProps<ParagraphNode>} props - 段落组件属性
12
12
  * @param {ParagraphNode} props.element - 段落节点元素
13
13
  * @param {React.ReactNode} props.children - 子组件内容
14
14
  * @param {Object} props.attributes - 元素属性
@@ -23,7 +23,7 @@ import { ElementProps, ParagraphNode } from '../../../el';
23
23
  * </ReadonlyParagraph>
24
24
  * ```
25
25
  *
26
- * @returns {React.ReactElement} 渲染的只读段落组件
26
+ * @returns {React.ReactElement}
27
27
  *
28
28
  * @remarks
29
29
  * - 移除拖拽手柄(DragHandle)
@@ -52,7 +52,6 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import classNames from "clsx";
54
54
  import React from "react";
55
- import { Element, Node } from "slate";
56
55
  /**
57
56
  * ReadonlyParagraph 组件 - 只读段落预览组件
58
57
  *
@@ -61,7 +60,7 @@ import { Element, Node } from "slate";
61
60
  *
62
61
  * @component
63
62
  * @description 只读段落预览组件,用于预览模式下的段落渲染
64
- * @param {ElementProps<ParagraphNode>} props - 组件属性
63
+ * @param {ElementProps<ParagraphNode>} props - 段落组件属性
65
64
  * @param {ParagraphNode} props.element - 段落节点元素
66
65
  * @param {React.ReactNode} props.children - 子组件内容
67
66
  * @param {Object} props.attributes - 元素属性
@@ -76,7 +75,7 @@ import { Element, Node } from "slate";
76
75
  * </ReadonlyParagraph>
77
76
  * ```
78
77
  *
79
- * @returns {React.ReactElement} 渲染的只读段落组件
78
+ * @returns {React.ReactElement}
80
79
  *
81
80
  * @remarks
82
81
  * - 移除拖拽手柄(DragHandle)
@@ -87,17 +86,12 @@ import { Element, Node } from "slate";
87
86
  */ export var ReadonlyParagraph = /*#__PURE__*/ React.memo(function(props) {
88
87
  var _props_element_align;
89
88
  var _props_element_otherProps;
90
- var str = Node.string(props.element).trim();
91
89
  var align = (_props_element_align = props.element.align) !== null && _props_element_align !== void 0 ? _props_element_align : (_props_element_otherProps = props.element.otherProps) === null || _props_element_otherProps === void 0 ? void 0 : _props_element_otherProps.align;
92
- var hasNestedElement = props.element.children.some(function(child) {
93
- return Element.isElement(child);
94
- });
95
90
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props.attributes), {
96
91
  "data-be": 'paragraph',
97
92
  className: classNames({}),
98
93
  "data-align": align,
99
94
  style: {
100
- display: str || hasNestedElement ? undefined : 'none',
101
95
  textAlign: align
102
96
  }
103
97
  }), props.children);
@@ -97,12 +97,13 @@ function _unsupported_iterable_to_array(o, minLen) {
97
97
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
98
98
  }
99
99
  import classNames from "clsx";
100
- import React, { useContext } from "react";
101
- import { Element, Node } from "slate";
100
+ import React, { useContext, useEffect, useState } from "react";
101
+ import { Node } from "slate";
102
102
  import { I18nContext } from "../../../../I18n";
103
103
  import { debugInfo } from "../../../../Utils/debugUtils";
104
104
  import { useSelStatus } from "../../../hooks/editor";
105
105
  import { useEditorStore } from "../../store";
106
+ import { DragHandle } from "../../tools/DragHandle";
106
107
  export var Paragraph = function Paragraph(props) {
107
108
  var _props_element_align;
108
109
  var _props_element_otherProps, _markdownEditorRef_current;
@@ -114,6 +115,25 @@ export var Paragraph = function Paragraph(props) {
114
115
  var _useEditorStore = useEditorStore(), store = _useEditorStore.store, markdownEditorRef = _useEditorStore.markdownEditorRef, markdownContainerRef = _useEditorStore.markdownContainerRef, readonly = _useEditorStore.readonly, editorProps = _useEditorStore.editorProps;
115
116
  var locale = useContext(I18nContext).locale;
116
117
  var _useSelStatus = _sliced_to_array(useSelStatus(props.element), 1), selected = _useSelStatus[0];
118
+ var _useState = _sliced_to_array(useState(false), 2), isComposing = _useState[0], setIsComposing = _useState[1];
119
+ useEffect(function() {
120
+ var container = markdownContainerRef.current;
121
+ if (!container) return;
122
+ var observer = new MutationObserver(function() {
123
+ setIsComposing(container.hasAttribute('data-composition'));
124
+ });
125
+ observer.observe(container, {
126
+ attributes: true,
127
+ attributeFilter: [
128
+ 'data-composition'
129
+ ]
130
+ });
131
+ return function() {
132
+ return observer.disconnect();
133
+ };
134
+ }, [
135
+ markdownContainerRef
136
+ ]);
117
137
  return React.useMemo(function() {
118
138
  var _props_element_children_every, _props_element_children, _props_element, _markdownEditorRef_current;
119
139
  var str = Node.string(props.element).trim();
@@ -123,17 +143,10 @@ export var Paragraph = function Paragraph(props) {
123
143
  readonly: readonly,
124
144
  align: align
125
145
  });
126
- // 检查是否为空:trim 后的字符串为空(包括只包含空格的情况),且所有子节点都是纯文本节点(没有 type、code、tag)
127
- // 当只输入空格时,trim() 后为空字符串,应该显示 placeholder
128
146
  var hasOnlyTextNodes = (_props_element = props.element) === null || _props_element === void 0 ? void 0 : (_props_element_children = _props_element.children) === null || _props_element_children === void 0 ? void 0 : (_props_element_children_every = _props_element_children.every) === null || _props_element_children_every === void 0 ? void 0 : _props_element_children_every.call(_props_element_children, function(child) {
129
147
  return !child.type && !child.code && !child.tag;
130
148
  });
131
- var hasNestedElement = props.element.children.some(function(child) {
132
- return Element.isElement(child);
133
- });
134
- // 组合输入进行中时,Slate 模型尚未更新(字符还在 IME 候选区),
135
- // 此时强制视为非空以隐藏占位符,避免用户输入时占位符仍然可见。
136
- var isEmpty = !str && ((_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length) === 1 && hasOnlyTextNodes ? true : undefined;
149
+ var isEmpty = !str && !isComposing && ((_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length) === 1 && hasOnlyTextNodes ? true : undefined;
137
150
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, props.attributes), {
138
151
  "data-be": 'paragraph',
139
152
  "data-drag-el": true,
@@ -147,16 +160,14 @@ export var Paragraph = function Paragraph(props) {
147
160
  },
148
161
  "data-empty": isEmpty,
149
162
  style: {
150
- display: str || hasNestedElement ? undefined : 'none',
151
163
  textAlign: align
152
164
  }
153
- }), props.children);
165
+ }), /*#__PURE__*/ React.createElement(DragHandle, null), props.children);
154
166
  }, [
155
- props.element,
156
167
  props.element.children,
157
168
  align,
158
- readonly,
159
169
  selected,
170
+ isComposing,
160
171
  (_markdownEditorRef_current = markdownEditorRef.current) === null || _markdownEditorRef_current === void 0 ? void 0 : _markdownEditorRef_current.children.length,
161
172
  editorProps.titlePlaceholderContent
162
173
  ]);
@@ -323,6 +323,17 @@ var repairBrokenChildArrays = function repairBrokenChildArrays(editor) {
323
323
  normalizeNode(entry);
324
324
  return;
325
325
  }
326
+ // 清空后 Slate 规范化可能再插一个空段,根上出现多个仅空文本的 paragraph;
327
+ // 与 replaceEditorContent 已插入的一块叠成双 DOM(见 debug H6)。
328
+ var validTop = childList.filter(isValidChild);
329
+ if (validTop.length > 1) {
330
+ var collapsed = EditorUtils.coalesceRootAllEmptyParagraphs(validTop);
331
+ if (collapsed.length < validTop.length) {
332
+ EditorUtils.replaceEditorContent(editor, collapsed);
333
+ normalizeNode(entry);
334
+ return;
335
+ }
336
+ }
326
337
  normalizeNode(entry);
327
338
  return;
328
339
  }
@@ -670,9 +670,6 @@ export declare class EditorStore {
670
670
  end: number;
671
671
  };
672
672
  lineContent: string;
673
- /**
674
- * 更新结构不同的表格
675
- */
676
673
  nodeType?: string | undefined;
677
674
  searchVariant?: string | undefined;
678
675
  isLink?: boolean | undefined;
@@ -11,6 +11,12 @@ export declare class EditorUtils {
11
11
  readonly text: "";
12
12
  }];
13
13
  };
14
+ /**
15
+ * 当根节点全部为「仅空白」的段落时,合并为单个空段。
16
+ * 避免解析 `\\n\\n` 或外部 schema 产生多个空段,导致 Slate/占位与双 DOM。
17
+ * 仅一个根块时原样返回,以保留单空段上的 align 等段落级字段。
18
+ */
19
+ static coalesceRootAllEmptyParagraphs(nodes: Node[]): Node[];
14
20
  /**
15
21
  * 通过 Slate Transforms API 安全替换编辑器全部内容。
16
22
  * 避免直接赋值 editor.children,确保 Operation/History/Normalizer 管线正常运行。
@@ -157,6 +157,32 @@ export var EditorUtils = /*#__PURE__*/ function() {
157
157
  };
158
158
  }
159
159
  },
160
+ {
161
+ key: "coalesceRootAllEmptyParagraphs",
162
+ value: /**
163
+ * 当根节点全部为「仅空白」的段落时,合并为单个空段。
164
+ * 避免解析 `\\n\\n` 或外部 schema 产生多个空段,导致 Slate/占位与双 DOM。
165
+ * 仅一个根块时原样返回,以保留单空段上的 align 等段落级字段。
166
+ */ function coalesceRootAllEmptyParagraphs(nodes) {
167
+ if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length)) {
168
+ return [
169
+ JSON.parse(JSON.stringify(EditorUtils.p))
170
+ ];
171
+ }
172
+ if (nodes.length === 1) {
173
+ return nodes;
174
+ }
175
+ var onlyEmptyParagraphs = nodes.every(function(n) {
176
+ return Element.isElement(n) && n.type === 'paragraph' && Node.string(n).trim() === '';
177
+ });
178
+ if (onlyEmptyParagraphs) {
179
+ return [
180
+ JSON.parse(JSON.stringify(EditorUtils.p))
181
+ ];
182
+ }
183
+ return nodes;
184
+ }
185
+ },
160
186
  {
161
187
  key: "replaceEditorContent",
162
188
  value: /**
@@ -169,6 +195,7 @@ export var EditorUtils = /*#__PURE__*/ function() {
169
195
  */ function replaceEditorContent(editor, nodes, options) {
170
196
  var _ref = options || {}, _ref_withoutHistory = _ref.withoutHistory, withoutHistory = _ref_withoutHistory === void 0 ? true : _ref_withoutHistory;
171
197
  var doReplace = function doReplace() {
198
+ var normalized = EditorUtils.coalesceRootAllEmptyParagraphs(nodes);
172
199
  Editor.withoutNormalizing(editor, function() {
173
200
  if (editor.selection) {
174
201
  Transforms.deselect(editor);
@@ -181,7 +208,7 @@ export var EditorUtils = /*#__PURE__*/ function() {
181
208
  ]
182
209
  });
183
210
  }
184
- Transforms.insertNodes(editor, nodes, {
211
+ Transforms.insertNodes(editor, normalized, {
185
212
  at: [
186
213
  0
187
214
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.30.26",
3
+ "version": "2.30.27",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",
@@ -25,7 +25,6 @@
25
25
  "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
26
26
  "playwright:install": "playwright install --with-deps chromium",
27
27
  "prepare": "husky install && dumi setup",
28
- "prepublishOnly": "npm run build",
29
28
  "prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
30
29
  "preview": "pnpm dumi preview",
31
30
  "report:demo": "node scripts/generateDemoReport.js",