@ant-design/agentic-ui 2.29.37 → 2.29.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Hooks/useLanguage.d.ts +21 -0
- package/dist/I18n/locales.d.ts +22 -3
- package/dist/I18n/locales.js +51 -5
- package/dist/MarkdownEditor/editor/elements/index.js +15 -1
- package/dist/MarkdownEditor/editor/parser/constants.d.ts +5 -0
- package/dist/MarkdownEditor/editor/parser/constants.js +4 -0
- package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +5 -4
- package/dist/MarkdownEditor/editor/parser/remarkParse.d.ts +5 -0
- package/dist/MarkdownEditor/editor/parser/remarkParse.js +16 -0
- package/dist/MarkdownEditor/editor/plugins/useHighlight.js +53 -10
- package/dist/MarkdownEditor/editor/plugins/useKeyboard.js +2 -2
- package/dist/MarkdownEditor/editor/style.js +1 -1
- package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/index.js +35 -23
- package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/style.js +47 -37
- package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/templates.d.ts +13 -1
- package/dist/MarkdownEditor/editor/tools/JinjaTemplatePanel/templates.js +30 -11
- package/dist/MarkdownEditor/editor/utils/markdownToHtml.js +5 -3
- package/dist/MarkdownInputField/RefinePromptButton/index.js +4 -2
- package/dist/Plugins/chart/ChartRender.js +4 -2
- package/dist/Plugins/chart/DonutChart/Legend.js +132 -12
- package/dist/Plugins/chart/DonutChart/index.js +58 -6
- package/dist/Plugins/chart/DonutChart/plugins.d.ts +5 -0
- package/dist/Plugins/chart/DonutChart/plugins.js +48 -0
- package/dist/Plugins/chart/DonutChart/style.js +17 -6
- package/dist/Plugins/chart/DonutChart/types.d.ts +2 -0
- package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +44 -2
- package/dist/Plugins/code/CodeUI/Katex/katex.min.css +1 -3
- package/dist/Plugins/katex/katex.min.css +1 -3
- package/package.json +3 -1
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
import type { LocalKeys } from '../../../../I18n';
|
|
1
2
|
import type { JinjaTemplateItem } from '../../../types';
|
|
2
|
-
|
|
3
|
+
declare const JINJA_TEMPLATE_IDS: readonly ["variableInterpolation", "condition", "loop", "filter", "setVariable"];
|
|
4
|
+
/** 内置 Jinja 模板基础数据(不含 i18n 文案) */
|
|
5
|
+
export declare const JINJA_TEMPLATE_BASE: {
|
|
6
|
+
id: (typeof JINJA_TEMPLATE_IDS)[number];
|
|
7
|
+
template: string;
|
|
8
|
+
}[];
|
|
9
|
+
/**
|
|
10
|
+
* 根据 locale 生成带国际化文案的 Jinja 模板列表
|
|
11
|
+
*/
|
|
12
|
+
export declare function getJinjaTemplateData(locale: LocalKeys): JinjaTemplateItem[];
|
|
13
|
+
/** 内置 Jinja 模板数据(默认中文),与 agent-ui-pc JinjaTemplateData 文案一致 */
|
|
3
14
|
export declare const JINJA_TEMPLATE_DATA: JinjaTemplateItem[];
|
|
4
15
|
/** 默认使用说明链接,未配置 jinja.docLink 时使用 */
|
|
5
16
|
export declare const JINJA_DOC_LINK = "https://jinja.palletsprojects.com/";
|
|
17
|
+
export {};
|
|
@@ -1,28 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
import { cnLabels } from "../../../../I18n";
|
|
2
|
+
var JINJA_TEMPLATE_IDS = [
|
|
3
|
+
'variableInterpolation',
|
|
4
|
+
'condition',
|
|
5
|
+
'loop',
|
|
6
|
+
'filter',
|
|
7
|
+
'setVariable'
|
|
8
|
+
];
|
|
9
|
+
/** 内置 Jinja 模板基础数据(不含 i18n 文案) */ export var JINJA_TEMPLATE_BASE = [
|
|
2
10
|
{
|
|
3
|
-
|
|
4
|
-
description: '{{ variable }}',
|
|
11
|
+
id: 'variableInterpolation',
|
|
5
12
|
template: '{{ }}'
|
|
6
13
|
},
|
|
7
14
|
{
|
|
8
|
-
|
|
9
|
-
description: '{% if condition %}...{% endif %}',
|
|
15
|
+
id: 'condition',
|
|
10
16
|
template: '{% if %}\n \n{% endif %}'
|
|
11
17
|
},
|
|
12
18
|
{
|
|
13
|
-
|
|
14
|
-
description: '{% for item in list %}...{% endfor %}',
|
|
19
|
+
id: 'loop',
|
|
15
20
|
template: '{% for in %}\n \n{% endfor %}'
|
|
16
21
|
},
|
|
17
22
|
{
|
|
18
|
-
|
|
19
|
-
description: '{{ value | filter }}',
|
|
23
|
+
id: 'filter',
|
|
20
24
|
template: '{{ | }}'
|
|
21
25
|
},
|
|
22
26
|
{
|
|
23
|
-
|
|
24
|
-
description: '{% set name = value %}',
|
|
27
|
+
id: 'setVariable',
|
|
25
28
|
template: '{% set = %}'
|
|
26
29
|
}
|
|
27
30
|
];
|
|
31
|
+
/**
|
|
32
|
+
* 根据 locale 生成带国际化文案的 Jinja 模板列表
|
|
33
|
+
*/ export function getJinjaTemplateData(locale) {
|
|
34
|
+
return JINJA_TEMPLATE_BASE.map(function(param) {
|
|
35
|
+
var id = param.id, template = param.template;
|
|
36
|
+
var _locale_titleKey, _locale_descKey;
|
|
37
|
+
var titleKey = "jinja.template.".concat(id, ".title");
|
|
38
|
+
var descKey = "jinja.template.".concat(id, ".description");
|
|
39
|
+
return {
|
|
40
|
+
title: (_locale_titleKey = locale[titleKey]) !== null && _locale_titleKey !== void 0 ? _locale_titleKey : id,
|
|
41
|
+
description: (_locale_descKey = locale[descKey]) !== null && _locale_descKey !== void 0 ? _locale_descKey : undefined,
|
|
42
|
+
template: template
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** 内置 Jinja 模板数据(默认中文),与 agent-ui-pc JinjaTemplateData 文案一致 */ export var JINJA_TEMPLATE_DATA = getJinjaTemplateData(cnLabels);
|
|
28
47
|
/** 默认使用说明链接,未配置 jinja.docLink 时使用 */ export var JINJA_DOC_LINK = 'https://jinja.palletsprojects.com/';
|
|
@@ -170,7 +170,8 @@ import remarkParse from "remark-parse";
|
|
|
170
170
|
import remarkRehype from "remark-rehype";
|
|
171
171
|
import { unified } from "unified";
|
|
172
172
|
import { visit } from "unist-util-visit";
|
|
173
|
-
import {
|
|
173
|
+
import { JINJA_DOLLAR_PLACEHOLDER } from "../parser/constants";
|
|
174
|
+
import { convertParagraphToImage, fixStrongWithSpecialChars, protectJinjaDollarInText } from "../parser/remarkParse";
|
|
174
175
|
// HTML 转义相关的正则表达式和工具
|
|
175
176
|
var ESCAPE_TEST_NO_ENCODE = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
|
|
176
177
|
var ESCAPE_TEST = /[&<>"']/;
|
|
@@ -305,6 +306,7 @@ export var DEFAULT_MARKDOWN_REMARK_PLUGINS = [
|
|
|
305
306
|
],
|
|
306
307
|
fixStrongWithSpecialChars,
|
|
307
308
|
convertParagraphToImage,
|
|
309
|
+
protectJinjaDollarInText,
|
|
308
310
|
[
|
|
309
311
|
remarkMath,
|
|
310
312
|
INLINE_MATH_WITH_SINGLE_DOLLAR
|
|
@@ -414,7 +416,7 @@ var createMarkdownProcessor = function createMarkdownProcessor(plugins, config)
|
|
|
414
416
|
htmlContent = _state.sent();
|
|
415
417
|
return [
|
|
416
418
|
2,
|
|
417
|
-
String(htmlContent)
|
|
419
|
+
String(htmlContent).split(JINJA_DOLLAR_PLACEHOLDER).join('$')
|
|
418
420
|
];
|
|
419
421
|
case 2:
|
|
420
422
|
error = _state.sent();
|
|
@@ -463,7 +465,7 @@ var createMarkdownProcessor = function createMarkdownProcessor(plugins, config)
|
|
|
463
465
|
*/ export var markdownToHtmlSync = function markdownToHtmlSync(markdown, plugins, config) {
|
|
464
466
|
try {
|
|
465
467
|
var file = createMarkdownProcessor(plugins, config).processSync(markdown);
|
|
466
|
-
return String(file);
|
|
468
|
+
return String(file).split(JINJA_DOLLAR_PLACEHOLDER).join('$');
|
|
467
469
|
} catch (error) {
|
|
468
470
|
console.error('Error converting markdown to HTML:', error);
|
|
469
471
|
return '';
|
|
@@ -2,6 +2,7 @@ import { LoadingOutlined } from "@ant-design/icons";
|
|
|
2
2
|
import { TextOptimize } from "@sofa-design/icons";
|
|
3
3
|
import { ConfigProvider, Tooltip } from "antd";
|
|
4
4
|
import React, { useContext } from "react";
|
|
5
|
+
import { useLocale } from "../../I18n";
|
|
5
6
|
import { ErrorBoundary } from "react-error-boundary";
|
|
6
7
|
import { ActionIconBox } from "../../Components/ActionIconBox";
|
|
7
8
|
import { isBrowserEnv } from "./env";
|
|
@@ -9,6 +10,7 @@ import { useStyle } from "./style";
|
|
|
9
10
|
export var RefinePromptButton = function RefinePromptButton(props) {
|
|
10
11
|
var disabled = props.disabled, status = props.status, onRefine = props.onRefine;
|
|
11
12
|
var getPrefixCls = useContext(ConfigProvider.ConfigContext).getPrefixCls;
|
|
13
|
+
var locale = useLocale();
|
|
12
14
|
var baseCls = getPrefixCls('agentic-md-input-field-refine-button');
|
|
13
15
|
var wrapSSR = useStyle(baseCls).wrapSSR;
|
|
14
16
|
var handleClick = function handleClick() {
|
|
@@ -24,9 +26,9 @@ export var RefinePromptButton = function RefinePromptButton(props) {
|
|
|
24
26
|
return null;
|
|
25
27
|
}
|
|
26
28
|
return wrapSSR(/*#__PURE__*/ React.createElement(Tooltip, {
|
|
27
|
-
title: status === 'loading' ? '
|
|
29
|
+
title: status === 'loading' ? locale['refine.loading'] : locale['refine.oneClickOptimize']
|
|
28
30
|
}, /*#__PURE__*/ React.createElement(ActionIconBox, {
|
|
29
|
-
title: '
|
|
31
|
+
title: locale['refine.optimizePrompt'],
|
|
30
32
|
onClick: handleClick,
|
|
31
33
|
"data-testid": "refine-prompt-button"
|
|
32
34
|
}, /*#__PURE__*/ React.createElement(ErrorBoundary, {
|
|
@@ -345,6 +345,7 @@ import { debounce, getDataHash, isConfigEqual, isNotEmpty, toNumber } from "./ut
|
|
|
345
345
|
* 负责使用已加载的 runtime 渲染图表
|
|
346
346
|
*/ var ChartRuntimeRendererImpl = function ChartRuntimeRendererImpl(param) {
|
|
347
347
|
var chartType = param.chartType, runtime = param.runtime, convertDonutData = param.convertDonutData, convertFlatData = param.convertFlatData, config = param.config, title = param.title, dataTime = param.dataTime, toolBar = param.toolBar, filterBy = param.filterBy, groupBy = param.groupBy, colorLegend = param.colorLegend, chartData = param.chartData, getFieldValue = param.getFieldValue, _param_loading = param.loading, loading = _param_loading === void 0 ? false : _param_loading;
|
|
348
|
+
var i18n = useContext(I18nContext);
|
|
348
349
|
var DonutChart = runtime.DonutChart, FunnelChart = runtime.FunnelChart, AreaChart = runtime.AreaChart, BarChart = runtime.BarChart, LineChart = runtime.LineChart, RadarChart = runtime.RadarChart, ScatterChart = runtime.ScatterChart;
|
|
349
350
|
if (chartType === 'pie') {
|
|
350
351
|
return /*#__PURE__*/ React.createElement(DonutChart, {
|
|
@@ -505,6 +506,7 @@ import { debounce, getDataHash, isConfigEqual, isNotEmpty, toNumber } from "./ut
|
|
|
505
506
|
});
|
|
506
507
|
}
|
|
507
508
|
if (chartType === 'funnel') {
|
|
509
|
+
var _i18n_locale, _i18n_locale1;
|
|
508
510
|
var funnelData = (chartData || []).map(function(row, i) {
|
|
509
511
|
var filterLabel = getFieldValue(row, filterBy);
|
|
510
512
|
var category = getFieldValue(row, groupBy);
|
|
@@ -532,8 +534,8 @@ import { debounce, getDataHash, isConfigEqual, isNotEmpty, toNumber } from "./ut
|
|
|
532
534
|
title: title || '',
|
|
533
535
|
dataTime: dataTime,
|
|
534
536
|
typeNames: {
|
|
535
|
-
rate: '转化率',
|
|
536
|
-
name: colorLegend || '转化'
|
|
537
|
+
rate: (i18n === null || i18n === void 0 ? void 0 : (_i18n_locale = i18n.locale) === null || _i18n_locale === void 0 ? void 0 : _i18n_locale['common.conversionRate']) || '转化率',
|
|
538
|
+
name: colorLegend || (i18n === null || i18n === void 0 ? void 0 : (_i18n_locale1 = i18n.locale) === null || _i18n_locale1 === void 0 ? void 0 : _i18n_locale1['common.conversion']) || '转化'
|
|
537
539
|
},
|
|
538
540
|
toolbarExtra: toolBar,
|
|
539
541
|
loading: loading
|
|
@@ -1,3 +1,11 @@
|
|
|
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
|
+
}
|
|
1
9
|
function _define_property(obj, key, value) {
|
|
2
10
|
if (key in obj) {
|
|
3
11
|
Object.defineProperty(obj, key, {
|
|
@@ -11,6 +19,33 @@ function _define_property(obj, key, value) {
|
|
|
11
19
|
}
|
|
12
20
|
return obj;
|
|
13
21
|
}
|
|
22
|
+
function _iterable_to_array_limit(arr, i) {
|
|
23
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
24
|
+
if (_i == null) return;
|
|
25
|
+
var _arr = [];
|
|
26
|
+
var _n = true;
|
|
27
|
+
var _d = false;
|
|
28
|
+
var _s, _e;
|
|
29
|
+
try {
|
|
30
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
31
|
+
_arr.push(_s.value);
|
|
32
|
+
if (i && _arr.length === i) break;
|
|
33
|
+
}
|
|
34
|
+
} catch (err) {
|
|
35
|
+
_d = true;
|
|
36
|
+
_e = err;
|
|
37
|
+
} finally{
|
|
38
|
+
try {
|
|
39
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
40
|
+
} finally{
|
|
41
|
+
if (_d) throw _e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return _arr;
|
|
45
|
+
}
|
|
46
|
+
function _non_iterable_rest() {
|
|
47
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
48
|
+
}
|
|
14
49
|
function _object_spread(target) {
|
|
15
50
|
for(var i = 1; i < arguments.length; i++){
|
|
16
51
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
@@ -26,32 +61,76 @@ function _object_spread(target) {
|
|
|
26
61
|
}
|
|
27
62
|
return target;
|
|
28
63
|
}
|
|
29
|
-
|
|
64
|
+
function _sliced_to_array(arr, i) {
|
|
65
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
66
|
+
}
|
|
67
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
68
|
+
if (!o) return;
|
|
69
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
70
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
71
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
72
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
73
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
74
|
+
}
|
|
75
|
+
import React, { useEffect, useState } from "react";
|
|
76
|
+
import { useLocale } from "../../../I18n";
|
|
77
|
+
/** 图例每页显示条数,超过则显示分页 */ var LEGEND_PAGE_SIZE = 12;
|
|
30
78
|
var Legend = function Legend(param) {
|
|
31
79
|
var chartData = param.chartData, backgroundColors = param.backgroundColors, hiddenDataIndicesByChart = param.hiddenDataIndicesByChart, chartIndex = param.chartIndex, onLegendItemClick = param.onLegendItemClick, total = param.total, baseClassName = param.baseClassName, hashId = param.hashId, isMobile = param.isMobile;
|
|
80
|
+
var locale = useLocale();
|
|
32
81
|
var hiddenDataIndices = React.useMemo(function() {
|
|
33
82
|
return hiddenDataIndicesByChart[chartIndex] || new Set();
|
|
34
83
|
}, [
|
|
35
84
|
hiddenDataIndicesByChart,
|
|
36
85
|
chartIndex
|
|
37
86
|
]);
|
|
87
|
+
var totalPages = Math.max(1, Math.ceil(chartData.length / LEGEND_PAGE_SIZE));
|
|
88
|
+
var _useState = _sliced_to_array(useState(0), 2), currentPage = _useState[0], setCurrentPage = _useState[1];
|
|
89
|
+
useEffect(function() {
|
|
90
|
+
setCurrentPage(0);
|
|
91
|
+
}, [
|
|
92
|
+
chartData.length,
|
|
93
|
+
chartIndex
|
|
94
|
+
]);
|
|
95
|
+
var startIndex = currentPage * LEGEND_PAGE_SIZE;
|
|
96
|
+
var displayedItems = chartData.slice(startIndex, startIndex + LEGEND_PAGE_SIZE);
|
|
97
|
+
var handlePrevPage = function handlePrevPage() {
|
|
98
|
+
setCurrentPage(function(p) {
|
|
99
|
+
return Math.max(0, p - 1);
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
var handleNextPage = function handleNextPage() {
|
|
103
|
+
setCurrentPage(function(p) {
|
|
104
|
+
return Math.min(totalPages - 1, p + 1);
|
|
105
|
+
});
|
|
106
|
+
};
|
|
38
107
|
return /*#__PURE__*/ React.createElement("div", {
|
|
39
108
|
className: [
|
|
40
109
|
"".concat(baseClassName, "-legend"),
|
|
41
110
|
hashId
|
|
42
111
|
].filter(Boolean).join(' '),
|
|
43
112
|
style: _object_spread({
|
|
44
|
-
marginLeft: isMobile ? 0 : 12
|
|
45
|
-
maxHeight: isMobile ? '120px' : 'none',
|
|
46
|
-
overflowY: isMobile ? 'auto' : 'visible'
|
|
113
|
+
marginLeft: isMobile ? 0 : 12
|
|
47
114
|
}, isMobile ? {
|
|
115
|
+
display: 'flex',
|
|
116
|
+
flexDirection: 'column',
|
|
117
|
+
maxHeight: '200px',
|
|
118
|
+
minHeight: 0,
|
|
48
119
|
alignSelf: 'center'
|
|
49
120
|
} : {})
|
|
50
|
-
},
|
|
51
|
-
|
|
121
|
+
}, /*#__PURE__*/ React.createElement("div", {
|
|
122
|
+
style: _object_spread({}, isMobile ? {
|
|
123
|
+
flex: 1,
|
|
124
|
+
minHeight: 0,
|
|
125
|
+
overflowY: 'auto',
|
|
126
|
+
overflowX: 'hidden'
|
|
127
|
+
} : {})
|
|
128
|
+
}, displayedItems.map(function(d, i) {
|
|
129
|
+
var dataIndex = startIndex + i;
|
|
130
|
+
var isHidden = hiddenDataIndices.has(dataIndex);
|
|
52
131
|
var _obj;
|
|
53
132
|
return /*#__PURE__*/ React.createElement("div", {
|
|
54
|
-
key:
|
|
133
|
+
key: dataIndex,
|
|
55
134
|
className: [
|
|
56
135
|
"".concat(baseClassName, "-legend-item"),
|
|
57
136
|
hashId
|
|
@@ -64,23 +143,23 @@ var Legend = function Legend(param) {
|
|
|
64
143
|
textDecoration: isHidden ? 'line-through' : 'none'
|
|
65
144
|
},
|
|
66
145
|
onClick: function onClick() {
|
|
67
|
-
return onLegendItemClick(
|
|
146
|
+
return onLegendItemClick(dataIndex);
|
|
68
147
|
},
|
|
69
148
|
onKeyDown: function onKeyDown(e) {
|
|
70
149
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
71
150
|
e.preventDefault();
|
|
72
|
-
onLegendItemClick(
|
|
151
|
+
onLegendItemClick(dataIndex);
|
|
73
152
|
}
|
|
74
153
|
},
|
|
75
154
|
tabIndex: 0,
|
|
76
155
|
role: "button",
|
|
77
|
-
"aria-label": "".concat(isHidden ? '
|
|
156
|
+
"aria-label": "".concat(isHidden ? locale['chart.legend.show'] : locale['chart.legend.hide'], " ").concat(d.label)
|
|
78
157
|
}, /*#__PURE__*/ React.createElement("span", {
|
|
79
158
|
className: [
|
|
80
159
|
"".concat(baseClassName, "-legend-color"),
|
|
81
160
|
hashId
|
|
82
161
|
].filter(Boolean).join(' '),
|
|
83
|
-
style: (_obj = {}, _define_property(_obj, '--donut-legend-color', backgroundColors[
|
|
162
|
+
style: (_obj = {}, _define_property(_obj, '--donut-legend-color', backgroundColors[dataIndex] || '#ccc'), _define_property(_obj, "width", isMobile ? 10 : 12), _define_property(_obj, "height", isMobile ? 10 : 12), _define_property(_obj, "borderRadius", 4), _define_property(_obj, "marginRight", isMobile ? 4 : 6), _obj)
|
|
84
163
|
}), /*#__PURE__*/ React.createElement("span", {
|
|
85
164
|
className: [
|
|
86
165
|
"".concat(baseClassName, "-legend-label"),
|
|
@@ -118,6 +197,47 @@ var Legend = function Legend(param) {
|
|
|
118
197
|
var v = typeof d.value === 'number' ? d.value : Number(d.value);
|
|
119
198
|
return total > 0 && Number.isFinite(v) ? (v / total * 100).toFixed(0) : '0';
|
|
120
199
|
}(), "%")));
|
|
121
|
-
}))
|
|
200
|
+
})), totalPages > 1 && /*#__PURE__*/ React.createElement("div", {
|
|
201
|
+
className: [
|
|
202
|
+
"".concat(baseClassName, "-legend-pagination"),
|
|
203
|
+
hashId
|
|
204
|
+
].filter(Boolean).join(' '),
|
|
205
|
+
style: isMobile ? {
|
|
206
|
+
flexShrink: 0
|
|
207
|
+
} : undefined
|
|
208
|
+
}, /*#__PURE__*/ React.createElement("button", {
|
|
209
|
+
type: "button",
|
|
210
|
+
"aria-label": locale['chart.legend.prevPage'],
|
|
211
|
+
disabled: currentPage <= 0,
|
|
212
|
+
onClick: handlePrevPage,
|
|
213
|
+
style: {
|
|
214
|
+
padding: '2px 6px',
|
|
215
|
+
fontSize: 12,
|
|
216
|
+
cursor: currentPage <= 0 ? 'not-allowed' : 'pointer',
|
|
217
|
+
opacity: currentPage <= 0 ? 0.5 : 1,
|
|
218
|
+
border: '1px solid rgba(0,0,0,0.15)',
|
|
219
|
+
borderRadius: 4,
|
|
220
|
+
background: '#fff'
|
|
221
|
+
}
|
|
222
|
+
}, "<"), /*#__PURE__*/ React.createElement("span", {
|
|
223
|
+
style: {
|
|
224
|
+
fontSize: 12,
|
|
225
|
+
color: '#767E8B'
|
|
226
|
+
}
|
|
227
|
+
}, currentPage + 1, "/", totalPages), /*#__PURE__*/ React.createElement("button", {
|
|
228
|
+
type: "button",
|
|
229
|
+
"aria-label": locale['chart.legend.nextPage'],
|
|
230
|
+
disabled: currentPage >= totalPages - 1,
|
|
231
|
+
onClick: handleNextPage,
|
|
232
|
+
style: {
|
|
233
|
+
padding: '2px 6px',
|
|
234
|
+
fontSize: 12,
|
|
235
|
+
cursor: currentPage >= totalPages - 1 ? 'not-allowed' : 'pointer',
|
|
236
|
+
opacity: currentPage >= totalPages - 1 ? 0.5 : 1,
|
|
237
|
+
border: '1px solid rgba(0,0,0,0.15)',
|
|
238
|
+
borderRadius: 4,
|
|
239
|
+
background: '#fff'
|
|
240
|
+
}
|
|
241
|
+
}, ">")));
|
|
122
242
|
};
|
|
123
243
|
export default Legend;
|
|
@@ -146,8 +146,10 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
146
146
|
}
|
|
147
147
|
import { ConfigProvider } from "antd";
|
|
148
148
|
import { ArcElement, Chart as ChartJS, Legend, Tooltip } from "chart.js";
|
|
149
|
+
import ChartDataLabels from "chartjs-plugin-datalabels";
|
|
149
150
|
import classNames from "clsx";
|
|
150
151
|
import React, { useContext, useMemo, useRef, useState } from "react";
|
|
152
|
+
import { useLocale } from "../../../I18n";
|
|
151
153
|
import { Doughnut } from "react-chartjs-2";
|
|
152
154
|
import { ChartContainer, ChartFilter, ChartStatistic, ChartToolBar, downloadChart } from "../components";
|
|
153
155
|
import { isWindowDefined } from "../env";
|
|
@@ -156,7 +158,7 @@ import { resolveCssVariable } from "../utils";
|
|
|
156
158
|
import { SINGLE_MODE_DESKTOP_CUTOUT, SINGLE_MODE_MOBILE_CUTOUT } from "./constants";
|
|
157
159
|
import { useAutoCategory, useFilterLabels, useMobile, useResponsiveDimensions } from "./hooks";
|
|
158
160
|
import LegendView from "./Legend";
|
|
159
|
-
import { createBackgroundArcPlugin, createCenterTextPlugin } from "./plugins";
|
|
161
|
+
import { createBackgroundArcPlugin, createCenterTextPlugin, createDataLabelsLeaderLinePlugin } from "./plugins";
|
|
160
162
|
import { useStyle } from "./style";
|
|
161
163
|
/**
|
|
162
164
|
* @fileoverview 环形图组件文件
|
|
@@ -225,11 +227,12 @@ import { useStyle } from "./style";
|
|
|
225
227
|
if (!isWindowDefined()) {
|
|
226
228
|
return undefined;
|
|
227
229
|
}
|
|
228
|
-
ChartJS.register(ArcElement, Tooltip, Legend);
|
|
230
|
+
ChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);
|
|
229
231
|
donutChartComponentsRegistered = true;
|
|
230
232
|
return undefined;
|
|
231
233
|
}, []);
|
|
232
234
|
var _useMobile = useMobile(), isMobile = _useMobile.isMobile, windowWidth = _useMobile.windowWidth;
|
|
235
|
+
var locale = useLocale();
|
|
233
236
|
// 默认配置:当 configs 不传时,使用默认配置,showLegend 默认为 true
|
|
234
237
|
var defaultConfigs = [
|
|
235
238
|
{
|
|
@@ -454,7 +457,7 @@ import { useStyle } from "./style";
|
|
|
454
457
|
chartData = [
|
|
455
458
|
currentDataItem,
|
|
456
459
|
{
|
|
457
|
-
label: '
|
|
460
|
+
label: locale['chart.legend.remaining'],
|
|
458
461
|
value: remainingValue,
|
|
459
462
|
category: currentDataItem.category
|
|
460
463
|
}
|
|
@@ -546,6 +549,9 @@ import { useStyle } from "./style";
|
|
|
546
549
|
legend: {
|
|
547
550
|
display: false
|
|
548
551
|
},
|
|
552
|
+
/** 默认不展示扇区上的数值与占比,仅通过 configs[].showDataLabels === true 开启 */ datalabels: {
|
|
553
|
+
display: false
|
|
554
|
+
},
|
|
549
555
|
tooltip: {
|
|
550
556
|
enabled: cfg.showTooltip !== false,
|
|
551
557
|
filter: function filter(tooltipItem) {
|
|
@@ -568,7 +574,10 @@ import { useStyle } from "./style";
|
|
|
568
574
|
var label = param.label, raw = param.raw;
|
|
569
575
|
var val = typeof raw === 'number' ? raw : Number(raw);
|
|
570
576
|
var pct = total > 0 && Number.isFinite(val) ? (val / total * 100).toFixed(0) : '0';
|
|
571
|
-
|
|
577
|
+
if (cfg.showDataLabels) {
|
|
578
|
+
return "".concat(label, ": ").concat(Number.isFinite(val) ? val : raw, " (").concat(pct, "%)");
|
|
579
|
+
}
|
|
580
|
+
return "".concat(label, " (").concat(pct, "%)");
|
|
572
581
|
}
|
|
573
582
|
}
|
|
574
583
|
}
|
|
@@ -584,6 +593,43 @@ import { useStyle } from "./style";
|
|
|
584
593
|
padding: isMobile ? 4 : 6
|
|
585
594
|
}
|
|
586
595
|
};
|
|
596
|
+
var dataLabelOffset = isMobile ? 22 : 36;
|
|
597
|
+
var optionsWithDataLabels = _object_spread_props(_object_spread({}, options, cfg.showDataLabels === true && !isSingleValueMode && {
|
|
598
|
+
layout: _object_spread_props(_object_spread({}, options.layout), {
|
|
599
|
+
padding: isMobile ? 36 : 52
|
|
600
|
+
})
|
|
601
|
+
}), {
|
|
602
|
+
plugins: _object_spread({}, options.plugins, cfg.showDataLabels === true && !isSingleValueMode && {
|
|
603
|
+
datalabels: {
|
|
604
|
+
display: function display(context) {
|
|
605
|
+
var _context_dataset_data, _context_dataset;
|
|
606
|
+
var value = (_context_dataset = context.dataset) === null || _context_dataset === void 0 ? void 0 : (_context_dataset_data = _context_dataset.data) === null || _context_dataset_data === void 0 ? void 0 : _context_dataset_data[context.dataIndex];
|
|
607
|
+
var numVal = typeof value === 'number' ? value : Number(value);
|
|
608
|
+
if (!Number.isFinite(numVal) || total <= 0) return false;
|
|
609
|
+
var pct = numVal / total * 100;
|
|
610
|
+
if (pct < 2) return false;
|
|
611
|
+
return true;
|
|
612
|
+
},
|
|
613
|
+
formatter: function formatter(value, context) {
|
|
614
|
+
var _context_chart_data_labels;
|
|
615
|
+
var pct = total > 0 ? (value / total * 100).toFixed(2) : '0';
|
|
616
|
+
var label = (_context_chart_data_labels = context.chart.data.labels) === null || _context_chart_data_labels === void 0 ? void 0 : _context_chart_data_labels[context.dataIndex];
|
|
617
|
+
var labelStr = label !== undefined && label !== null ? String(label) : '';
|
|
618
|
+
return labelStr ? "".concat(labelStr, ": ").concat(pct, "%") : "".concat(value, " (").concat(pct, "%)");
|
|
619
|
+
},
|
|
620
|
+
color: isDarkTheme ? '#fff' : '#343A45',
|
|
621
|
+
font: {
|
|
622
|
+
size: isMobile ? 10 : 11,
|
|
623
|
+
weight: 'normal'
|
|
624
|
+
},
|
|
625
|
+
anchor: 'end',
|
|
626
|
+
align: 'end',
|
|
627
|
+
offset: dataLabelOffset,
|
|
628
|
+
clamp: false,
|
|
629
|
+
clip: false
|
|
630
|
+
}
|
|
631
|
+
})
|
|
632
|
+
});
|
|
587
633
|
var _obj, _obj1;
|
|
588
634
|
return /*#__PURE__*/ React.createElement(ChartContainer, {
|
|
589
635
|
key: idx,
|
|
@@ -622,10 +668,16 @@ import { useStyle } from "./style";
|
|
|
622
668
|
chartRefs.current[idx] = instance;
|
|
623
669
|
},
|
|
624
670
|
data: chartJsData,
|
|
625
|
-
options:
|
|
671
|
+
options: optionsWithDataLabels,
|
|
672
|
+
plugins: cfg.showDataLabels === true && !isSingleValueMode ? [
|
|
673
|
+
createDataLabelsLeaderLinePlugin(dataLabelOffset),
|
|
674
|
+
ChartDataLabels
|
|
675
|
+
] : []
|
|
626
676
|
})), cfg.showLegend && /*#__PURE__*/ React.createElement(LegendView, {
|
|
627
677
|
chartData: chartData,
|
|
628
|
-
backgroundColors:
|
|
678
|
+
backgroundColors: chartData.map(function(_, i) {
|
|
679
|
+
return backgroundColors[i % backgroundColors.length];
|
|
680
|
+
}),
|
|
629
681
|
hiddenDataIndicesByChart: hiddenDataIndicesByChart,
|
|
630
682
|
chartIndex: idx,
|
|
631
683
|
onLegendItemClick: function onLegendItemClick(dataIndex) {
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import { Plugin } from 'chart.js';
|
|
2
|
+
/**
|
|
3
|
+
* 数据标签指示线插件:仅在会展示数据标签的扇区上绘制线(与 datalabels display 逻辑一致,避免无线无文案)。
|
|
4
|
+
* 传入的 lineLength 应与 options.plugins.datalabels.offset 一致。
|
|
5
|
+
*/
|
|
6
|
+
export declare const createDataLabelsLeaderLinePlugin: (lineLength?: number) => Plugin<'doughnut'>;
|
|
2
7
|
export declare const createCenterTextPlugin: (value: number, label: string, isMobile?: boolean) => Plugin<'doughnut'>;
|
|
3
8
|
export declare const createBackgroundArcPlugin: (bgColor?: string, padding?: number) => Plugin<'doughnut'>;
|
|
@@ -1,3 +1,51 @@
|
|
|
1
|
+
/** 指示线默认长度(像素),需与 datalabels 的 offset 一致,使线头与文案衔接 */ var DEFAULT_LEADER_LINE_PX = 4;
|
|
2
|
+
/** 曲线控制点偏移系数,使指示线呈柔和弧线 */ var CURVE_OFFSET = 12;
|
|
3
|
+
/** 与 datalabels 的 display 阈值一致:占比不超过此不展示标签,也不画指示线 */ var MIN_PCT_FOR_LABEL = 2;
|
|
4
|
+
/**
|
|
5
|
+
* 数据标签指示线插件:仅在会展示数据标签的扇区上绘制线(与 datalabels display 逻辑一致,避免无线无文案)。
|
|
6
|
+
* 传入的 lineLength 应与 options.plugins.datalabels.offset 一致。
|
|
7
|
+
*/ export var createDataLabelsLeaderLinePlugin = function createDataLabelsLeaderLinePlugin() {
|
|
8
|
+
var lineLength = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : DEFAULT_LEADER_LINE_PX;
|
|
9
|
+
return {
|
|
10
|
+
id: 'datalabelsLeaderLine',
|
|
11
|
+
afterDatasetDraw: function afterDatasetDraw(chart, args) {
|
|
12
|
+
var _chart_data_datasets, _meta_data;
|
|
13
|
+
var ctx = chart.ctx;
|
|
14
|
+
var meta = chart.getDatasetMeta(args.index);
|
|
15
|
+
var dataset = (_chart_data_datasets = chart.data.datasets) === null || _chart_data_datasets === void 0 ? void 0 : _chart_data_datasets[args.index];
|
|
16
|
+
var values = dataset === null || dataset === void 0 ? void 0 : dataset.data;
|
|
17
|
+
if (!(meta === null || meta === void 0 ? void 0 : (_meta_data = meta.data) === null || _meta_data === void 0 ? void 0 : _meta_data.length) || !(values === null || values === void 0 ? void 0 : values.length)) return;
|
|
18
|
+
var total = values.reduce(function(s, v) {
|
|
19
|
+
return s + (Number.isFinite(Number(v)) ? Number(v) : 0);
|
|
20
|
+
}, 0);
|
|
21
|
+
if (total <= 0) return;
|
|
22
|
+
ctx.save();
|
|
23
|
+
ctx.strokeStyle = 'rgba(0, 25, 61, 0.16)';
|
|
24
|
+
ctx.lineWidth = 1;
|
|
25
|
+
meta.data.forEach(function(element, i) {
|
|
26
|
+
var val = Number(values[i]);
|
|
27
|
+
if (!Number.isFinite(val) || val / total * 100 < MIN_PCT_FOR_LABEL) return;
|
|
28
|
+
var arc = element;
|
|
29
|
+
var angle = (arc.startAngle + arc.endAngle) / 2;
|
|
30
|
+
var cos = Math.cos(angle);
|
|
31
|
+
var sin = Math.sin(angle);
|
|
32
|
+
var x1 = arc.x + arc.outerRadius * cos;
|
|
33
|
+
var y1 = arc.y + arc.outerRadius * sin;
|
|
34
|
+
var x2 = arc.x + (arc.outerRadius + lineLength) * cos;
|
|
35
|
+
var y2 = arc.y + (arc.outerRadius + lineLength) * sin;
|
|
36
|
+
var midX = (x1 + x2) / 2;
|
|
37
|
+
var midY = (y1 + y2) / 2;
|
|
38
|
+
var ctrlX = midX + CURVE_OFFSET * -sin;
|
|
39
|
+
var ctrlY = midY + CURVE_OFFSET * cos;
|
|
40
|
+
ctx.beginPath();
|
|
41
|
+
ctx.moveTo(x1, y1);
|
|
42
|
+
ctx.quadraticCurveTo(ctrlX, ctrlY, x2, y2);
|
|
43
|
+
ctx.stroke();
|
|
44
|
+
});
|
|
45
|
+
ctx.restore();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
1
49
|
export var createCenterTextPlugin = function createCenterTextPlugin(value, label) {
|
|
2
50
|
var isMobile = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false;
|
|
3
51
|
return {
|
|
@@ -77,20 +77,24 @@ var genStyle = function genStyle(token) {
|
|
|
77
77
|
gap: 8,
|
|
78
78
|
marginBottom: 6
|
|
79
79
|
}),
|
|
80
|
-
'&-chart-wrapper': _define_property({
|
|
80
|
+
'&-chart-wrapper': _define_property({
|
|
81
|
+
overflow: 'visible'
|
|
82
|
+
}, "@media (max-width: 768px)", {
|
|
81
83
|
marginBottom: 12
|
|
82
84
|
}),
|
|
83
85
|
'&-row': _define_property({
|
|
84
86
|
display: 'flex',
|
|
85
87
|
alignItems: 'center',
|
|
86
|
-
flexDirection: 'row'
|
|
88
|
+
flexDirection: 'row',
|
|
89
|
+
overflow: 'visible'
|
|
87
90
|
}, "@media (max-width: 768px)", {
|
|
88
91
|
flexDirection: 'column',
|
|
89
92
|
alignItems: 'stretch'
|
|
90
93
|
}),
|
|
91
94
|
'&-chart': _define_property({
|
|
92
95
|
width: 'var(--donut-chart-width, 200px)',
|
|
93
|
-
height: 'var(--donut-chart-height, 200px)'
|
|
96
|
+
height: 'var(--donut-chart-height, 200px)',
|
|
97
|
+
overflow: 'visible'
|
|
94
98
|
}, "@media (max-width: 768px)", {
|
|
95
99
|
alignSelf: 'center',
|
|
96
100
|
marginBottom: 8
|
|
@@ -105,9 +109,7 @@ var genStyle = function genStyle(token) {
|
|
|
105
109
|
marginLeft: 12
|
|
106
110
|
}, "@media (max-width: 768px)", {
|
|
107
111
|
marginLeft: 0,
|
|
108
|
-
marginTop: 8
|
|
109
|
-
maxHeight: '120px',
|
|
110
|
-
overflowY: 'auto'
|
|
112
|
+
marginTop: 8
|
|
111
113
|
}),
|
|
112
114
|
'&-legend-item': _define_property({
|
|
113
115
|
display: 'flex',
|
|
@@ -168,6 +170,15 @@ var genStyle = function genStyle(token) {
|
|
|
168
170
|
fontSize: 10,
|
|
169
171
|
marginTop: 1
|
|
170
172
|
}),
|
|
173
|
+
'&-legend-pagination': {
|
|
174
|
+
display: 'flex',
|
|
175
|
+
alignItems: 'center',
|
|
176
|
+
justifyContent: 'center',
|
|
177
|
+
gap: 8,
|
|
178
|
+
marginTop: 8,
|
|
179
|
+
paddingTop: 8,
|
|
180
|
+
borderTop: '1px solid rgba(0,0,0,0.06)'
|
|
181
|
+
},
|
|
171
182
|
'&-statistic-container': {
|
|
172
183
|
display: 'flex',
|
|
173
184
|
gap: '16px',
|
|
@@ -19,6 +19,8 @@ export interface DonutChartConfig {
|
|
|
19
19
|
borderColor?: string;
|
|
20
20
|
/** 图表样式:'donut' 为环形图(默认),'pie' 为饼图 */
|
|
21
21
|
chartStyle?: 'donut' | 'pie';
|
|
22
|
+
/** 是否展示数据标签与指示线:开启后扇区外显示数值/占比及连接线,tooltip 中也会展示原始数值,默认 false */
|
|
23
|
+
showDataLabels?: boolean;
|
|
22
24
|
}
|
|
23
25
|
export interface DonutChartProps extends ChartContainerProps {
|
|
24
26
|
data: DonutChartData[];
|