@hsu-react/ui 0.0.8 → 0.0.10
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/es/components/Chart/Bar/index.d.ts +5 -1
- package/es/components/Chart/Bar/index.js +84 -9
- package/es/components/Chart/Line/index.d.ts +5 -1
- package/es/components/Chart/Line/index.js +84 -9
- package/es/components/Chart/_utils/autoSmooth.d.ts +2 -0
- package/es/components/Chart/_utils/autoSmooth.js +12 -2
- package/es/components/Chart/_utils/cartesian.d.ts +11 -0
- package/es/components/Chart/_utils/cartesian.js +19 -0
- package/es/components/Chart/chartUtils/chartTooltipFormatter.d.ts +2 -0
- package/es/components/Chart/chartUtils/chartTooltipFormatter.js +13 -3
- package/es/components/Chart/chartUtils/index.d.ts +5 -2
- package/es/components/Chart/chartUtils/index.js +3 -1
- package/es/components/Chart/chartUtils/useDataZoomWindow.d.ts +19 -0
- package/es/components/Chart/chartUtils/useDataZoomWindow.js +37 -0
- package/es/components/Chart/chartUtils/useLegendSelection.d.ts +14 -0
- package/es/components/Chart/chartUtils/useLegendSelection.js +35 -0
- package/es/components/FormItem/ItemContainer/index.d.ts +2 -0
- package/es/components/FormItem/ItemContainer/index.js +4 -15
- package/es/components/Modal/index.module.scss +1 -0
- package/es/components/Panel/ListPanel/ListModalPanel/index.js +33 -5
- package/es/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
- package/es/components/Panel/ListPanel/index.module.scss +11 -12
- package/es/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.d.ts +3 -3
- package/es/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.js +3 -3
- package/es/components/Search/SearchAdvanced/index.js +26 -148
- package/es/components/Search/SearchCard/index.js +1 -1
- package/es/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.js +2 -2
- package/es/components/Search/SearchCollapsible/index.js +17 -138
- package/es/components/Search/SearchWithFilter/index.js +4 -143
- package/es/components/Search/SearchWithMore/index.js +11 -142
- package/es/components/Search/_components/FilterDropdown/index.js +5 -6
- package/es/components/Search/_components/SearchBase/index.d.ts +32 -0
- package/es/components/Search/_components/SearchBase/index.js +185 -0
- package/es/components/Search/_hooks/useSearchCommon.js +5 -11
- package/es/components/Search/_hooks/useSearchExpand.js +4 -13
- package/es/components/Search/_utils/calculateButtonGroupAndColumnWidth.js +3 -10
- package/es/components/Search/_utils/calculateVisibleItems.js +4 -5
- package/es/components/Search/_utils/index.d.ts +2 -0
- package/es/components/Search/_utils/index.js +3 -1
- package/es/components/Search/_utils/measureButtonGroupWidth.d.ts +6 -0
- package/es/components/Search/_utils/measureButtonGroupWidth.js +18 -0
- package/es/components/Search/_utils/shouldDisplayExtraItem.d.ts +11 -0
- package/es/components/Search/_utils/shouldDisplayExtraItem.js +13 -0
- package/es/components/Search/index.d.ts +4 -0
- package/es/components/Search/index.js +6 -133
- package/es/components/Table/_hooks/useTableColumns.js +11 -0
- package/lib/components/Chart/Bar/index.d.ts +5 -1
- package/lib/components/Chart/Bar/index.js +68 -4
- package/lib/components/Chart/Line/index.d.ts +5 -1
- package/lib/components/Chart/Line/index.js +68 -4
- package/lib/components/Chart/_utils/autoSmooth.d.ts +2 -0
- package/lib/components/Chart/_utils/autoSmooth.js +11 -1
- package/lib/components/Chart/_utils/cartesian.d.ts +11 -0
- package/lib/components/Chart/_utils/cartesian.js +21 -1
- package/lib/components/Chart/chartUtils/chartTooltipFormatter.d.ts +2 -0
- package/lib/components/Chart/chartUtils/chartTooltipFormatter.js +5 -3
- package/lib/components/Chart/chartUtils/index.d.ts +5 -2
- package/lib/components/Chart/chartUtils/index.js +14 -0
- package/lib/components/Chart/chartUtils/useDataZoomWindow.d.ts +19 -0
- package/lib/components/Chart/chartUtils/useDataZoomWindow.js +31 -0
- package/lib/components/Chart/chartUtils/useLegendSelection.d.ts +14 -0
- package/lib/components/Chart/chartUtils/useLegendSelection.js +26 -0
- package/lib/components/FormItem/ItemContainer/index.d.ts +2 -0
- package/lib/components/FormItem/ItemContainer/index.js +2 -5
- package/lib/components/Modal/index.module.scss +1 -0
- package/lib/components/Panel/ListPanel/ListModalPanel/index.js +21 -2
- package/lib/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
- package/lib/components/Panel/ListPanel/index.module.scss +11 -12
- package/lib/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.d.ts +3 -3
- package/lib/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.js +3 -3
- package/lib/components/Search/SearchAdvanced/index.js +19 -134
- package/lib/components/Search/SearchCard/index.js +1 -1
- package/lib/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.js +2 -2
- package/lib/components/Search/SearchCollapsible/index.js +12 -124
- package/lib/components/Search/SearchWithFilter/index.js +5 -129
- package/lib/components/Search/SearchWithMore/index.js +7 -126
- package/lib/components/Search/_components/FilterDropdown/index.js +5 -6
- package/lib/components/Search/_components/SearchBase/index.d.ts +32 -0
- package/lib/components/Search/_components/SearchBase/index.js +169 -0
- package/lib/components/Search/_hooks/useSearchCommon.js +4 -6
- package/lib/components/Search/_hooks/useSearchExpand.js +2 -13
- package/lib/components/Search/_utils/calculateButtonGroupAndColumnWidth.js +2 -10
- package/lib/components/Search/_utils/calculateVisibleItems.js +3 -5
- package/lib/components/Search/_utils/index.d.ts +2 -0
- package/lib/components/Search/_utils/index.js +15 -1
- package/lib/components/Search/_utils/measureButtonGroupWidth.d.ts +6 -0
- package/lib/components/Search/_utils/measureButtonGroupWidth.js +24 -0
- package/lib/components/Search/_utils/shouldDisplayExtraItem.d.ts +11 -0
- package/lib/components/Search/_utils/shouldDisplayExtraItem.js +19 -0
- package/lib/components/Search/index.d.ts +4 -0
- package/lib/components/Search/index.js +8 -119
- package/lib/components/Table/_hooks/useTableColumns.js +11 -0
- package/package.json +1 -1
- package/src/components/Chart/Bar/index.tsx +132 -2
- package/src/components/Chart/Line/index.tsx +132 -2
- package/src/components/Chart/_utils/autoSmooth.ts +181 -164
- package/src/components/Chart/_utils/cartesian.ts +28 -0
- package/src/components/Chart/chartUtils/chartTooltipFormatter.ts +11 -2
- package/src/components/Chart/chartUtils/index.ts +53 -37
- package/src/components/Chart/chartUtils/useDataZoomWindow.ts +61 -0
- package/src/components/Chart/chartUtils/useLegendSelection.ts +35 -0
- package/src/components/FormItem/ItemContainer/index.tsx +4 -7
- package/src/components/Modal/index.module.scss +1 -0
- package/src/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
- package/src/components/Panel/ListPanel/ListModalPanel/index.tsx +261 -233
- package/src/components/Panel/ListPanel/index.module.scss +11 -12
- package/src/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.tsx +6 -6
- package/src/components/Search/SearchAdvanced/index.tsx +25 -164
- package/src/components/Search/SearchCard/index.tsx +1 -1
- package/src/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.tsx +2 -2
- package/src/components/Search/SearchCollapsible/index.tsx +13 -162
- package/src/components/Search/SearchWithFilter/index.tsx +2 -164
- package/src/components/Search/SearchWithMore/index.tsx +9 -161
- package/src/components/Search/_components/FilterDropdown/index.tsx +5 -6
- package/src/components/Search/_components/SearchBase/index.tsx +224 -0
- package/src/components/Search/_hooks/useSearchCommon.ts +10 -13
- package/src/components/Search/_hooks/useSearchExpand.ts +3 -13
- package/src/components/Search/_utils/calculateButtonGroupAndColumnWidth.ts +2 -10
- package/src/components/Search/_utils/calculateVisibleItems.ts +10 -11
- package/src/components/Search/_utils/index.ts +2 -0
- package/src/components/Search/_utils/measureButtonGroupWidth.ts +23 -0
- package/src/components/Search/_utils/shouldDisplayExtraItem.ts +23 -0
- package/src/components/Search/index.tsx +7 -153
- package/src/components/Table/_hooks/useTableColumns.tsx +17 -0
- /package/es/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.d.ts +0 -0
- /package/lib/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.d.ts +0 -0
|
@@ -4,137 +4,26 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var
|
|
8
|
-
var _FormItem = _interopRequireDefault(require("../FormItem"));
|
|
9
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
-
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
|
-
var _indexModule = _interopRequireDefault(require("./index.module.scss"));
|
|
12
|
-
var _hooks = require("./_hooks");
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
13
8
|
var _SearchCard = _interopRequireDefault(require("./SearchCard"));
|
|
14
9
|
var _SearchAdvanced = _interopRequireDefault(require("./SearchAdvanced"));
|
|
15
10
|
var _SearchCollapsible = _interopRequireDefault(require("./SearchCollapsible"));
|
|
16
11
|
var _SearchWithFilter = _interopRequireDefault(require("./SearchWithFilter"));
|
|
17
12
|
var _SearchWithMore = _interopRequireDefault(require("./SearchWithMore"));
|
|
18
|
-
var
|
|
19
|
-
var _SearchButtons = require("./_components/SearchButtons");
|
|
20
|
-
var _ExpandButton = require("./_components/ExpandButton");
|
|
13
|
+
var _SearchBase = _interopRequireDefault(require("./_components/SearchBase"));
|
|
21
14
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
22
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
23
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
24
15
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
16
|
// 导出所有可用的 Search 模式键名
|
|
26
17
|
|
|
27
18
|
// 导出 Search 模式映射类型
|
|
28
19
|
|
|
20
|
+
/**
|
|
21
|
+
* 基础 Search 组件
|
|
22
|
+
* - 标准的搜索表单布局,自适应列数与展开/收起
|
|
23
|
+
*/
|
|
29
24
|
const Search = props => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
moreSearchItems = [],
|
|
33
|
-
className,
|
|
34
|
-
onSearch,
|
|
35
|
-
onReset,
|
|
36
|
-
externalForm,
|
|
37
|
-
hasPermi,
|
|
38
|
-
columnNum = 4,
|
|
39
|
-
beforeButtonGroup,
|
|
40
|
-
affterButtonGroup,
|
|
41
|
-
searchData,
|
|
42
|
-
minLabelWidth,
|
|
43
|
-
defaultExpanded = false,
|
|
44
|
-
onExpandChange,
|
|
45
|
-
autoAdaptWidth = true,
|
|
46
|
-
baseWidth,
|
|
47
|
-
onValuesChange,
|
|
48
|
-
searchDisabled = false,
|
|
49
|
-
showAllSearchItems = false,
|
|
50
|
-
searchText,
|
|
51
|
-
resetText,
|
|
52
|
-
columnOffsetWidth = 0
|
|
53
|
-
} = props;
|
|
54
|
-
const [form] = _antd.Form.useForm(externalForm);
|
|
55
|
-
const {
|
|
56
|
-
containerRef,
|
|
57
|
-
buttonGroupRef,
|
|
58
|
-
cls,
|
|
59
|
-
getLabelWidth,
|
|
60
|
-
currentSearchItems,
|
|
61
|
-
totalColumnNum,
|
|
62
|
-
expand,
|
|
63
|
-
toggleExpand,
|
|
64
|
-
showExpandButton,
|
|
65
|
-
onSearchClick,
|
|
66
|
-
onResetClick,
|
|
67
|
-
shouldRender,
|
|
68
|
-
permitted
|
|
69
|
-
} = (0, _hooks.useSearchCommon)({
|
|
70
|
-
form,
|
|
71
|
-
searchItems,
|
|
72
|
-
moreSearchItems,
|
|
73
|
-
searchData,
|
|
74
|
-
hasPermi,
|
|
75
|
-
beforeButtonGroup,
|
|
76
|
-
affterButtonGroup,
|
|
77
|
-
columnNum,
|
|
78
|
-
autoAdaptWidth,
|
|
79
|
-
defaultExpanded,
|
|
80
|
-
onExpandChange,
|
|
81
|
-
showAllSearchItems,
|
|
82
|
-
minLabelWidth,
|
|
83
|
-
baseWidth,
|
|
84
|
-
onSearch,
|
|
85
|
-
onReset,
|
|
86
|
-
columnOffsetWidth
|
|
87
|
-
});
|
|
88
|
-
if (!shouldRender) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
92
|
-
ref: containerRef,
|
|
93
|
-
className: (0, _classnames.default)(_indexModule.default.Search, className),
|
|
94
|
-
style: {
|
|
95
|
-
"--column-number": totalColumnNum,
|
|
96
|
-
"--column-offset-width": `${columnOffsetWidth}px`
|
|
97
|
-
},
|
|
98
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
99
|
-
className: (0, _classnames.default)(_indexModule.default.searchOption, _indexModule.default[expand.toString()]),
|
|
100
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_antd.Form, {
|
|
101
|
-
form: form,
|
|
102
|
-
className: (0, _classnames.default)(_indexModule.default.option, cls),
|
|
103
|
-
onValuesChange: onValuesChange,
|
|
104
|
-
children: [permitted && currentSearchItems?.map((item, idx) => {
|
|
105
|
-
const visibleCurrentItems = currentSearchItems.filter(i => i.visible !== false);
|
|
106
|
-
const columnIndex = idx % totalColumnNum;
|
|
107
|
-
const sameColumnItems = visibleCurrentItems.filter((_, _idx) => _idx % totalColumnNum === columnIndex);
|
|
108
|
-
return /*#__PURE__*/(0, _react.createElement)(_FormItem.default, {
|
|
109
|
-
...item,
|
|
110
|
-
key: item.name,
|
|
111
|
-
className: (0, _classnames.default)(_indexModule.default.item, item.className, {
|
|
112
|
-
[_indexModule.default.unFill]: item.width !== undefined
|
|
113
|
-
}),
|
|
114
|
-
labelWidth: item.width !== undefined ? undefined : getLabelWidth(sameColumnItems, undefined, minLabelWidth)
|
|
115
|
-
});
|
|
116
|
-
}), (beforeButtonGroup?.length || affterButtonGroup?.length || permitted) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ButtonGroup.ButtonGroup, {
|
|
117
|
-
beforeButtonGroup: beforeButtonGroup,
|
|
118
|
-
affterButtonGroup: affterButtonGroup,
|
|
119
|
-
expandButton: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ExpandButton.ExpandButton, {
|
|
120
|
-
expand: expand,
|
|
121
|
-
toggleExpand: toggleExpand,
|
|
122
|
-
advancedFilters: false,
|
|
123
|
-
showExpandButton: showExpandButton,
|
|
124
|
-
showAllSearchItems: showAllSearchItems || !!moreSearchItems?.length
|
|
125
|
-
}),
|
|
126
|
-
permitted: permitted,
|
|
127
|
-
ref: buttonGroupRef,
|
|
128
|
-
children: currentSearchItems.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_SearchButtons.SearchButtons, {
|
|
129
|
-
onSearch: onSearchClick,
|
|
130
|
-
onReset: onResetClick,
|
|
131
|
-
searchDisabled: searchDisabled,
|
|
132
|
-
searchText: searchText,
|
|
133
|
-
resetText: resetText
|
|
134
|
-
})
|
|
135
|
-
})]
|
|
136
|
-
})
|
|
137
|
-
})
|
|
25
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SearchBase.default, {
|
|
26
|
+
...props
|
|
138
27
|
});
|
|
139
28
|
};
|
|
140
29
|
Search.Card = _SearchCard.default;
|
|
@@ -19,6 +19,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
19
19
|
const MEASURE_ALIGN_FONT_SIZE = 14;
|
|
20
20
|
// Canvas measureText 仅返回 advance width,较 DOM 实际渲染偏窄约 1px,补 2px 缓冲避免最宽行被挤压
|
|
21
21
|
const MEASURE_ALIGN_BUFFER_PX = 2;
|
|
22
|
+
// 单元格左右内边距合计(--td-padding: 4px 8px),用于把列宽抬到能放下定宽内容块
|
|
23
|
+
const MEASURE_ALIGN_CELL_PADDING_PX = 16;
|
|
22
24
|
|
|
23
25
|
// 计算 measureAlign 列的定宽(取本列所有行展示文本的最大像素宽)
|
|
24
26
|
const getMeasureAlignWidth = (column, dataSource) => {
|
|
@@ -109,6 +111,15 @@ const useTableColumns = params => {
|
|
|
109
111
|
}, 0) ?? 0 : 0;
|
|
110
112
|
item.width = Math.max(titleWidth, dataIndexWidth) + 32;
|
|
111
113
|
}
|
|
114
|
+
|
|
115
|
+
// measureAlign 列:列宽须容得下最宽行的定宽内容块 + 单元格左右内边距,
|
|
116
|
+
// 否则出现超长值(如 +3357.52%)时内容会被列宽截断;声明的 width 只作下限。
|
|
117
|
+
if (item.measureAlign && typeof item.width === "number") {
|
|
118
|
+
const measured = getMeasureAlignWidth(item, dataSource);
|
|
119
|
+
if (measured > 0) {
|
|
120
|
+
item.width = Math.max(item.width, measured + MEASURE_ALIGN_CELL_PADDING_PX);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
112
123
|
return item;
|
|
113
124
|
})?.map(item => {
|
|
114
125
|
return {
|
package/package.json
CHANGED
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
ChartScrollConfig,
|
|
17
17
|
createDefaultCategoryXAxis,
|
|
18
18
|
createDefaultValueYAxis,
|
|
19
|
+
DataZoomIndexWindow,
|
|
19
20
|
getSliderShow,
|
|
21
|
+
percentWindowToIndexWindow,
|
|
20
22
|
resolveScrollConfig,
|
|
21
23
|
} from "../_utils/cartesian";
|
|
22
24
|
|
|
@@ -27,6 +29,10 @@ export interface ChartBarProps extends ChartCommonProps {
|
|
|
27
29
|
legendData?: string[];
|
|
28
30
|
scrollConfig?: ChartScrollConfig;
|
|
29
31
|
onClick?: (event: echarts.ECElementEvent) => void;
|
|
32
|
+
/** 图例点选变化回调,参数为当前各系列选中状态(配合 legend.selected 可实现坐标轴重算) */
|
|
33
|
+
onLegendSelectChanged?: (selected: Record<string, boolean>) => void;
|
|
34
|
+
/** dataZoom 可见窗口变化回调(滑块/滚轮/自动滚动/初始同步均触发),参数为当前可见的 x 轴索引区间(配合 useDataZoomWindow 可按展示部分重算坐标轴) */
|
|
35
|
+
onDataZoomWindowChanged?: (window: DataZoomIndexWindow) => void;
|
|
30
36
|
/** 是否启用图例自动滚动,默认 false */
|
|
31
37
|
enableLegendAutoScroll?: boolean;
|
|
32
38
|
/** 图例每页可见数量,默认 8 */
|
|
@@ -55,6 +61,8 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
55
61
|
insideDataZoom,
|
|
56
62
|
sliderDataZoom,
|
|
57
63
|
onClick,
|
|
64
|
+
onLegendSelectChanged,
|
|
65
|
+
onDataZoomWindowChanged,
|
|
58
66
|
enableLegendAutoScroll = false,
|
|
59
67
|
legendVisibleCount = 8,
|
|
60
68
|
legendScrollInterval = 1500,
|
|
@@ -63,6 +71,7 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
63
71
|
const chartRef = useRef<HTMLDivElement>(null);
|
|
64
72
|
const chartInstanceRef = useRef<echarts.ECharts | null>(null);
|
|
65
73
|
const resizeObserverRef = useRef<ResizeObserver | null>(null);
|
|
74
|
+
const prevXAxisKeyRef = useRef<string | null>(null);
|
|
66
75
|
const legendScrollRef = useRef<ReturnType<typeof autoScrollLegend> | null>(
|
|
67
76
|
null,
|
|
68
77
|
);
|
|
@@ -268,8 +277,46 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
268
277
|
chartInstanceRef.current = chart;
|
|
269
278
|
}
|
|
270
279
|
|
|
271
|
-
//
|
|
280
|
+
// 设置配置:notMerge 会把 dataZoom 窗口重置回初始位置,
|
|
281
|
+
// x 轴数据未变化时(如坐标轴重算/图例点选触发的重渲染)先记录当前窗口,设置后恢复
|
|
282
|
+
const xAxisKey = xAxisData?.join("\u0001") ?? "";
|
|
283
|
+
const prevZoomRanges =
|
|
284
|
+
prevXAxisKeyRef.current === xAxisKey
|
|
285
|
+
? ((chart.getOption() as ChartsOption | undefined)?.dataZoom as
|
|
286
|
+
| Array<{ start?: number; end?: number }>
|
|
287
|
+
| undefined)
|
|
288
|
+
: undefined;
|
|
289
|
+
prevXAxisKeyRef.current = xAxisKey;
|
|
272
290
|
chart.setOption(chartOption as ChartOptionType, true);
|
|
291
|
+
const nextZooms = (chartOption as ChartsOption).dataZoom;
|
|
292
|
+
if (
|
|
293
|
+
prevZoomRanges?.length &&
|
|
294
|
+
Array.isArray(nextZooms) &&
|
|
295
|
+
nextZooms.length === prevZoomRanges.length
|
|
296
|
+
) {
|
|
297
|
+
chart.setOption({
|
|
298
|
+
dataZoom: prevZoomRanges.map((z) => ({ start: z.start, end: z.end })),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 向调用方同步当前可见窗口(初始渲染与恢复后),用于按展示部分重算坐标轴
|
|
303
|
+
if (onDataZoomWindowChanged) {
|
|
304
|
+
const zooms = (chart.getOption() as ChartsOption | undefined)
|
|
305
|
+
?.dataZoom as Array<{ start?: number; end?: number }> | undefined;
|
|
306
|
+
const zoom = zooms?.[0];
|
|
307
|
+
const totalLen = xAxisData?.length ?? 0;
|
|
308
|
+
if (typeof zoom?.start === "number" && typeof zoom?.end === "number") {
|
|
309
|
+
onDataZoomWindowChanged(
|
|
310
|
+
percentWindowToIndexWindow(zoom.start, zoom.end, totalLen),
|
|
311
|
+
);
|
|
312
|
+
} else {
|
|
313
|
+
// 无 dataZoom(如数据量不足未启用滚动)时窗口即全量,同步一次避免残留旧窗口
|
|
314
|
+
onDataZoomWindowChanged({
|
|
315
|
+
startIndex: 0,
|
|
316
|
+
endIndex: Math.max(0, totalLen - 1),
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
273
320
|
|
|
274
321
|
// 添加 resize 监听
|
|
275
322
|
window.addEventListener("resize", handleResize);
|
|
@@ -285,6 +332,59 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
285
332
|
chartInstanceRef.current?.on("click", onClick);
|
|
286
333
|
}
|
|
287
334
|
|
|
335
|
+
// 图例点选事件
|
|
336
|
+
const handleLegendSelectChanged = (params: unknown) => {
|
|
337
|
+
onLegendSelectChanged?.(
|
|
338
|
+
(params as { selected: Record<string, boolean> }).selected,
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
if (onLegendSelectChanged) {
|
|
342
|
+
chartInstanceRef.current?.on(
|
|
343
|
+
"legendselectchanged",
|
|
344
|
+
handleLegendSelectChanged,
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// dataZoom 原生交互(slider 拖动 / inside 缩放)→ 同步可见窗口
|
|
349
|
+
const handleDataZoom = (params: unknown) => {
|
|
350
|
+
const raw = params as {
|
|
351
|
+
start?: number;
|
|
352
|
+
end?: number;
|
|
353
|
+
startValue?: number;
|
|
354
|
+
endValue?: number;
|
|
355
|
+
batch?: Array<{
|
|
356
|
+
start?: number;
|
|
357
|
+
end?: number;
|
|
358
|
+
startValue?: number;
|
|
359
|
+
endValue?: number;
|
|
360
|
+
}>;
|
|
361
|
+
};
|
|
362
|
+
const info = raw?.batch?.[0] ?? raw;
|
|
363
|
+
if (
|
|
364
|
+
typeof info?.startValue === "number" &&
|
|
365
|
+
typeof info?.endValue === "number"
|
|
366
|
+
) {
|
|
367
|
+
onDataZoomWindowChanged?.({
|
|
368
|
+
startIndex: Math.max(0, Math.round(info.startValue)),
|
|
369
|
+
endIndex: Math.max(0, Math.round(info.endValue)),
|
|
370
|
+
});
|
|
371
|
+
} else if (
|
|
372
|
+
typeof info?.start === "number" &&
|
|
373
|
+
typeof info?.end === "number"
|
|
374
|
+
) {
|
|
375
|
+
onDataZoomWindowChanged?.(
|
|
376
|
+
percentWindowToIndexWindow(
|
|
377
|
+
info.start,
|
|
378
|
+
info.end,
|
|
379
|
+
xAxisData?.length ?? 0,
|
|
380
|
+
),
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
if (onDataZoomWindowChanged) {
|
|
385
|
+
chartInstanceRef.current?.on("datazoom", handleDataZoom);
|
|
386
|
+
}
|
|
387
|
+
|
|
288
388
|
// 图例自动滚动(参考 Pie 组件)
|
|
289
389
|
const opt = chartOption as ChartsOption;
|
|
290
390
|
const legendDataLen = Array.isArray(opt.legend)
|
|
@@ -317,6 +417,17 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
317
417
|
chartInstanceRef.current?.off("click", onClick);
|
|
318
418
|
}
|
|
319
419
|
|
|
420
|
+
if (onLegendSelectChanged) {
|
|
421
|
+
chartInstanceRef.current?.off(
|
|
422
|
+
"legendselectchanged",
|
|
423
|
+
handleLegendSelectChanged,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (onDataZoomWindowChanged) {
|
|
428
|
+
chartInstanceRef.current?.off("datazoom", handleDataZoom);
|
|
429
|
+
}
|
|
430
|
+
|
|
320
431
|
if (legendScrollRef.current) {
|
|
321
432
|
legendScrollRef.current.dispose();
|
|
322
433
|
legendScrollRef.current = null;
|
|
@@ -326,6 +437,9 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
326
437
|
chartOption,
|
|
327
438
|
handleResize,
|
|
328
439
|
onClick,
|
|
440
|
+
onLegendSelectChanged,
|
|
441
|
+
onDataZoomWindowChanged,
|
|
442
|
+
xAxisData,
|
|
329
443
|
enableLegendAutoScroll,
|
|
330
444
|
legendVisibleCount,
|
|
331
445
|
legendScrollInterval,
|
|
@@ -358,10 +472,26 @@ const ChartBar: React.FC<ChartBarProps> = (props) => {
|
|
|
358
472
|
startIndex: normalizedScroll.startIndex,
|
|
359
473
|
autoPlay: normalizedScroll.autoScroll,
|
|
360
474
|
enableWheelScroll,
|
|
475
|
+
onWindowChange: onDataZoomWindowChanged
|
|
476
|
+
? (startPercent, endPercent) =>
|
|
477
|
+
onDataZoomWindowChanged(
|
|
478
|
+
percentWindowToIndexWindow(
|
|
479
|
+
startPercent,
|
|
480
|
+
endPercent,
|
|
481
|
+
xAxisData.length,
|
|
482
|
+
),
|
|
483
|
+
)
|
|
484
|
+
: undefined,
|
|
361
485
|
});
|
|
362
486
|
|
|
363
487
|
return dispose;
|
|
364
|
-
}, [
|
|
488
|
+
}, [
|
|
489
|
+
dataZoom,
|
|
490
|
+
normalizedScroll,
|
|
491
|
+
sliderDataZoom,
|
|
492
|
+
xAxisData,
|
|
493
|
+
onDataZoomWindowChanged,
|
|
494
|
+
]);
|
|
365
495
|
|
|
366
496
|
// 组件卸载时清理资源
|
|
367
497
|
useEffect(() => {
|
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
ChartScrollConfig,
|
|
17
17
|
createDefaultCategoryXAxis,
|
|
18
18
|
createDefaultValueYAxis,
|
|
19
|
+
DataZoomIndexWindow,
|
|
19
20
|
getSliderShow,
|
|
21
|
+
percentWindowToIndexWindow,
|
|
20
22
|
resolveScrollConfig,
|
|
21
23
|
} from "../_utils/cartesian";
|
|
22
24
|
|
|
@@ -28,6 +30,10 @@ export interface ChartLineProps extends ChartCommonProps {
|
|
|
28
30
|
scrollConfig?: ChartScrollConfig;
|
|
29
31
|
yAxisNameOffsets?: number[];
|
|
30
32
|
onClick?: (event: echarts.ECElementEvent) => void;
|
|
33
|
+
/** 图例点选变化回调,参数为当前各系列选中状态(配合 legend.selected 可实现坐标轴重算) */
|
|
34
|
+
onLegendSelectChanged?: (selected: Record<string, boolean>) => void;
|
|
35
|
+
/** dataZoom 可见窗口变化回调(滑块/滚轮/自动滚动/初始同步均触发),参数为当前可见的 x 轴索引区间(配合 useDataZoomWindow 可按展示部分重算坐标轴) */
|
|
36
|
+
onDataZoomWindowChanged?: (window: DataZoomIndexWindow) => void;
|
|
31
37
|
/** 是否启用图例自动滚动,默认 false */
|
|
32
38
|
enableLegendAutoScroll?: boolean;
|
|
33
39
|
/** 图例每页可见数量,默认 8 */
|
|
@@ -56,6 +62,8 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
56
62
|
insideDataZoom,
|
|
57
63
|
sliderDataZoom,
|
|
58
64
|
onClick,
|
|
65
|
+
onLegendSelectChanged,
|
|
66
|
+
onDataZoomWindowChanged,
|
|
59
67
|
enableLegendAutoScroll = false,
|
|
60
68
|
legendVisibleCount = 8,
|
|
61
69
|
legendScrollInterval = 1500,
|
|
@@ -64,6 +72,7 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
64
72
|
const chartRef = useRef<HTMLDivElement>(null);
|
|
65
73
|
const chartInstanceRef = useRef<echarts.ECharts | null>(null);
|
|
66
74
|
const resizeObserverRef = useRef<ResizeObserver | null>(null);
|
|
75
|
+
const prevXAxisKeyRef = useRef<string | null>(null);
|
|
67
76
|
const legendScrollRef = useRef<ReturnType<typeof autoScrollLegend> | null>(
|
|
68
77
|
null,
|
|
69
78
|
);
|
|
@@ -265,8 +274,46 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
265
274
|
chartInstanceRef.current = chart;
|
|
266
275
|
}
|
|
267
276
|
|
|
268
|
-
//
|
|
277
|
+
// 设置配置:notMerge 会把 dataZoom 窗口重置回初始位置,
|
|
278
|
+
// x 轴数据未变化时(如坐标轴重算/图例点选触发的重渲染)先记录当前窗口,设置后恢复
|
|
279
|
+
const xAxisKey = xAxisData?.join("\u0001") ?? "";
|
|
280
|
+
const prevZoomRanges =
|
|
281
|
+
prevXAxisKeyRef.current === xAxisKey
|
|
282
|
+
? ((chart.getOption() as ChartsOption | undefined)?.dataZoom as
|
|
283
|
+
| Array<{ start?: number; end?: number }>
|
|
284
|
+
| undefined)
|
|
285
|
+
: undefined;
|
|
286
|
+
prevXAxisKeyRef.current = xAxisKey;
|
|
269
287
|
chart.setOption(chartOption as ChartOptionType, true);
|
|
288
|
+
const nextZooms = (chartOption as ChartsOption).dataZoom;
|
|
289
|
+
if (
|
|
290
|
+
prevZoomRanges?.length &&
|
|
291
|
+
Array.isArray(nextZooms) &&
|
|
292
|
+
nextZooms.length === prevZoomRanges.length
|
|
293
|
+
) {
|
|
294
|
+
chart.setOption({
|
|
295
|
+
dataZoom: prevZoomRanges.map((z) => ({ start: z.start, end: z.end })),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// 向调用方同步当前可见窗口(初始渲染与恢复后),用于按展示部分重算坐标轴
|
|
300
|
+
if (onDataZoomWindowChanged) {
|
|
301
|
+
const zooms = (chart.getOption() as ChartsOption | undefined)
|
|
302
|
+
?.dataZoom as Array<{ start?: number; end?: number }> | undefined;
|
|
303
|
+
const zoom = zooms?.[0];
|
|
304
|
+
const totalLen = xAxisData?.length ?? 0;
|
|
305
|
+
if (typeof zoom?.start === "number" && typeof zoom?.end === "number") {
|
|
306
|
+
onDataZoomWindowChanged(
|
|
307
|
+
percentWindowToIndexWindow(zoom.start, zoom.end, totalLen),
|
|
308
|
+
);
|
|
309
|
+
} else {
|
|
310
|
+
// 无 dataZoom(如数据量不足未启用滚动)时窗口即全量,同步一次避免残留旧窗口
|
|
311
|
+
onDataZoomWindowChanged({
|
|
312
|
+
startIndex: 0,
|
|
313
|
+
endIndex: Math.max(0, totalLen - 1),
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
270
317
|
|
|
271
318
|
// 添加 resize 监听
|
|
272
319
|
window.addEventListener("resize", handleResize);
|
|
@@ -282,6 +329,59 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
282
329
|
chartInstanceRef.current?.on("click", onClick);
|
|
283
330
|
}
|
|
284
331
|
|
|
332
|
+
// 图例点选事件
|
|
333
|
+
const handleLegendSelectChanged = (params: unknown) => {
|
|
334
|
+
onLegendSelectChanged?.(
|
|
335
|
+
(params as { selected: Record<string, boolean> }).selected,
|
|
336
|
+
);
|
|
337
|
+
};
|
|
338
|
+
if (onLegendSelectChanged) {
|
|
339
|
+
chartInstanceRef.current?.on(
|
|
340
|
+
"legendselectchanged",
|
|
341
|
+
handleLegendSelectChanged,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// dataZoom 原生交互(slider 拖动 / inside 缩放)→ 同步可见窗口
|
|
346
|
+
const handleDataZoom = (params: unknown) => {
|
|
347
|
+
const raw = params as {
|
|
348
|
+
start?: number;
|
|
349
|
+
end?: number;
|
|
350
|
+
startValue?: number;
|
|
351
|
+
endValue?: number;
|
|
352
|
+
batch?: Array<{
|
|
353
|
+
start?: number;
|
|
354
|
+
end?: number;
|
|
355
|
+
startValue?: number;
|
|
356
|
+
endValue?: number;
|
|
357
|
+
}>;
|
|
358
|
+
};
|
|
359
|
+
const info = raw?.batch?.[0] ?? raw;
|
|
360
|
+
if (
|
|
361
|
+
typeof info?.startValue === "number" &&
|
|
362
|
+
typeof info?.endValue === "number"
|
|
363
|
+
) {
|
|
364
|
+
onDataZoomWindowChanged?.({
|
|
365
|
+
startIndex: Math.max(0, Math.round(info.startValue)),
|
|
366
|
+
endIndex: Math.max(0, Math.round(info.endValue)),
|
|
367
|
+
});
|
|
368
|
+
} else if (
|
|
369
|
+
typeof info?.start === "number" &&
|
|
370
|
+
typeof info?.end === "number"
|
|
371
|
+
) {
|
|
372
|
+
onDataZoomWindowChanged?.(
|
|
373
|
+
percentWindowToIndexWindow(
|
|
374
|
+
info.start,
|
|
375
|
+
info.end,
|
|
376
|
+
xAxisData?.length ?? 0,
|
|
377
|
+
),
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
if (onDataZoomWindowChanged) {
|
|
382
|
+
chartInstanceRef.current?.on("datazoom", handleDataZoom);
|
|
383
|
+
}
|
|
384
|
+
|
|
285
385
|
// 图例自动滚动(与 Pie/Bar 一致)
|
|
286
386
|
const opt = chartOption as ChartsOption;
|
|
287
387
|
const legendDataLen = Array.isArray(opt.legend)
|
|
@@ -314,6 +414,17 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
314
414
|
chartInstanceRef.current?.off("click", onClick);
|
|
315
415
|
}
|
|
316
416
|
|
|
417
|
+
if (onLegendSelectChanged) {
|
|
418
|
+
chartInstanceRef.current?.off(
|
|
419
|
+
"legendselectchanged",
|
|
420
|
+
handleLegendSelectChanged,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (onDataZoomWindowChanged) {
|
|
425
|
+
chartInstanceRef.current?.off("datazoom", handleDataZoom);
|
|
426
|
+
}
|
|
427
|
+
|
|
317
428
|
if (legendScrollRef.current) {
|
|
318
429
|
legendScrollRef.current.dispose();
|
|
319
430
|
legendScrollRef.current = null;
|
|
@@ -323,6 +434,9 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
323
434
|
chartOption,
|
|
324
435
|
handleResize,
|
|
325
436
|
onClick,
|
|
437
|
+
onLegendSelectChanged,
|
|
438
|
+
onDataZoomWindowChanged,
|
|
439
|
+
xAxisData,
|
|
326
440
|
enableLegendAutoScroll,
|
|
327
441
|
legendVisibleCount,
|
|
328
442
|
legendScrollInterval,
|
|
@@ -355,10 +469,26 @@ const ChartLine: React.FC<ChartLineProps> = (props) => {
|
|
|
355
469
|
startIndex: normalizedScroll.startIndex,
|
|
356
470
|
autoPlay: normalizedScroll.autoScroll,
|
|
357
471
|
enableWheelScroll,
|
|
472
|
+
onWindowChange: onDataZoomWindowChanged
|
|
473
|
+
? (startPercent, endPercent) =>
|
|
474
|
+
onDataZoomWindowChanged(
|
|
475
|
+
percentWindowToIndexWindow(
|
|
476
|
+
startPercent,
|
|
477
|
+
endPercent,
|
|
478
|
+
xAxisData.length,
|
|
479
|
+
),
|
|
480
|
+
)
|
|
481
|
+
: undefined,
|
|
358
482
|
});
|
|
359
483
|
|
|
360
484
|
return dispose;
|
|
361
|
-
}, [
|
|
485
|
+
}, [
|
|
486
|
+
dataZoom,
|
|
487
|
+
normalizedScroll,
|
|
488
|
+
sliderDataZoom,
|
|
489
|
+
xAxisData,
|
|
490
|
+
onDataZoomWindowChanged,
|
|
491
|
+
]);
|
|
362
492
|
|
|
363
493
|
// 组件卸载时清理资源
|
|
364
494
|
useEffect(() => {
|