@ant-design/agentic-ui 2.7.0 → 2.8.0

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.
@@ -240,12 +240,20 @@ var genStyle = (token) => {
240
240
  "&:hover": {
241
241
  // 支持直接在元素上的属性
242
242
  "&[aria-describedby]": {
243
- animation: "scrollText 2s linear 0.5s forwards",
243
+ animationName: "scrollText",
244
+ animationDuration: "2s",
245
+ animationTimingFunction: "linear",
246
+ animationDelay: "0.5s",
247
+ animationFillMode: "forwards",
244
248
  animationPlayState: "running"
245
249
  },
246
250
  // 支持子元素上的属性
247
251
  "& > div[aria-describedby]": {
248
- animation: "scrollText 2s linear 0.5s forwards",
252
+ animationName: "scrollText",
253
+ animationDuration: "2s",
254
+ animationTimingFunction: "linear",
255
+ animationDelay: "0.5s",
256
+ animationFillMode: "forwards",
249
257
  animationPlayState: "running"
250
258
  },
251
259
  // 渐变遮罩层
@@ -19,6 +19,7 @@
19
19
  export declare const kbToSize: (kb: number) => string;
20
20
  /**
21
21
  * 检查文件是否为图片类型
22
+ * 通过 MIME 类型和文件扩展名双重判断
22
23
  *
23
24
  * @param {File} file - 要检查的文件
24
25
  * @returns {boolean} 是否为图片文件
@@ -12,7 +12,23 @@ var kbToSize = (kb) => {
12
12
  return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + " " + sizes[i];
13
13
  };
14
14
  var isImageFile = (file) => {
15
- return file.type.startsWith("image/");
15
+ if (file.type.startsWith("image/")) {
16
+ return true;
17
+ }
18
+ const imageExtensions = [
19
+ ".jpg",
20
+ ".jpeg",
21
+ ".png",
22
+ ".gif",
23
+ ".bmp",
24
+ ".webp",
25
+ ".svg",
26
+ ".ico",
27
+ ".tiff",
28
+ ".tif"
29
+ ];
30
+ const fileName = file.name.toLowerCase();
31
+ return imageExtensions.some((ext) => fileName.endsWith(ext));
16
32
  };
17
33
  export {
18
34
  isImageFile,
@@ -4,6 +4,7 @@ import React from 'react';
4
4
  *
5
5
  * 该组件用于渲染各种类型的图表,支持饼图、柱状图、折线图、面积图、表格等。
6
6
  * 提供图表类型切换、全屏显示、下载、配置等功能。
7
+ * 使用 React.lazy 和 Suspense 实现代码分割和延迟加载,优化性能。
7
8
  *
8
9
  * @component
9
10
  * @description 图表渲染组件,支持多种图表类型的渲染和交互
@@ -54,6 +55,7 @@ import React from 'react';
54
55
  * - 提供响应式布局
55
56
  * - 集成国际化支持
56
57
  * - 提供图表属性工具栏
58
+ * - 使用 React.lazy 和 Suspense 实现代码分割
57
59
  */
58
60
  export declare const ChartRender: React.FC<{
59
61
  chartType: 'pie' | 'donut' | 'bar' | 'line' | 'column' | 'area' | 'radar' | 'scatter' | 'funnel' | 'descriptions' | 'table';
@@ -1,4 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
2
4
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
4
6
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -14,12 +16,33 @@ var __spreadValues = (a, b) => {
14
16
  }
15
17
  return a;
16
18
  };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
17
40
 
18
41
  // src/Plugins/chart/ChartRender.tsx
19
42
  import { DownOutlined, SettingOutlined } from "@ant-design/icons";
20
43
  import { ProForm, ProFormSelect } from "@ant-design/pro-components";
21
44
  import { ConfigProvider, Descriptions, Dropdown, Popover, Table } from "antd";
22
- import React, { useContext, useMemo, useState } from "react";
45
+ import React, { lazy, Suspense, useContext, useMemo, useState } from "react";
23
46
  import { ActionIconBox } from "../../Components/ActionIconBox";
24
47
  import { Loading } from "../../Components/Loading";
25
48
  import { useIntersectionOnce } from "../../Hooks/useIntersectionOnce";
@@ -75,6 +98,219 @@ var getChartMap = (i18n) => {
75
98
  }
76
99
  };
77
100
  };
101
+ var ChartRuntimeRendererImpl = ({
102
+ chartType,
103
+ runtime,
104
+ convertDonutData,
105
+ convertFlatData,
106
+ config,
107
+ renderKey,
108
+ title,
109
+ dataTime,
110
+ toolBar,
111
+ filterBy,
112
+ groupBy,
113
+ colorLegend,
114
+ chartData,
115
+ getFieldValue
116
+ }) => {
117
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
118
+ const {
119
+ DonutChart,
120
+ FunnelChart,
121
+ AreaChart,
122
+ BarChart,
123
+ LineChart,
124
+ RadarChart,
125
+ ScatterChart
126
+ } = runtime;
127
+ if (chartType === "pie") {
128
+ return /* @__PURE__ */ React.createElement(
129
+ DonutChart,
130
+ {
131
+ key: `${config == null ? void 0 : config.index}-pie-${renderKey}`,
132
+ data: convertDonutData,
133
+ configs: [{ chartStyle: "pie", showLegend: true }],
134
+ height: (config == null ? void 0 : config.height) || 400,
135
+ title,
136
+ showToolbar: true,
137
+ dataTime,
138
+ toolbarExtra: toolBar
139
+ }
140
+ );
141
+ }
142
+ if (chartType === "donut") {
143
+ return /* @__PURE__ */ React.createElement(
144
+ DonutChart,
145
+ {
146
+ key: `${config == null ? void 0 : config.index}-donut-${renderKey}`,
147
+ data: convertDonutData,
148
+ configs: [{ chartStyle: "donut", showLegend: true }],
149
+ height: (config == null ? void 0 : config.height) || 400,
150
+ title,
151
+ showToolbar: true,
152
+ dataTime,
153
+ toolbarExtra: toolBar
154
+ }
155
+ );
156
+ }
157
+ if (chartType === "bar") {
158
+ return /* @__PURE__ */ React.createElement(
159
+ BarChart,
160
+ {
161
+ key: `${config == null ? void 0 : config.index}-bar-${renderKey}`,
162
+ data: convertFlatData,
163
+ height: (config == null ? void 0 : config.height) || 400,
164
+ title: title || "",
165
+ indexAxis: "y",
166
+ stacked: (_a = config == null ? void 0 : config.rest) == null ? void 0 : _a.stacked,
167
+ showLegend: (_c = (_b = config == null ? void 0 : config.rest) == null ? void 0 : _b.showLegend) != null ? _c : true,
168
+ showGrid: (_e = (_d = config == null ? void 0 : config.rest) == null ? void 0 : _d.showGrid) != null ? _e : true,
169
+ dataTime,
170
+ toolbarExtra: toolBar
171
+ }
172
+ );
173
+ }
174
+ if (chartType === "line") {
175
+ return /* @__PURE__ */ React.createElement(
176
+ LineChart,
177
+ {
178
+ key: `${config == null ? void 0 : config.index}-line-${renderKey}`,
179
+ data: convertFlatData,
180
+ height: (config == null ? void 0 : config.height) || 400,
181
+ title: title || "",
182
+ showLegend: (_g = (_f = config == null ? void 0 : config.rest) == null ? void 0 : _f.showLegend) != null ? _g : true,
183
+ showGrid: (_i = (_h = config == null ? void 0 : config.rest) == null ? void 0 : _h.showGrid) != null ? _i : true,
184
+ dataTime,
185
+ toolbarExtra: toolBar
186
+ }
187
+ );
188
+ }
189
+ if (chartType === "column") {
190
+ return /* @__PURE__ */ React.createElement(
191
+ BarChart,
192
+ {
193
+ key: `${config == null ? void 0 : config.index}-column-${renderKey}`,
194
+ data: convertFlatData,
195
+ height: (config == null ? void 0 : config.height) || 400,
196
+ title: title || "",
197
+ indexAxis: "x",
198
+ stacked: (_j = config == null ? void 0 : config.rest) == null ? void 0 : _j.stacked,
199
+ showLegend: (_l = (_k = config == null ? void 0 : config.rest) == null ? void 0 : _k.showLegend) != null ? _l : true,
200
+ showGrid: (_n = (_m = config == null ? void 0 : config.rest) == null ? void 0 : _m.showGrid) != null ? _n : true,
201
+ dataTime,
202
+ toolbarExtra: toolBar
203
+ }
204
+ );
205
+ }
206
+ if (chartType === "area") {
207
+ return /* @__PURE__ */ React.createElement(
208
+ AreaChart,
209
+ {
210
+ key: `${config == null ? void 0 : config.index}-area-${renderKey}`,
211
+ data: convertFlatData,
212
+ height: (config == null ? void 0 : config.height) || 400,
213
+ title: title || "",
214
+ showLegend: (_p = (_o = config == null ? void 0 : config.rest) == null ? void 0 : _o.showLegend) != null ? _p : true,
215
+ showGrid: (_r = (_q = config == null ? void 0 : config.rest) == null ? void 0 : _q.showGrid) != null ? _r : true,
216
+ dataTime,
217
+ toolbarExtra: toolBar
218
+ }
219
+ );
220
+ }
221
+ if (chartType === "radar") {
222
+ const radarData = (chartData || []).map((row, i) => {
223
+ var _a2;
224
+ const filterLabel = getFieldValue(row, filterBy);
225
+ const category = getFieldValue(row, groupBy);
226
+ const type = getFieldValue(row, colorLegend);
227
+ return __spreadValues(__spreadValues(__spreadValues({
228
+ label: String((_a2 = row == null ? void 0 : row[config == null ? void 0 : config.x]) != null ? _a2 : i + 1),
229
+ score: row == null ? void 0 : row[config == null ? void 0 : config.y]
230
+ }, category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
231
+ });
232
+ return /* @__PURE__ */ React.createElement(
233
+ RadarChart,
234
+ {
235
+ key: `${config == null ? void 0 : config.index}-radar-${renderKey}`,
236
+ data: radarData,
237
+ height: (config == null ? void 0 : config.height) || 400,
238
+ title: title || "",
239
+ dataTime,
240
+ toolbarExtra: toolBar
241
+ }
242
+ );
243
+ }
244
+ if (chartType === "scatter") {
245
+ const scatterData = (chartData || []).map((row) => {
246
+ const filterLabel = getFieldValue(row, filterBy);
247
+ const category = getFieldValue(row, groupBy);
248
+ const type = getFieldValue(row, colorLegend);
249
+ return __spreadValues(__spreadValues(__spreadValues({
250
+ x: row == null ? void 0 : row[config == null ? void 0 : config.x],
251
+ y: row == null ? void 0 : row[config == null ? void 0 : config.y]
252
+ }, category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
253
+ });
254
+ return /* @__PURE__ */ React.createElement(
255
+ ScatterChart,
256
+ {
257
+ key: `${config == null ? void 0 : config.index}-scatter-${renderKey}`,
258
+ data: scatterData,
259
+ height: (config == null ? void 0 : config.height) || 400,
260
+ title: title || "",
261
+ dataTime,
262
+ toolbarExtra: toolBar
263
+ }
264
+ );
265
+ }
266
+ if (chartType === "funnel") {
267
+ const funnelData = (chartData || []).map((row, i) => {
268
+ var _a2;
269
+ const filterLabel = getFieldValue(row, filterBy);
270
+ const category = getFieldValue(row, groupBy);
271
+ const type = getFieldValue(row, colorLegend);
272
+ return __spreadValues(__spreadValues(__spreadValues(__spreadValues({
273
+ x: String((_a2 = row == null ? void 0 : row[config == null ? void 0 : config.x]) != null ? _a2 : i + 1),
274
+ y: toNumber(row == null ? void 0 : row[config == null ? void 0 : config.y], 0)
275
+ }, (row == null ? void 0 : row.ratio) !== void 0 ? { ratio: row.ratio } : {}), category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
276
+ });
277
+ return /* @__PURE__ */ React.createElement(
278
+ FunnelChart,
279
+ {
280
+ key: `${config == null ? void 0 : config.index}-funnel-${renderKey}`,
281
+ data: funnelData,
282
+ height: (config == null ? void 0 : config.height) || 400,
283
+ title: title || "",
284
+ dataTime,
285
+ typeNames: { rate: "转化率", name: colorLegend || "转化" },
286
+ toolbarExtra: toolBar
287
+ }
288
+ );
289
+ }
290
+ return null;
291
+ };
292
+ var ChartRuntimeRenderer = lazy(() => __async(void 0, null, function* () {
293
+ const runtime = yield loadChartRuntime();
294
+ return {
295
+ default: (props) => /* @__PURE__ */ React.createElement(ChartRuntimeRendererImpl, __spreadProps(__spreadValues({}, props), { runtime }))
296
+ };
297
+ }));
298
+ var ChartRuntimeFallback = ({ height = 240 }) => /* @__PURE__ */ React.createElement(
299
+ "div",
300
+ {
301
+ style: {
302
+ minHeight: height,
303
+ display: "flex",
304
+ alignItems: "center",
305
+ justifyContent: "center",
306
+ width: "100%",
307
+ color: "#6B7280"
308
+ },
309
+ role: "status",
310
+ "aria-live": "polite"
311
+ },
312
+ /* @__PURE__ */ React.createElement(Loading, null)
313
+ );
78
314
  var ChartRender = (props) => {
79
315
  const [chartType, setChartType] = useState(() => props.chartType);
80
316
  const {
@@ -91,9 +327,6 @@ var ChartRender = (props) => {
91
327
  const i18n = useContext(I18nContext);
92
328
  const [config, setConfig] = useState(() => props.config);
93
329
  const [renderKey, setRenderKey] = useState(0);
94
- const [runtime, setRuntime] = useState(null);
95
- const [runtimeError, setRuntimeError] = useState(null);
96
- const [isRuntimeLoading, setRuntimeLoading] = useState(false);
97
330
  const containerRef = React.useRef(null);
98
331
  const isIntersecting = useIntersectionOnce(containerRef);
99
332
  const renderDescriptionsFallback = React.useMemo(() => {
@@ -102,43 +335,6 @@ var ChartRender = (props) => {
102
335
  return chartData.length < 2 && columnCount > 8;
103
336
  }, [chartData, config == null ? void 0 : config.columns]);
104
337
  const shouldLoadRuntime = chartType !== "table" && chartType !== "descriptions" && !renderDescriptionsFallback;
105
- React.useEffect(() => {
106
- if (runtime)
107
- return;
108
- if (isRuntimeLoading)
109
- return;
110
- if (runtimeError)
111
- return;
112
- let cancelled = false;
113
- setRuntimeLoading(true);
114
- loadChartRuntime().then((module) => {
115
- if (cancelled)
116
- return;
117
- setRuntime(module);
118
- }).catch((error) => {
119
- if (cancelled)
120
- return;
121
- const message = error instanceof Error ? error.message : String(error);
122
- setRuntimeError(message);
123
- }).finally(() => {
124
- if (cancelled)
125
- return;
126
- setRuntimeLoading(false);
127
- });
128
- return () => {
129
- cancelled = true;
130
- };
131
- }, [
132
- shouldLoadRuntime,
133
- isIntersecting,
134
- runtime,
135
- isRuntimeLoading,
136
- runtimeError
137
- ]);
138
- const handleRetryRuntime = React.useCallback(() => {
139
- setRuntime(null);
140
- setRuntimeError(null);
141
- }, []);
142
338
  const ChartMap = useMemo(() => getChartMap(i18n), [i18n]);
143
339
  const getAxisTitles = () => {
144
340
  var _a, _b, _c, _d;
@@ -408,7 +604,6 @@ var ChartRender = (props) => {
408
604
  };
409
605
  const toolBar = getChartPopover();
410
606
  const chartDom = useMemo(() => {
411
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
412
607
  if (typeof window === "undefined")
413
608
  return null;
414
609
  if (false)
@@ -456,7 +651,7 @@ var ChartRender = (props) => {
456
651
  }
457
652
  },
458
653
  chartData.map((row, rowIndex) => {
459
- var _a2;
654
+ var _a;
460
655
  return /* @__PURE__ */ React.createElement(
461
656
  Descriptions,
462
657
  {
@@ -470,7 +665,7 @@ var ChartRender = (props) => {
470
665
  sm: 1,
471
666
  xs: 1
472
667
  },
473
- items: (_a2 = config == null ? void 0 : config.columns) == null ? void 0 : _a2.map((column) => {
668
+ items: (_a = config == null ? void 0 : config.columns) == null ? void 0 : _a.map((column) => {
474
669
  if (!column.title || !column.dataIndex)
475
670
  return null;
476
671
  return {
@@ -483,234 +678,34 @@ var ChartRender = (props) => {
483
678
  })
484
679
  );
485
680
  }
486
- if (!runtime && shouldLoadRuntime) {
487
- const height = (config == null ? void 0 : config.height) || 240;
488
- if (runtimeError) {
489
- return /* @__PURE__ */ React.createElement(
490
- "div",
491
- {
492
- style: {
493
- minHeight: height,
494
- display: "flex",
495
- flexDirection: "column",
496
- alignItems: "center",
497
- justifyContent: "center",
498
- width: "100%",
499
- gap: 8,
500
- color: "rgba(239, 68, 68, 0.8)"
501
- },
502
- role: "alert"
503
- },
504
- /* @__PURE__ */ React.createElement("span", null, runtimeError),
505
- /* @__PURE__ */ React.createElement(
506
- "button",
507
- {
508
- type: "button",
509
- onClick: handleRetryRuntime,
510
- style: {
511
- padding: "4px 12px",
512
- borderRadius: "0.5em",
513
- border: "1px solid rgba(239, 68, 68, 0.5)",
514
- background: "transparent",
515
- color: "rgba(239, 68, 68, 0.8)",
516
- cursor: "pointer"
517
- }
518
- },
519
- "重试加载"
520
- )
521
- );
522
- }
681
+ if (shouldLoadRuntime && isIntersecting) {
523
682
  return /* @__PURE__ */ React.createElement(
524
- "div",
683
+ Suspense,
525
684
  {
526
- style: {
527
- minHeight: height,
528
- display: "flex",
529
- alignItems: "center",
530
- justifyContent: "center",
531
- width: "100%",
532
- color: "#6B7280"
533
- },
534
- role: "status",
535
- "aria-live": "polite"
685
+ fallback: /* @__PURE__ */ React.createElement(ChartRuntimeFallback, { height: (config == null ? void 0 : config.height) || 240 })
536
686
  },
537
- isRuntimeLoading || !isIntersecting ? /* @__PURE__ */ React.createElement(Loading, null) : null
538
- );
539
- }
540
- if (!runtime) {
541
- return null;
542
- }
543
- const {
544
- DonutChart,
545
- FunnelChart,
546
- AreaChart,
547
- BarChart,
548
- LineChart,
549
- RadarChart,
550
- ScatterChart
551
- } = runtime;
552
- if (chartType === "pie") {
553
- return /* @__PURE__ */ React.createElement(
554
- DonutChart,
555
- {
556
- key: `${config == null ? void 0 : config.index}-pie-${renderKey}`,
557
- data: convertDonutData,
558
- configs: [{ chartStyle: "pie", showLegend: true }],
559
- height: (config == null ? void 0 : config.height) || 400,
560
- title,
561
- showToolbar: true,
562
- dataTime,
563
- toolbarExtra: toolBar
564
- }
565
- );
566
- }
567
- if (chartType === "donut") {
568
- return /* @__PURE__ */ React.createElement(
569
- DonutChart,
570
- {
571
- key: `${config == null ? void 0 : config.index}-donut-${renderKey}`,
572
- data: convertDonutData,
573
- configs: [{ chartStyle: "donut", showLegend: true }],
574
- height: (config == null ? void 0 : config.height) || 400,
575
- title,
576
- showToolbar: true,
577
- dataTime,
578
- toolbarExtra: toolBar
579
- }
580
- );
581
- }
582
- if (chartType === "bar") {
583
- return /* @__PURE__ */ React.createElement(
584
- BarChart,
585
- {
586
- key: `${config == null ? void 0 : config.index}-bar-${renderKey}`,
587
- data: convertFlatData,
588
- height: (config == null ? void 0 : config.height) || 400,
589
- title: title || "",
590
- indexAxis: "y",
591
- stacked: (_a = config == null ? void 0 : config.rest) == null ? void 0 : _a.stacked,
592
- showLegend: (_c = (_b = config == null ? void 0 : config.rest) == null ? void 0 : _b.showLegend) != null ? _c : true,
593
- showGrid: (_e = (_d = config == null ? void 0 : config.rest) == null ? void 0 : _d.showGrid) != null ? _e : true,
594
- dataTime,
595
- toolbarExtra: toolBar
596
- }
597
- );
598
- }
599
- if (chartType === "line") {
600
- return /* @__PURE__ */ React.createElement(
601
- LineChart,
602
- {
603
- key: `${config == null ? void 0 : config.index}-line-${renderKey}`,
604
- data: convertFlatData,
605
- height: (config == null ? void 0 : config.height) || 400,
606
- title: title || "",
607
- showLegend: (_g = (_f = config == null ? void 0 : config.rest) == null ? void 0 : _f.showLegend) != null ? _g : true,
608
- showGrid: (_i = (_h = config == null ? void 0 : config.rest) == null ? void 0 : _h.showGrid) != null ? _i : true,
609
- dataTime,
610
- toolbarExtra: toolBar
611
- }
612
- );
613
- }
614
- if (chartType === "column") {
615
- return /* @__PURE__ */ React.createElement(
616
- BarChart,
617
- {
618
- key: `${config == null ? void 0 : config.index}-column-${renderKey}`,
619
- data: convertFlatData,
620
- height: (config == null ? void 0 : config.height) || 400,
621
- title: title || "",
622
- indexAxis: "x",
623
- stacked: (_j = config == null ? void 0 : config.rest) == null ? void 0 : _j.stacked,
624
- showLegend: (_l = (_k = config == null ? void 0 : config.rest) == null ? void 0 : _k.showLegend) != null ? _l : true,
625
- showGrid: (_n = (_m = config == null ? void 0 : config.rest) == null ? void 0 : _m.showGrid) != null ? _n : true,
626
- dataTime,
627
- toolbarExtra: toolBar
628
- }
629
- );
630
- }
631
- if (chartType === "area") {
632
- return /* @__PURE__ */ React.createElement(
633
- AreaChart,
634
- {
635
- key: `${config == null ? void 0 : config.index}-area-${renderKey}`,
636
- data: convertFlatData,
637
- height: (config == null ? void 0 : config.height) || 400,
638
- title: title || "",
639
- showLegend: (_p = (_o = config == null ? void 0 : config.rest) == null ? void 0 : _o.showLegend) != null ? _p : true,
640
- showGrid: (_r = (_q = config == null ? void 0 : config.rest) == null ? void 0 : _q.showGrid) != null ? _r : true,
641
- dataTime,
642
- toolbarExtra: toolBar
643
- }
644
- );
645
- }
646
- if (chartType === "radar") {
647
- const radarData = (chartData || []).map((row, i) => {
648
- var _a2;
649
- const filterLabel = getFieldValue(row, filterBy);
650
- const category = getFieldValue(row, groupBy);
651
- const type = getFieldValue(row, colorLegend);
652
- return __spreadValues(__spreadValues(__spreadValues({
653
- label: String((_a2 = row == null ? void 0 : row[config == null ? void 0 : config.x]) != null ? _a2 : i + 1),
654
- score: row == null ? void 0 : row[config == null ? void 0 : config.y]
655
- }, category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
656
- });
657
- return /* @__PURE__ */ React.createElement(
658
- RadarChart,
659
- {
660
- key: `${config == null ? void 0 : config.index}-radar-${renderKey}`,
661
- data: radarData,
662
- height: (config == null ? void 0 : config.height) || 400,
663
- title: title || "",
664
- dataTime,
665
- toolbarExtra: toolBar
666
- }
667
- );
668
- }
669
- if (chartType === "scatter") {
670
- const scatterData = (chartData || []).map((row) => {
671
- const filterLabel = getFieldValue(row, filterBy);
672
- const category = getFieldValue(row, groupBy);
673
- const type = getFieldValue(row, colorLegend);
674
- return __spreadValues(__spreadValues(__spreadValues({
675
- x: row == null ? void 0 : row[config == null ? void 0 : config.x],
676
- y: row == null ? void 0 : row[config == null ? void 0 : config.y]
677
- }, category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
678
- });
679
- return /* @__PURE__ */ React.createElement(
680
- ScatterChart,
681
- {
682
- key: `${config == null ? void 0 : config.index}-scatter-${renderKey}`,
683
- data: scatterData,
684
- height: (config == null ? void 0 : config.height) || 400,
685
- title: title || "",
686
- dataTime,
687
- toolbarExtra: toolBar
688
- }
687
+ /* @__PURE__ */ React.createElement(
688
+ ChartRuntimeRenderer,
689
+ {
690
+ chartType,
691
+ convertDonutData,
692
+ convertFlatData,
693
+ config,
694
+ renderKey,
695
+ title,
696
+ dataTime,
697
+ toolBar,
698
+ filterBy,
699
+ groupBy,
700
+ colorLegend,
701
+ chartData,
702
+ getFieldValue
703
+ }
704
+ )
689
705
  );
690
706
  }
691
- if (chartType === "funnel") {
692
- const funnelData = (chartData || []).map((row, i) => {
693
- var _a2;
694
- const filterLabel = getFieldValue(row, filterBy);
695
- const category = getFieldValue(row, groupBy);
696
- const type = getFieldValue(row, colorLegend);
697
- return __spreadValues(__spreadValues(__spreadValues(__spreadValues({
698
- x: String((_a2 = row == null ? void 0 : row[config == null ? void 0 : config.x]) != null ? _a2 : i + 1),
699
- y: toNumber(row == null ? void 0 : row[config == null ? void 0 : config.y], 0)
700
- }, (row == null ? void 0 : row.ratio) !== void 0 ? { ratio: row.ratio } : {}), category ? { category } : {}), type ? { type } : {}), filterLabel ? { filterLabel } : {});
701
- });
702
- return /* @__PURE__ */ React.createElement(
703
- FunnelChart,
704
- {
705
- key: `${config == null ? void 0 : config.index}-funnel-${renderKey}`,
706
- data: funnelData,
707
- height: (config == null ? void 0 : config.height) || 400,
708
- title: title || "",
709
- dataTime,
710
- typeNames: { rate: "转化率", name: colorLegend || "转化" },
711
- toolbarExtra: toolBar
712
- }
713
- );
707
+ if (shouldLoadRuntime && !isIntersecting) {
708
+ return /* @__PURE__ */ React.createElement(ChartRuntimeFallback, { height: (config == null ? void 0 : config.height) || 240 });
714
709
  }
715
710
  return null;
716
711
  }, [
@@ -726,13 +721,9 @@ var ChartRender = (props) => {
726
721
  filterBy,
727
722
  groupBy,
728
723
  colorLegend,
729
- runtime,
730
- runtimeError,
731
- isRuntimeLoading,
732
724
  isIntersecting,
733
725
  shouldLoadRuntime,
734
- renderDescriptionsFallback,
735
- handleRetryRuntime
726
+ renderDescriptionsFallback
736
727
  ]);
737
728
  return /* @__PURE__ */ React.createElement("div", { ref: containerRef, style: { width: "100%" }, contentEditable: false }, chartDom);
738
729
  };
@@ -56,30 +56,53 @@ var loadChartRuntime = () => __async(void 0, null, function* () {
56
56
  }
57
57
  if (!runtimeLoader) {
58
58
  runtimeLoader = Promise.all([
59
- Promise.resolve().then(() => __toESM(__require("./AreaChart"))),
60
- Promise.resolve().then(() => __toESM(__require("./BarChart"))),
61
- Promise.resolve().then(() => __toESM(__require("./DonutChart"))),
62
- Promise.resolve().then(() => __toESM(__require("./FunnelChart"))),
63
- Promise.resolve().then(() => __toESM(__require("./LineChart"))),
64
- Promise.resolve().then(() => __toESM(__require("./RadarChart"))),
65
- Promise.resolve().then(() => __toESM(__require("./ScatterChart")))
66
- ]).then(([
67
- areaModule,
68
- barModule,
69
- donutModule,
70
- funnelModule,
71
- lineModule,
72
- radarModule,
73
- scatterModule
74
- ]) => ({
75
- AreaChart: areaModule.default,
76
- BarChart: barModule.default,
77
- DonutChart: donutModule.default,
78
- FunnelChart: funnelModule.default,
79
- LineChart: lineModule.default,
80
- RadarChart: radarModule.default,
81
- ScatterChart: scatterModule.default
82
- })).catch((error) => {
59
+ Promise.resolve().then(() => __toESM(__require(
60
+ /* webpackChunkName: "chart-area" */
61
+ "./AreaChart"
62
+ ))),
63
+ Promise.resolve().then(() => __toESM(__require(
64
+ /* webpackChunkName: "chart-bar" */
65
+ "./BarChart"
66
+ ))),
67
+ Promise.resolve().then(() => __toESM(__require(
68
+ /* webpackChunkName: "chart-donut" */
69
+ "./DonutChart"
70
+ ))),
71
+ Promise.resolve().then(() => __toESM(__require(
72
+ /* webpackChunkName: "chart-funnel" */
73
+ "./FunnelChart"
74
+ ))),
75
+ Promise.resolve().then(() => __toESM(__require(
76
+ /* webpackChunkName: "chart-line" */
77
+ "./LineChart"
78
+ ))),
79
+ Promise.resolve().then(() => __toESM(__require(
80
+ /* webpackChunkName: "chart-radar" */
81
+ "./RadarChart"
82
+ ))),
83
+ Promise.resolve().then(() => __toESM(__require(
84
+ /* webpackChunkName: "chart-scatter" */
85
+ "./ScatterChart"
86
+ )))
87
+ ]).then(
88
+ ([
89
+ areaModule,
90
+ barModule,
91
+ donutModule,
92
+ funnelModule,
93
+ lineModule,
94
+ radarModule,
95
+ scatterModule
96
+ ]) => ({
97
+ AreaChart: areaModule.default,
98
+ BarChart: barModule.default,
99
+ DonutChart: donutModule.default,
100
+ FunnelChart: funnelModule.default,
101
+ LineChart: lineModule.default,
102
+ RadarChart: radarModule.default,
103
+ ScatterChart: scatterModule.default
104
+ })
105
+ ).catch((error) => {
83
106
  runtimeLoader = null;
84
107
  throw error;
85
108
  });
@@ -1,23 +1,27 @@
1
1
  import React from 'react';
2
2
  import { CodeNode } from '../../MarkdownEditor/el';
3
3
  type MermaidApi = typeof import('mermaid').default;
4
+ /**
5
+ * 加载 Mermaid 库
6
+ * 使用单例模式确保只加载一次,并初始化配置
7
+ */
4
8
  export declare const loadMermaid: () => Promise<MermaidApi>;
5
9
  /**
6
10
  * Mermaid 组件 - Mermaid图表渲染组件
7
11
  *
8
12
  * 该组件使用Mermaid库渲染图表,支持流程图、时序图、甘特图等。
9
- * 提供图表渲染、错误处理、延迟渲染等功能。
13
+ * 使用 React.lazy 和 Suspense 实现代码分割和延迟加载,优化性能。
10
14
  *
11
15
  * @component
12
16
  * @description Mermaid图表渲染组件,支持各种Mermaid图表类型
13
17
  * @param {Object} props - 组件属性
14
- * @param {CodeNode} props.el - 代码节点,包含Mermaid图表代码
15
- * @param {string} [props.el.value] - Mermaid图表代码字符串
18
+ * @param {CodeNode} props.element - 代码节点,包含Mermaid图表代码
19
+ * @param {string} [props.element.value] - Mermaid图表代码字符串
16
20
  *
17
21
  * @example
18
22
  * ```tsx
19
23
  * <Mermaid
20
- * el={{
24
+ * element={{
21
25
  * type: 'code',
22
26
  * value: 'graph TD\nA[开始] --> B[处理] --> C[结束]'
23
27
  * }}
@@ -29,6 +33,7 @@ export declare const loadMermaid: () => Promise<MermaidApi>;
29
33
  * @remarks
30
34
  * - 基于Mermaid库实现图表渲染
31
35
  * - 支持多种图表类型(流程图、时序图、甘特图等)
36
+ * - 使用 React.lazy 和 Suspense 实现代码分割
32
37
  * - 提供延迟渲染优化性能
33
38
  * - 包含错误处理机制
34
39
  * - 支持空状态显示
@@ -49,7 +49,7 @@ var __async = (__this, __arguments, generator) => {
49
49
  };
50
50
 
51
51
  // src/Plugins/mermaid/Mermaid.tsx
52
- import React, { useEffect, useMemo, useRef } from "react";
52
+ import React, { lazy, Suspense, useEffect, useMemo, useRef } from "react";
53
53
  import { useGetSetState } from "react-use";
54
54
  import { useIntersectionOnce } from "../../Hooks/useIntersectionOnce";
55
55
  var mermaidLoader = null;
@@ -58,7 +58,11 @@ var loadMermaid = () => __async(void 0, null, function* () {
58
58
  throw new Error("Mermaid 仅在浏览器环境中可用");
59
59
  }
60
60
  if (!mermaidLoader) {
61
- mermaidLoader = Promise.resolve().then(() => __toESM(__require("mermaid"))).then((module) => {
61
+ mermaidLoader = Promise.resolve().then(() => __toESM(__require(
62
+ /* webpackChunkName: "mermaid" */
63
+ /* webpackMode: "lazy" */
64
+ "mermaid"
65
+ ))).then((module) => {
62
66
  const api = module.default;
63
67
  if (api == null ? void 0 : api.initialize) {
64
68
  api.initialize({ startOnLoad: false });
@@ -71,9 +75,8 @@ var loadMermaid = () => __async(void 0, null, function* () {
71
75
  }
72
76
  return mermaidLoader;
73
77
  });
74
- var Mermaid = (props) => {
78
+ var MermaidRendererImpl = (props) => {
75
79
  var _a;
76
- const isBrowser = typeof window !== "undefined";
77
80
  const [state, setState] = useGetSetState({
78
81
  code: "",
79
82
  error: ""
@@ -88,9 +91,6 @@ var Mermaid = (props) => {
88
91
  );
89
92
  const isVisible = useIntersectionOnce(containerRef);
90
93
  useEffect(() => {
91
- if (!isBrowser) {
92
- return void 0;
93
- }
94
94
  const nextCode = props.element.value || "";
95
95
  const currentState = state();
96
96
  if (!isVisible) {
@@ -151,10 +151,7 @@ var Mermaid = (props) => {
151
151
  timer.current = null;
152
152
  }
153
153
  };
154
- }, [isBrowser, (_a = props == null ? void 0 : props.element) == null ? void 0 : _a.value, id, isVisible, setState, state]);
155
- if (!isBrowser) {
156
- return null;
157
- }
154
+ }, [(_a = props == null ? void 0 : props.element) == null ? void 0 : _a.value, id, isVisible, setState, state]);
158
155
  const snapshot = state();
159
156
  return /* @__PURE__ */ React.createElement(
160
157
  "div",
@@ -188,6 +185,31 @@ var Mermaid = (props) => {
188
185
  !snapshot.code && !snapshot.error && /* @__PURE__ */ React.createElement("div", { style: { textAlign: "center", color: "#6B7280" } }, "Empty")
189
186
  );
190
187
  };
188
+ var MermaidRenderer = lazy(() => __async(void 0, null, function* () {
189
+ yield loadMermaid();
190
+ return { default: MermaidRendererImpl };
191
+ }));
192
+ var MermaidFallback = () => /* @__PURE__ */ React.createElement(
193
+ "div",
194
+ {
195
+ style: {
196
+ marginBottom: "0.75em",
197
+ padding: "0.75rem 0",
198
+ display: "flex",
199
+ justifyContent: "center",
200
+ alignItems: "center",
201
+ color: "#6B7280"
202
+ }
203
+ },
204
+ "加载中..."
205
+ );
206
+ var Mermaid = (props) => {
207
+ const isBrowser = typeof window !== "undefined";
208
+ if (!isBrowser) {
209
+ return null;
210
+ }
211
+ return /* @__PURE__ */ React.createElement(Suspense, { fallback: /* @__PURE__ */ React.createElement(MermaidFallback, null) }, /* @__PURE__ */ React.createElement(MermaidRenderer, { element: props.element }));
212
+ };
191
213
  export {
192
214
  Mermaid,
193
215
  loadMermaid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ant-design/agentic-ui",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "面向智能体的 UI 组件库,提供多步推理可视化、工具调用展示、任务执行协同等 Agentic UI 能力",
5
5
  "repository": "git@github.com:ant-design/agentic-ui.git",
6
6
  "license": "MIT",
@@ -26,7 +26,7 @@
26
26
  "prettier": "prettier --write \"{src,docs,test}/**/*.{js,jsx,ts,tsx,css,less,json,md}\"",
27
27
  "report:demo": "node scripts/generateDemoReport.js",
28
28
  "start": "npm run dev",
29
- "test": "echo \"No test specified\" && exit 0",
29
+ "test": "echo 'test'",
30
30
  "test:coverage": "vitest --run --coverage",
31
31
  "tsc": "tsc --noEmit"
32
32
  },