@ant-design/agentic-ui 2.30.33 → 2.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/Components/Loading/style.js +16 -5
  2. package/dist/Components/Robot/lotties/BlowingWindLottie/index.js +16 -3
  3. package/dist/Components/Robot/lotties/BouncingLottie/index.js +16 -3
  4. package/dist/Components/Robot/lotties/DazingLottie/index.js +16 -3
  5. package/dist/Components/Robot/lotties/PeekLottie/index.js +16 -3
  6. package/dist/Components/Robot/lotties/ThinkingLottie/index.js +16 -3
  7. package/dist/Components/lotties/CreativeSparkLottie/index.js +16 -3
  8. package/dist/Components/lotties/DazingLottie/index.js +16 -3
  9. package/dist/Components/lotties/LoadingLottie/index.js +16 -3
  10. package/dist/Components/lotties/ThinkingLottie/index.js +16 -3
  11. package/dist/Components/lotties/ThreeThinkingLottie/index.js +7 -55
  12. package/dist/Components/lotties/bubble-actions/Copy/index.js +12 -3
  13. package/dist/Components/lotties/bubble-actions/Dislike/index.js +12 -3
  14. package/dist/Components/lotties/bubble-actions/Like/index.js +12 -3
  15. package/dist/Components/lotties/bubble-actions/More/index.js +12 -3
  16. package/dist/Components/lotties/bubble-actions/Play/index.js +12 -3
  17. package/dist/Components/lotties/bubble-actions/Quote/index.js +12 -3
  18. package/dist/Components/lotties/bubble-actions/Refresh/index.js +12 -3
  19. package/dist/Components/lotties/bubble-actions/Share/index.js +12 -3
  20. package/dist/Components/lotties/index.d.ts +1 -0
  21. package/dist/Components/lotties/index.js +1 -0
  22. package/dist/Components/lotties/useAsyncLottieData.d.ts +9 -0
  23. package/dist/Components/lotties/useAsyncLottieData.js +83 -0
  24. package/dist/Hooks/useLanguage.d.ts +1 -0
  25. package/dist/I18n/locales.d.ts +1 -0
  26. package/dist/I18n/locales.js +2 -0
  27. package/dist/Icons/animated/VoicePlayLottie/index.js +16 -3
  28. package/dist/Icons/animated/VoicingLottie/index.js +16 -3
  29. package/dist/MarkdownEditor/editor/elements/Paragraph/index.js +10 -10
  30. package/dist/MarkdownEditor/style.js +7 -1
  31. package/dist/MarkdownInputField/BorderBeamAnimation.d.ts +1 -1
  32. package/dist/MarkdownInputField/BorderBeamAnimation.js +6 -3
  33. package/dist/Plugins/chart/AreaChart/index.js +10 -8
  34. package/dist/Plugins/chart/BarChart/index.js +10 -8
  35. package/dist/Plugins/chart/BoxPlotChart/index.d.ts +1 -1
  36. package/dist/Plugins/chart/BoxPlotChart/index.js +11 -8
  37. package/dist/Plugins/chart/DonutChart/index.js +14 -12
  38. package/dist/Plugins/chart/FunnelChart/index.js +10 -8
  39. package/dist/Plugins/chart/HistogramChart/index.d.ts +1 -1
  40. package/dist/Plugins/chart/HistogramChart/index.js +11 -8
  41. package/dist/Plugins/chart/LineChart/index.js +10 -8
  42. package/dist/Plugins/chart/RadarChart/index.js +14 -12
  43. package/dist/Plugins/chart/ScatterChart/index.js +14 -12
  44. package/dist/Plugins/chart/components/ChartContainer/ChartContainer.js +4 -2
  45. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
  46. package/dist/Plugins/chart/components/ChartToolBar/style.js +2 -2
  47. package/dist/Plugins/chart/hooks/useChartTheme.d.ts +1 -1
  48. package/dist/Plugins/chart/hooks/useChartTheme.js +1 -1
  49. package/dist/Plugins/chart/hooks/useDetectTheme.d.ts +7 -8
  50. package/dist/Plugins/chart/hooks/useDetectTheme.js +81 -54
  51. package/dist/ThoughtChainList/style.js +14 -3
  52. package/dist/Workspace/File/FileComponent.js +15 -9
  53. package/dist/Workspace/File/FileTree/FileTreeComponent.js +6 -1
  54. package/dist/Workspace/File/PreviewComponent.js +23 -6
  55. package/package.json +4 -4
@@ -156,12 +156,12 @@ import { Scatter } from "react-chartjs-2";
156
156
  import ChartStatistic from "../ChartStatistic";
157
157
  import { ChartContainer, ChartFilter, ChartToolBar, downloadChart } from "../components";
158
158
  import { defaultColorList } from "../const";
159
- import { useChartTheme } from "../hooks";
159
+ import { useChartTheme, useDetectTheme } from "../hooks";
160
160
  import { hexToRgba, resolveCssVariable } from "../utils";
161
161
  import { useStyle } from "./style";
162
162
  var scatterChartComponentsRegistered = false;
163
163
  var ScatterChart = function ScatterChart(_0) {
164
- var data = _0.data, _0_width = _0.width, width = _0_width === void 0 ? 600 : _0_width, _0_height = _0.height, height = _0_height === void 0 ? 400 : _0_height, className = _0.className, classNamesProp = _0.classNames, title = _0.title, toolbarExtra = _0.toolbarExtra, _0_renderFilterInToolbar = _0.renderFilterInToolbar, renderFilterInToolbar = _0_renderFilterInToolbar === void 0 ? false : _0_renderFilterInToolbar, dataTime = _0.dataTime, _0_xUnit = _0.xUnit, xUnit = _0_xUnit === void 0 ? '月' : _0_xUnit, yUnit = _0.yUnit, xAxisLabel = _0.xAxisLabel, yAxisLabel = _0.yAxisLabel, _0_xPosition = _0.xPosition, xPosition = _0_xPosition === void 0 ? 'bottom' : _0_xPosition, _0_yPosition = _0.yPosition, yPosition = _0_yPosition === void 0 ? 'left' : _0_yPosition, _0_hiddenX = _0.hiddenX, hiddenX = _0_hiddenX === void 0 ? false : _0_hiddenX, _0_hiddenY = _0.hiddenY, hiddenY = _0_hiddenY === void 0 ? false : _0_hiddenY, _0_showGrid = _0.showGrid, showGrid = _0_showGrid === void 0 ? true : _0_showGrid, _0_theme = _0.theme, theme = _0_theme === void 0 ? 'light' : _0_theme, color = _0.color, statisticConfig = _0.statistic, _0_textMaxWidth = _0.textMaxWidth, textMaxWidth = _0_textMaxWidth === void 0 ? 80 : _0_textMaxWidth, _0_loading = _0.loading, loading = _0_loading === void 0 ? false : _0_loading, xMinProp = _0.xMin, xMaxProp = _0.xMax, yMinProp = _0.yMin, yMaxProp = _0.yMax, props = _object_without_properties(_0, [
164
+ var data = _0.data, _0_width = _0.width, width = _0_width === void 0 ? 600 : _0_width, _0_height = _0.height, height = _0_height === void 0 ? 400 : _0_height, className = _0.className, classNamesProp = _0.classNames, title = _0.title, toolbarExtra = _0.toolbarExtra, _0_renderFilterInToolbar = _0.renderFilterInToolbar, renderFilterInToolbar = _0_renderFilterInToolbar === void 0 ? false : _0_renderFilterInToolbar, dataTime = _0.dataTime, _0_xUnit = _0.xUnit, xUnit = _0_xUnit === void 0 ? '月' : _0_xUnit, yUnit = _0.yUnit, xAxisLabel = _0.xAxisLabel, yAxisLabel = _0.yAxisLabel, _0_xPosition = _0.xPosition, xPosition = _0_xPosition === void 0 ? 'bottom' : _0_xPosition, _0_yPosition = _0.yPosition, yPosition = _0_yPosition === void 0 ? 'left' : _0_yPosition, _0_hiddenX = _0.hiddenX, hiddenX = _0_hiddenX === void 0 ? false : _0_hiddenX, _0_hiddenY = _0.hiddenY, hiddenY = _0_hiddenY === void 0 ? false : _0_hiddenY, _0_showGrid = _0.showGrid, showGrid = _0_showGrid === void 0 ? true : _0_showGrid, theme = _0.theme, color = _0.color, statisticConfig = _0.statistic, _0_textMaxWidth = _0.textMaxWidth, textMaxWidth = _0_textMaxWidth === void 0 ? 80 : _0_textMaxWidth, _0_loading = _0.loading, loading = _0_loading === void 0 ? false : _0_loading, xMinProp = _0.xMin, xMaxProp = _0.xMax, yMinProp = _0.yMin, yMaxProp = _0.yMax, props = _object_without_properties(_0, [
165
165
  "data",
166
166
  "width",
167
167
  "height",
@@ -205,7 +205,9 @@ var ScatterChart = function ScatterChart(_0) {
205
205
  var prefixCls = getPrefixCls('scatter-chart');
206
206
  var _useStyle = useStyle(prefixCls), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
207
207
  // 主题颜色 - 必须在所有条件返回之前调用
208
- var _useChartTheme = useChartTheme(theme), axisTextColor = _useChartTheme.axisTextColor, gridColor = _useChartTheme.gridColor, isLight = _useChartTheme.isLight;
208
+ var detectedTheme = useDetectTheme();
209
+ var resolvedTheme = theme !== null && theme !== void 0 ? theme : detectedTheme;
210
+ var _useChartTheme = useChartTheme(resolvedTheme), axisTextColor = _useChartTheme.axisTextColor, gridColor = _useChartTheme.gridColor, isLight = _useChartTheme.isLight;
209
211
  // 处理 ChartStatistic 组件配置
210
212
  var statistics = useMemo(function() {
211
213
  if (!statisticConfig) return null;
@@ -293,7 +295,7 @@ var ScatterChart = function ScatterChart(_0) {
293
295
  var _props_styles;
294
296
  return wrapSSR(/*#__PURE__*/ React.createElement(ChartContainer, {
295
297
  baseClassName: classNames("".concat(prefixCls, "-container")),
296
- theme: theme,
298
+ theme: resolvedTheme,
297
299
  className: classNames(classNamesObj === null || classNamesObj === void 0 ? void 0 : classNamesObj.root, hashId, className),
298
300
  isMobile: isMobile,
299
301
  variant: props.variant,
@@ -303,7 +305,7 @@ var ScatterChart = function ScatterChart(_0) {
303
305
  }, props.style, (_props_styles = props.styles) === null || _props_styles === void 0 ? void 0 : _props_styles.root)
304
306
  }, /*#__PURE__*/ React.createElement(ChartToolBar, {
305
307
  title: title || '散点图',
306
- theme: theme,
308
+ theme: resolvedTheme,
307
309
  onDownload: function onDownload() {},
308
310
  extra: toolbarExtra,
309
311
  dataTime: dataTime,
@@ -693,7 +695,7 @@ var ScatterChart = function ScatterChart(_0) {
693
695
  var _props_styles1, _props_styles2, _props_styles3;
694
696
  return wrapSSR(/*#__PURE__*/ React.createElement(ChartContainer, {
695
697
  baseClassName: classNames("".concat(prefixCls, "-container")),
696
- theme: theme,
698
+ theme: resolvedTheme,
697
699
  className: classNames(classNamesObj === null || classNamesObj === void 0 ? void 0 : classNamesObj.root, hashId, className),
698
700
  isMobile: isMobile,
699
701
  variant: props.variant,
@@ -703,7 +705,7 @@ var ScatterChart = function ScatterChart(_0) {
703
705
  }, props.style, (_props_styles1 = props.styles) === null || _props_styles1 === void 0 ? void 0 : _props_styles1.root)
704
706
  }, /*#__PURE__*/ React.createElement(ChartToolBar, {
705
707
  title: title || '散点图',
706
- theme: theme,
708
+ theme: resolvedTheme,
707
709
  onDownload: handleDownload,
708
710
  extra: toolbarExtra,
709
711
  dataTime: dataTime,
@@ -717,7 +719,7 @@ var ScatterChart = function ScatterChart(_0) {
717
719
  selectedCustomSelection: selectedFilterLabel,
718
720
  onSelectionChange: setSelectedFilterLabel
719
721
  }), {
720
- theme: theme,
722
+ theme: resolvedTheme,
721
723
  variant: "compact"
722
724
  })) : undefined
723
725
  }), !renderFilterInToolbar && filterEnum.length > 0 && /*#__PURE__*/ React.createElement(ChartFilter, _object_spread_props(_object_spread({
@@ -729,7 +731,7 @@ var ScatterChart = function ScatterChart(_0) {
729
731
  selectedCustomSelection: selectedFilterLabel,
730
732
  onSelectionChange: setSelectedFilterLabel
731
733
  }), {
732
- theme: theme
734
+ theme: resolvedTheme
733
735
  })), statistics && /*#__PURE__*/ React.createElement("div", {
734
736
  className: classNames(classNamesObj === null || classNamesObj === void 0 ? void 0 : classNamesObj.statisticContainer, "".concat(prefixCls, "-statistic-container")),
735
737
  style: (_props_styles2 = props.styles) === null || _props_styles2 === void 0 ? void 0 : _props_styles2.statisticContainer
@@ -737,7 +739,7 @@ var ScatterChart = function ScatterChart(_0) {
737
739
  return /*#__PURE__*/ React.createElement(ChartStatistic, _object_spread_props(_object_spread({
738
740
  key: index
739
741
  }, config), {
740
- theme: theme
742
+ theme: resolvedTheme
741
743
  }));
742
744
  })), /*#__PURE__*/ React.createElement("div", {
743
745
  className: classNames(classNamesObj === null || classNamesObj === void 0 ? void 0 : classNamesObj.wrapper, "".concat(prefixCls, "-chart-wrapper")),
@@ -754,7 +756,7 @@ var ScatterChart = function ScatterChart(_0) {
754
756
  console.error('ScatterChart 渲染错误:', error);
755
757
  return wrapSSR(/*#__PURE__*/ React.createElement(ChartContainer, {
756
758
  baseClassName: classNames("".concat(prefixCls, "-container")),
757
- theme: theme,
759
+ theme: resolvedTheme,
758
760
  isMobile: isMobile,
759
761
  className: classNames(hashId, className),
760
762
  variant: props.variant,
@@ -764,7 +766,7 @@ var ScatterChart = function ScatterChart(_0) {
764
766
  }, props.style, (_props_styles4 = props.styles) === null || _props_styles4 === void 0 ? void 0 : _props_styles4.root)
765
767
  }, /*#__PURE__*/ React.createElement(ChartToolBar, {
766
768
  title: title || '散点图',
767
- theme: theme,
769
+ theme: resolvedTheme,
768
770
  onDownload: function onDownload() {},
769
771
  extra: toolbarExtra,
770
772
  dataTime: dataTime,
@@ -165,10 +165,12 @@ import { useStyle } from "./style";
165
165
  var _useStyle = useStyle(baseClassName), wrapSSR = _useStyle.wrapSSR, hashId = _useStyle.hashId;
166
166
  var ancestorDarkAntdProvided = useChartDarkAntdProvided();
167
167
  // 自动检测主题:当 themeProp 未指定且 autoDetectTheme 为 true 时,自动检测
168
+ // 当 themeProp 已明确传入时,跳过监听以避免创建多余的 MutationObserver
169
+ var needDetect = autoDetectTheme && !themeProp;
168
170
  var detectedTheme = useDetectTheme({
169
- observeChanges: autoDetectTheme
171
+ observeChanges: needDetect
170
172
  });
171
- var theme = themeProp !== null && themeProp !== void 0 ? themeProp : autoDetectTheme ? detectedTheme : 'light';
173
+ var theme = themeProp !== null && themeProp !== void 0 ? themeProp : needDetect ? detectedTheme : 'light';
172
174
  var wrapDarkAntd = theme === 'dark' && !ancestorDarkAntdProvided;
173
175
  // 构建动态类名
174
176
  var combinedClassName = classNames(baseClassName, hashId, theme === 'light' && "".concat(baseClassName, "-light-theme"), theme === 'dark' && "".concat(baseClassName, "-dark-theme"), isMobile && "".concat(baseClassName, "-mobile"), !isMobile && "".concat(baseClassName, "-desktop"), variant === 'outline' && "".concat(baseClassName, "-outline"), variant === 'borderless' && "".concat(baseClassName, "-borderless"), className, classNamesProp === null || classNamesProp === void 0 ? void 0 : classNamesProp.root);
@@ -462,6 +462,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
462
462
  'fileType.config': string;
463
463
  'fileType.powerpoint': string;
464
464
  'workspace.file.unsupportedPreview': string;
465
+ 'workspace.file.unsupportedPreviewNoDownload': string;
465
466
  'workspace.file.downloadButton': string;
466
467
  'workspace.file.videoNotSupported': string;
467
468
  'workspace.file.audioNotSupported': string;
@@ -888,6 +889,7 @@ declare class ChartErrorBoundary extends React.Component<ChartErrorBoundaryProps
888
889
  'fileType.config': string;
889
890
  'fileType.powerpoint': string;
890
891
  'workspace.file.unsupportedPreview': string;
892
+ 'workspace.file.unsupportedPreviewNoDownload': string;
891
893
  'workspace.file.downloadButton': string;
892
894
  'workspace.file.videoNotSupported': string;
893
895
  'workspace.file.audioNotSupported': string;
@@ -91,7 +91,7 @@ var genStyle = function genStyle(token) {
91
91
  fontVariationSettings: '"opsz" auto',
92
92
  /* gray/gray-文本-浅色注释 */ /* 样式描述:--gray-a9 */ color: 'rgba(0, 25, 61, 0.3255)',
93
93
  marginRight: '8px'
94
- }), _define_property(_obj, "".concat(token.componentCls, "-download-btn"), {
94
+ }), _define_property(_obj, "".concat(token.componentCls, "-download-btn, ").concat(token.componentCls, "-copy-btn"), {
95
95
  color: 'rgba(0, 25, 61, 0.3255)',
96
96
  padding: '3px',
97
97
  height: 'auto',
@@ -117,7 +117,7 @@ var genStyle = function genStyle(token) {
117
117
  color: '#fff'
118
118
  }), _define_property(_obj1, "".concat(token.componentCls, "-data-time"), {
119
119
  color: 'rgba(255, 255, 255, 0.65)'
120
- }), _define_property(_obj1, "".concat(token.componentCls, "-download-btn"), {
120
+ }), _define_property(_obj1, "".concat(token.componentCls, "-download-btn, ").concat(token.componentCls, "-copy-btn"), {
121
121
  color: 'rgba(255, 255, 255, 0.65)',
122
122
  backgroundColor: 'transparent',
123
123
  '&:hover': {
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * @since 1.0.0
15
15
  */
16
- export declare const useChartTheme: (theme?: 'light' | 'dark') => {
16
+ export declare const useChartTheme: (theme?: 'light' | 'dark' | undefined) => {
17
17
  isLight: boolean;
18
18
  axisTextColor: string;
19
19
  gridColor: string;
@@ -16,7 +16,7 @@ import { useMemo } from "react";
16
16
  */ export var useChartTheme = function useChartTheme() {
17
17
  var theme = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 'light';
18
18
  return useMemo(function() {
19
- var isLight = theme === 'light';
19
+ var isLight = (theme !== null && theme !== void 0 ? theme : 'light') === 'light';
20
20
  var axisTextColor = isLight ? 'rgba(0, 25, 61, 0.3255)' : 'rgba(255, 255, 255, 0.8)';
21
21
  var gridColor = isLight ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.2)';
22
22
  return {
@@ -19,14 +19,17 @@ export interface DetectThemeOptions {
19
19
  observeChanges?: boolean;
20
20
  }
21
21
  /**
22
- * 自动检测当前主题的 Hook
22
+ * 自动检测当前主题的 Hook(单例模式)
23
+ *
24
+ * 所有 hook 实例共享同一个 MutationObserver 和 matchMedia 监听器,
25
+ * 避免页面上多个图表时创建重复的 DOM 监听。
23
26
  *
24
27
  * 检测策略(按优先级):
25
28
  * 1. 检查 `html[data-theme='dark']` 属性
26
29
  * 2. 检查指定 CSS 变量的亮度值
27
30
  * 3. 检查 `--color-gray-bg-page` 的亮度值
28
31
  *
29
- * @param options 检测配置选项
32
+ * @param options 检测配置选项(observeChanges 为 false 时跳过监听)
30
33
  * @returns 检测到的主题 'light' | 'dark'
31
34
  *
32
35
  * @example
@@ -34,12 +37,8 @@ export interface DetectThemeOptions {
34
37
  * const theme = useDetectTheme();
35
38
  * // theme: 'light' | 'dark'
36
39
  *
37
- * // 自定义配置
38
- * const theme = useDetectTheme({
39
- * cssVariable: '--color-primary-bg-page',
40
- * darknessThreshold: 128,
41
- * observeChanges: true,
42
- * });
40
+ * // 禁用监听(仅检测一次)
41
+ * const theme = useDetectTheme({ observeChanges: false });
43
42
  * ```
44
43
  */
45
44
  export declare const useDetectTheme: (options?: DetectThemeOptions) => 'light' | 'dark';
@@ -44,7 +44,7 @@ function _unsupported_iterable_to_array(o, minLen) {
44
44
  if (n === "Map" || n === "Set") return Array.from(n);
45
45
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
46
  }
47
- import { useEffect, useState } from "react";
47
+ import { useSyncExternalStore } from "react";
48
48
  /**
49
49
  * 解析颜色值为 RGB
50
50
  */ var parseColorToRgb = function parseColorToRgb(color) {
@@ -131,43 +131,31 @@ import { useEffect, useState } from "react";
131
131
  }
132
132
  return 'light';
133
133
  };
134
- /**
135
- * 自动检测当前主题的 Hook
136
- *
137
- * 检测策略(按优先级):
138
- * 1. 检查 `html[data-theme='dark']` 属性
139
- * 2. 检查指定 CSS 变量的亮度值
140
- * 3. 检查 `--color-gray-bg-page` 的亮度值
141
- *
142
- * @param options 检测配置选项
143
- * @returns 检测到的主题 'light' | 'dark'
144
- *
145
- * @example
146
- * ```tsx
147
- * const theme = useDetectTheme();
148
- * // theme: 'light' | 'dark'
149
- *
150
- * // 自定义配置
151
- * const theme = useDetectTheme({
152
- * cssVariable: '--color-primary-bg-page',
153
- * darknessThreshold: 128,
154
- * observeChanges: true,
155
- * });
156
- * ```
157
- */ export var useDetectTheme = function useDetectTheme() {
158
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
159
- var _options_cssVariable = options.cssVariable, cssVariable = _options_cssVariable === void 0 ? '--color-gray-bg-page' : _options_cssVariable, _options_darknessThreshold = options.darknessThreshold, darknessThreshold = _options_darknessThreshold === void 0 ? 145 : _options_darknessThreshold, _options_observeChanges = options.observeChanges, observeChanges = _options_observeChanges === void 0 ? true : _options_observeChanges;
160
- var _useState = _sliced_to_array(useState(function() {
161
- return detectTheme(cssVariable, darknessThreshold);
162
- }), 2), theme = _useState[0], setTheme = _useState[1];
163
- useEffect(function() {
164
- if (!observeChanges) return;
134
+ // --- 单例主题检测:所有 hook 实例共享一个 MutationObserver + matchMedia 监听 ---
135
+ var listeners = [];
136
+ var currentTheme = 'light';
137
+ var observerRef = null;
138
+ var mediaQueryRef = null;
139
+ var refCount = 0;
140
+ var DEFAULT_CSS_VARIABLE = '--color-gray-bg-page';
141
+ var DEFAULT_DARKNESS_THRESHOLD = 145;
142
+ function subscribeTheme(listener) {
143
+ listeners.push(listener);
144
+ refCount++;
145
+ // 第一个订阅者时初始化全局监听器
146
+ if (refCount === 1 && typeof window !== 'undefined') {
147
+ currentTheme = detectTheme(DEFAULT_CSS_VARIABLE, DEFAULT_DARKNESS_THRESHOLD);
165
148
  var updateTheme = function updateTheme() {
166
- setTheme(detectTheme(cssVariable, darknessThreshold));
149
+ var next = detectTheme(DEFAULT_CSS_VARIABLE, DEFAULT_DARKNESS_THRESHOLD);
150
+ if (next !== currentTheme) {
151
+ currentTheme = next;
152
+ listeners.forEach(function(fn) {
153
+ return fn();
154
+ });
155
+ }
167
156
  };
168
- // 监听 data-theme 属性变化
169
157
  var htmlElement = document.documentElement;
170
- var observer = new MutationObserver(function(mutations) {
158
+ observerRef = new MutationObserver(function(mutations) {
171
159
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
172
160
  try {
173
161
  for(var _iterator = mutations[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -192,7 +180,7 @@ import { useEffect, useState } from "react";
192
180
  }
193
181
  }
194
182
  });
195
- observer.observe(htmlElement, {
183
+ observerRef.observe(htmlElement, {
196
184
  attributes: true,
197
185
  attributeFilter: [
198
186
  'data-theme',
@@ -200,23 +188,62 @@ import { useEffect, useState } from "react";
200
188
  'style'
201
189
  ]
202
190
  });
203
- // 监听 prefers-color-scheme 变化
204
- var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
205
- var handleMediaChange = function handleMediaChange() {
206
- updateTheme();
207
- };
208
- mediaQuery.addEventListener('change', handleMediaChange);
209
- // 初始检测
210
- updateTheme();
211
- return function() {
212
- observer.disconnect();
213
- mediaQuery.removeEventListener('change', handleMediaChange);
214
- };
215
- }, [
216
- cssVariable,
217
- darknessThreshold,
218
- observeChanges
219
- ]);
220
- return theme;
191
+ mediaQueryRef = window.matchMedia('(prefers-color-scheme: dark)');
192
+ mediaQueryRef.addEventListener('change', updateTheme);
193
+ }
194
+ return function() {
195
+ listeners = listeners.filter(function(fn) {
196
+ return fn !== listener;
197
+ });
198
+ refCount--;
199
+ // 最后一个订阅者取消时清理全局监听器
200
+ if (refCount === 0) {
201
+ observerRef === null || observerRef === void 0 ? void 0 : observerRef.disconnect();
202
+ observerRef = null;
203
+ if (mediaQueryRef) {
204
+ mediaQueryRef.removeEventListener('change', function() {});
205
+ mediaQueryRef = null;
206
+ }
207
+ }
208
+ };
209
+ }
210
+ function getSnapshot() {
211
+ return currentTheme;
212
+ }
213
+ function getServerSnapshot() {
214
+ return 'light';
215
+ }
216
+ /**
217
+ * 自动检测当前主题的 Hook(单例模式)
218
+ *
219
+ * 所有 hook 实例共享同一个 MutationObserver 和 matchMedia 监听器,
220
+ * 避免页面上多个图表时创建重复的 DOM 监听。
221
+ *
222
+ * 检测策略(按优先级):
223
+ * 1. 检查 `html[data-theme='dark']` 属性
224
+ * 2. 检查指定 CSS 变量的亮度值
225
+ * 3. 检查 `--color-gray-bg-page` 的亮度值
226
+ *
227
+ * @param options 检测配置选项(observeChanges 为 false 时跳过监听)
228
+ * @returns 检测到的主题 'light' | 'dark'
229
+ *
230
+ * @example
231
+ * ```tsx
232
+ * const theme = useDetectTheme();
233
+ * // theme: 'light' | 'dark'
234
+ *
235
+ * // 禁用监听(仅检测一次)
236
+ * const theme = useDetectTheme({ observeChanges: false });
237
+ * ```
238
+ */ export var useDetectTheme = function useDetectTheme() {
239
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
240
+ var _options_observeChanges = options.observeChanges, observeChanges = _options_observeChanges === void 0 ? true : _options_observeChanges;
241
+ // 当 observeChanges 为 false 时,只做一次性检测,不订阅变更
242
+ var liveTheme = useSyncExternalStore(subscribeTheme, getSnapshot, getServerSnapshot);
243
+ if (!observeChanges) {
244
+ var _options_cssVariable, _options_darknessThreshold;
245
+ return detectTheme((_options_cssVariable = options.cssVariable) !== null && _options_cssVariable !== void 0 ? _options_cssVariable : DEFAULT_CSS_VARIABLE, (_options_darknessThreshold = options.darknessThreshold) !== null && _options_darknessThreshold !== void 0 ? _options_darknessThreshold : DEFAULT_DARKNESS_THRESHOLD);
246
+ }
247
+ return liveTheme;
221
248
  };
222
249
  export default useDetectTheme;
@@ -52,7 +52,16 @@ function _object_spread_props(target, source) {
52
52
  }
53
53
  import { resetComponent, useEditorStyleRegister } from "../Hooks/useStyle";
54
54
  var genStyle = function genStyle(token) {
55
- return _define_property({}, token.componentCls, {
55
+ return _define_property({
56
+ '@keyframes thoughtChainSpin': {
57
+ '0%': {
58
+ transform: 'rotate(0deg)'
59
+ },
60
+ '100%': {
61
+ transform: 'rotate(360deg)'
62
+ }
63
+ }
64
+ }, token.componentCls, {
56
65
  padding: '12px',
57
66
  '*': {
58
67
  boxSizing: 'border-box'
@@ -87,8 +96,10 @@ var genStyle = function genStyle(token) {
87
96
  zIndex: 1,
88
97
  backgroundSize: '150%',
89
98
  backgroundPosition: '0 0',
90
- backgroundImage: "conic-gradient(\n from var(--angle, 0deg) at 50% 50%,\n rgba(46, 255, 127, 0.7) 0deg,\n rgba(120, 133, 255, 1) 90deg,\n rgba(255, 0, 153, 0.4) 180deg,\n rgba(0, 221, 255, 0.62) 270deg,\n rgba(46, 255, 127, 0.7) 360deg\n )",
91
- animationName: 'spin',
99
+ backgroundImage: "conic-gradient(\n rgba(46, 255, 127, 0.7) 0deg,\n rgba(120, 133, 255, 1) 90deg,\n rgba(255, 0, 153, 0.4) 180deg,\n rgba(0, 221, 255, 0.62) 270deg,\n rgba(46, 255, 127, 0.7) 360deg\n )",
100
+ transformOrigin: 'center center',
101
+ willChange: 'transform',
102
+ animationName: 'thoughtChainSpin',
92
103
  animationDuration: '2s',
93
104
  animationTimingFunction: 'linear',
94
105
  animationIterationCount: 'infinite'
@@ -755,6 +755,7 @@ export var FileComponent = function FileComponent(param) {
755
755
  resetKey
756
756
  ]);
757
757
  // 监听 nodes 变化,同步更新 previewFile
758
+ // 当外部数据更新时,保持预览文件与最新数据同步
758
759
  useEffect(function() {
759
760
  if (!previewFile) return;
760
761
  // 在所有节点中查找与当前预览文件匹配的文件
@@ -768,7 +769,7 @@ export var FileComponent = function FileComponent(param) {
768
769
  var found = findUpdatedFile(node.children);
769
770
  if (found) return found;
770
771
  } else {
771
- // 文件节点,比较 ID 或文件引用
772
+ // 文件节点,比较 ID 或文件名+类型
772
773
  if (node.id && node.id === previewFile.id || node.name === previewFile.name && node.type === previewFile.type) {
773
774
  return node;
774
775
  }
@@ -795,8 +796,15 @@ export var FileComponent = function FileComponent(param) {
795
796
  if (updatedFile) {
796
797
  setPreviewFile(updatedFile);
797
798
  }
799
+ // 注意:这里故意使用 nodes 而非 safeNodes 作为依赖
800
+ // 因为 safeNodes 每次渲染都会重新计算,会导致无限循环
801
+ // nodes 引用变化时才需要检查更新
802
+ // eslint-disable-next-line react-hooks/exhaustive-deps
798
803
  }, [
799
- nodes
804
+ nodes,
805
+ previewFile === null || previewFile === void 0 ? void 0 : previewFile.id,
806
+ previewFile === null || previewFile === void 0 ? void 0 : previewFile.name,
807
+ previewFile === null || previewFile === void 0 ? void 0 : previewFile.type
800
808
  ]);
801
809
  // 处理分组折叠/展开
802
810
  var handleToggleGroup = useRefFunction(function(groupId, type, collapsed) {
@@ -1022,7 +1030,9 @@ export var FileComponent = function FileComponent(param) {
1022
1030
  if (hasKeyword) {
1023
1031
  return /*#__PURE__*/ React.createElement(Typography.Text, {
1024
1032
  type: "secondary"
1025
- }, ((locale === null || locale === void 0 ? void 0 : locale['workspace.noResultsFor']) || "未找到与「".concat(keyword, "」匹配的结果")).replace('${keyword}', String(keyword)));
1033
+ }, compileTemplate((locale === null || locale === void 0 ? void 0 : locale['workspace.noResultsFor']) || '未找到与「${keyword}」匹配的结果', {
1034
+ keyword: String(keyword)
1035
+ }));
1026
1036
  }
1027
1037
  if (typeof emptyRender === 'function') {
1028
1038
  return emptyRender();
@@ -1044,12 +1054,8 @@ export var FileComponent = function FileComponent(param) {
1044
1054
  });
1045
1055
  // 渲染文件内容
1046
1056
  var renderFileContent = useRefFunction(function() {
1047
- if ((!nodes || nodes.length === 0) && !loading) {
1048
- return /*#__PURE__*/ React.createElement("div", {
1049
- className: classNames("".concat(prefixCls, "-empty"), hashId)
1050
- }, renderEmptyContent());
1051
- }
1052
- if (safeNodes.length === 0) {
1057
+ // 统一的空状态判断:数据为空且非加载中
1058
+ if (safeNodes.length === 0 && !loading) {
1053
1059
  return /*#__PURE__*/ React.createElement("div", {
1054
1060
  className: classNames("".concat(prefixCls, "-empty"), hashId)
1055
1061
  }, renderEmptyContent());
@@ -214,9 +214,14 @@ var FileTreeComponent = function FileTreeComponent(param) {
214
214
  }
215
215
  // 须让 `Promise` 在失败时 reject,以便 rc-tree 不将 key 记为已加载,从而可再次展开重试
216
216
  return Promise.resolve(onLoadChildrenRef(source)).then(function(loaded) {
217
+ var children = loaded !== null && loaded !== void 0 ? loaded : [];
217
218
  setInnerTree(function(prev) {
218
- return replaceNodeChildren(prev, k, loaded);
219
+ return replaceNodeChildren(prev, k, children);
219
220
  });
221
+ }).catch(function(error) {
222
+ console.error('Failed to load tree children:', error);
223
+ // 返回 reject 以便 rc-tree 不将 key 记为已加载,允许重试
224
+ throw error;
220
225
  });
221
226
  }, [
222
227
  onLoadChildrenRef,
@@ -185,7 +185,15 @@ var PlaceholderContent = function PlaceholderContent(param) {
185
185
  if (customContent || !processResult) return;
186
186
  var typeInference = processResult.typeInference, dataSource = processResult.dataSource;
187
187
  var isTextOrCode = typeInference.category === 'text' || typeInference.category === 'code';
188
- if (!isTextOrCode) return;
188
+ // 非文本/代码类型时重置状态
189
+ if (!isTextOrCode) {
190
+ setContentState({
191
+ status: 'idle',
192
+ mdContent: '',
193
+ rawContent: ''
194
+ });
195
+ return;
196
+ }
189
197
  var setReadyContent = function setReadyContent(raw) {
190
198
  setContentState({
191
199
  status: 'ready',
@@ -216,11 +224,19 @@ var PlaceholderContent = function PlaceholderContent(param) {
216
224
  });
217
225
  console.error('加载文本内容失败:', err);
218
226
  });
227
+ } else {
228
+ // 无数据源时重置状态,避免显示旧内容
229
+ setContentState({
230
+ status: 'idle',
231
+ mdContent: '',
232
+ rawContent: ''
233
+ });
219
234
  }
220
235
  }, [
221
236
  processResult,
222
237
  file.name,
223
- customContent
238
+ customContent,
239
+ locale
224
240
  ]);
225
241
  useEffect(function() {
226
242
  var _editorRef_current;
@@ -249,14 +265,13 @@ var PlaceholderContent = function PlaceholderContent(param) {
249
265
  var isCurrentFileHtml = isHtmlFile(file.name, processResult === null || processResult === void 0 ? void 0 : processResult.dataSource.mimeType);
250
266
  var renderPreviewContent = function renderPreviewContent() {
251
267
  if (file.loading) {
252
- var _file_content;
253
268
  return /*#__PURE__*/ React.createElement("div", {
254
269
  className: classNames("".concat(prefixCls, "-content-loading"), hashId)
255
270
  }, /*#__PURE__*/ React.createElement("span", {
256
271
  className: classNames("".concat(prefixCls, "-content-loading-tip"), hashId)
257
272
  }, /*#__PURE__*/ React.createElement(LoadingOutlined, null), (locale === null || locale === void 0 ? void 0 : locale['workspace.file.generating']) || '正在生成'), /*#__PURE__*/ React.createElement("div", {
258
273
  className: classNames("".concat(prefixCls, "-content-loading-inner"), hashId)
259
- }, (file === null || file === void 0 ? void 0 : (_file_content = file.content) === null || _file_content === void 0 ? void 0 : _file_content.padEnd(10000, file === null || file === void 0 ? void 0 : file.content)) || '...'.padEnd(10000, '...')));
274
+ }, (file === null || file === void 0 ? void 0 : file.content) || '...'));
260
275
  }
261
276
  if (customContent) {
262
277
  return /*#__PURE__*/ React.createElement("div", {
@@ -331,7 +346,7 @@ var PlaceholderContent = function PlaceholderContent(param) {
331
346
  className: classNames("".concat(filePrefixCls, "-item-separator"), hashId)
332
347
  }, "|"), /*#__PURE__*/ React.createElement("span", {
333
348
  className: classNames("".concat(filePrefixCls, "-item-time"), hashId)
334
- }, formatLastModified(file.lastModified))))))), canDownload && onDownload && /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("div", {
349
+ }, formatLastModified(file.lastModified))))))), canDownload && onDownload ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement("div", {
335
350
  className: classNames("".concat(prefixCls, "-unsupported-text"), hashId)
336
351
  }, (locale === null || locale === void 0 ? void 0 : locale['workspace.file.unsupportedPreview']) || '此文件无法预览,请下载查看。'), /*#__PURE__*/ React.createElement(Button, {
337
352
  color: "default",
@@ -339,7 +354,9 @@ var PlaceholderContent = function PlaceholderContent(param) {
339
354
  icon: /*#__PURE__*/ React.createElement(DownloadIcon, null),
340
355
  onClick: handleDownload,
341
356
  "aria-label": (locale === null || locale === void 0 ? void 0 : locale['workspace.file.download']) || '下载'
342
- }, (locale === null || locale === void 0 ? void 0 : locale['workspace.file.downloadButton']) || '下载'))));
357
+ }, (locale === null || locale === void 0 ? void 0 : locale['workspace.file.downloadButton']) || '下载')) : /*#__PURE__*/ React.createElement("div", {
358
+ className: classNames("".concat(prefixCls, "-unsupported-text"), hashId)
359
+ }, (locale === null || locale === void 0 ? void 0 : locale['workspace.file.unsupportedPreviewNoDownload']) || '此文件无法预览。')));
343
360
  }
344
361
  var renderTextOrCode = function renderTextOrCode() {
345
362
  if (isCurrentFileHtml) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.30.33",
3
+ "version": "2.31.1",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",
@@ -25,19 +25,19 @@
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 && npm run test",
28
+ "prepublishOnly": "npm run build",
29
29
  "prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
30
30
  "preview": "pnpm dumi preview",
31
31
  "report:demo": "node scripts/generateDemoReport.js",
32
32
  "start": "pnpm run dev",
33
33
  "test": "vitest --run",
34
34
  "test:coverage": "vitest --run --coverage",
35
- "test:coverage:full": "cross-env VITEST_FULL_SUITE=1 vitest --run --coverage",
35
+ "test:coverage:full": "vitest --run --coverage --mode full",
36
36
  "test:e2e": "playwright test",
37
37
  "test:e2e:debug": "playwright test --debug",
38
38
  "test:e2e:skip-server": "cross-env SKIP_WEBSERVER=1 playwright test",
39
39
  "test:e2e:ui": "playwright test --ui",
40
- "test:full": "cross-env VITEST_FULL_SUITE=1 vitest --run",
40
+ "test:full": "vitest --run --mode full",
41
41
  "tsc": "tsc --noEmit"
42
42
  },
43
43
  "lint-staged": {