@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.
Files changed (126) hide show
  1. package/es/components/Chart/Bar/index.d.ts +5 -1
  2. package/es/components/Chart/Bar/index.js +84 -9
  3. package/es/components/Chart/Line/index.d.ts +5 -1
  4. package/es/components/Chart/Line/index.js +84 -9
  5. package/es/components/Chart/_utils/autoSmooth.d.ts +2 -0
  6. package/es/components/Chart/_utils/autoSmooth.js +12 -2
  7. package/es/components/Chart/_utils/cartesian.d.ts +11 -0
  8. package/es/components/Chart/_utils/cartesian.js +19 -0
  9. package/es/components/Chart/chartUtils/chartTooltipFormatter.d.ts +2 -0
  10. package/es/components/Chart/chartUtils/chartTooltipFormatter.js +13 -3
  11. package/es/components/Chart/chartUtils/index.d.ts +5 -2
  12. package/es/components/Chart/chartUtils/index.js +3 -1
  13. package/es/components/Chart/chartUtils/useDataZoomWindow.d.ts +19 -0
  14. package/es/components/Chart/chartUtils/useDataZoomWindow.js +37 -0
  15. package/es/components/Chart/chartUtils/useLegendSelection.d.ts +14 -0
  16. package/es/components/Chart/chartUtils/useLegendSelection.js +35 -0
  17. package/es/components/FormItem/ItemContainer/index.d.ts +2 -0
  18. package/es/components/FormItem/ItemContainer/index.js +4 -15
  19. package/es/components/Modal/index.module.scss +1 -0
  20. package/es/components/Panel/ListPanel/ListModalPanel/index.js +33 -5
  21. package/es/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
  22. package/es/components/Panel/ListPanel/index.module.scss +11 -12
  23. package/es/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.d.ts +3 -3
  24. package/es/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.js +3 -3
  25. package/es/components/Search/SearchAdvanced/index.js +26 -148
  26. package/es/components/Search/SearchCard/index.js +1 -1
  27. package/es/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.js +2 -2
  28. package/es/components/Search/SearchCollapsible/index.js +17 -138
  29. package/es/components/Search/SearchWithFilter/index.js +4 -143
  30. package/es/components/Search/SearchWithMore/index.js +11 -142
  31. package/es/components/Search/_components/FilterDropdown/index.js +5 -6
  32. package/es/components/Search/_components/SearchBase/index.d.ts +32 -0
  33. package/es/components/Search/_components/SearchBase/index.js +185 -0
  34. package/es/components/Search/_hooks/useSearchCommon.js +5 -11
  35. package/es/components/Search/_hooks/useSearchExpand.js +4 -13
  36. package/es/components/Search/_utils/calculateButtonGroupAndColumnWidth.js +3 -10
  37. package/es/components/Search/_utils/calculateVisibleItems.js +4 -5
  38. package/es/components/Search/_utils/index.d.ts +2 -0
  39. package/es/components/Search/_utils/index.js +3 -1
  40. package/es/components/Search/_utils/measureButtonGroupWidth.d.ts +6 -0
  41. package/es/components/Search/_utils/measureButtonGroupWidth.js +18 -0
  42. package/es/components/Search/_utils/shouldDisplayExtraItem.d.ts +11 -0
  43. package/es/components/Search/_utils/shouldDisplayExtraItem.js +13 -0
  44. package/es/components/Search/index.d.ts +4 -0
  45. package/es/components/Search/index.js +6 -133
  46. package/es/components/Table/_hooks/useTableColumns.js +11 -0
  47. package/lib/components/Chart/Bar/index.d.ts +5 -1
  48. package/lib/components/Chart/Bar/index.js +68 -4
  49. package/lib/components/Chart/Line/index.d.ts +5 -1
  50. package/lib/components/Chart/Line/index.js +68 -4
  51. package/lib/components/Chart/_utils/autoSmooth.d.ts +2 -0
  52. package/lib/components/Chart/_utils/autoSmooth.js +11 -1
  53. package/lib/components/Chart/_utils/cartesian.d.ts +11 -0
  54. package/lib/components/Chart/_utils/cartesian.js +21 -1
  55. package/lib/components/Chart/chartUtils/chartTooltipFormatter.d.ts +2 -0
  56. package/lib/components/Chart/chartUtils/chartTooltipFormatter.js +5 -3
  57. package/lib/components/Chart/chartUtils/index.d.ts +5 -2
  58. package/lib/components/Chart/chartUtils/index.js +14 -0
  59. package/lib/components/Chart/chartUtils/useDataZoomWindow.d.ts +19 -0
  60. package/lib/components/Chart/chartUtils/useDataZoomWindow.js +31 -0
  61. package/lib/components/Chart/chartUtils/useLegendSelection.d.ts +14 -0
  62. package/lib/components/Chart/chartUtils/useLegendSelection.js +26 -0
  63. package/lib/components/FormItem/ItemContainer/index.d.ts +2 -0
  64. package/lib/components/FormItem/ItemContainer/index.js +2 -5
  65. package/lib/components/Modal/index.module.scss +1 -0
  66. package/lib/components/Panel/ListPanel/ListModalPanel/index.js +21 -2
  67. package/lib/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
  68. package/lib/components/Panel/ListPanel/index.module.scss +11 -12
  69. package/lib/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.d.ts +3 -3
  70. package/lib/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.js +3 -3
  71. package/lib/components/Search/SearchAdvanced/index.js +19 -134
  72. package/lib/components/Search/SearchCard/index.js +1 -1
  73. package/lib/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.js +2 -2
  74. package/lib/components/Search/SearchCollapsible/index.js +12 -124
  75. package/lib/components/Search/SearchWithFilter/index.js +5 -129
  76. package/lib/components/Search/SearchWithMore/index.js +7 -126
  77. package/lib/components/Search/_components/FilterDropdown/index.js +5 -6
  78. package/lib/components/Search/_components/SearchBase/index.d.ts +32 -0
  79. package/lib/components/Search/_components/SearchBase/index.js +169 -0
  80. package/lib/components/Search/_hooks/useSearchCommon.js +4 -6
  81. package/lib/components/Search/_hooks/useSearchExpand.js +2 -13
  82. package/lib/components/Search/_utils/calculateButtonGroupAndColumnWidth.js +2 -10
  83. package/lib/components/Search/_utils/calculateVisibleItems.js +3 -5
  84. package/lib/components/Search/_utils/index.d.ts +2 -0
  85. package/lib/components/Search/_utils/index.js +15 -1
  86. package/lib/components/Search/_utils/measureButtonGroupWidth.d.ts +6 -0
  87. package/lib/components/Search/_utils/measureButtonGroupWidth.js +24 -0
  88. package/lib/components/Search/_utils/shouldDisplayExtraItem.d.ts +11 -0
  89. package/lib/components/Search/_utils/shouldDisplayExtraItem.js +19 -0
  90. package/lib/components/Search/index.d.ts +4 -0
  91. package/lib/components/Search/index.js +8 -119
  92. package/lib/components/Table/_hooks/useTableColumns.js +11 -0
  93. package/package.json +1 -1
  94. package/src/components/Chart/Bar/index.tsx +132 -2
  95. package/src/components/Chart/Line/index.tsx +132 -2
  96. package/src/components/Chart/_utils/autoSmooth.ts +181 -164
  97. package/src/components/Chart/_utils/cartesian.ts +28 -0
  98. package/src/components/Chart/chartUtils/chartTooltipFormatter.ts +11 -2
  99. package/src/components/Chart/chartUtils/index.ts +53 -37
  100. package/src/components/Chart/chartUtils/useDataZoomWindow.ts +61 -0
  101. package/src/components/Chart/chartUtils/useLegendSelection.ts +35 -0
  102. package/src/components/FormItem/ItemContainer/index.tsx +4 -7
  103. package/src/components/Modal/index.module.scss +1 -0
  104. package/src/components/Panel/ListPanel/ListModalPanel/index.module.scss +17 -2
  105. package/src/components/Panel/ListPanel/ListModalPanel/index.tsx +261 -233
  106. package/src/components/Panel/ListPanel/index.module.scss +11 -12
  107. package/src/components/Search/{_components → SearchAdvanced/_components}/AdvancedFiltersDrawer/index.tsx +6 -6
  108. package/src/components/Search/SearchAdvanced/index.tsx +25 -164
  109. package/src/components/Search/SearchCard/index.tsx +1 -1
  110. package/src/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.tsx +2 -2
  111. package/src/components/Search/SearchCollapsible/index.tsx +13 -162
  112. package/src/components/Search/SearchWithFilter/index.tsx +2 -164
  113. package/src/components/Search/SearchWithMore/index.tsx +9 -161
  114. package/src/components/Search/_components/FilterDropdown/index.tsx +5 -6
  115. package/src/components/Search/_components/SearchBase/index.tsx +224 -0
  116. package/src/components/Search/_hooks/useSearchCommon.ts +10 -13
  117. package/src/components/Search/_hooks/useSearchExpand.ts +3 -13
  118. package/src/components/Search/_utils/calculateButtonGroupAndColumnWidth.ts +2 -10
  119. package/src/components/Search/_utils/calculateVisibleItems.ts +10 -11
  120. package/src/components/Search/_utils/index.ts +2 -0
  121. package/src/components/Search/_utils/measureButtonGroupWidth.ts +23 -0
  122. package/src/components/Search/_utils/shouldDisplayExtraItem.ts +23 -0
  123. package/src/components/Search/index.tsx +7 -153
  124. package/src/components/Table/_hooks/useTableColumns.tsx +17 -0
  125. /package/es/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.d.ts +0 -0
  126. /package/lib/components/Search/{_components → SearchCollapsible/_components}/CollapseToggle/index.d.ts +0 -0
@@ -1,164 +1,181 @@
1
- import * as echarts from "echarts";
2
-
3
- export interface AutoScrollByItemProps {
4
- chart: echarts.ECharts;
5
- xAxisData?: Array<string>;
6
- windowSize?: number;
7
- interval?: number;
8
- startIndex?: number;
9
- autoPlay?: boolean;
10
- enableWheelScroll?: boolean;
11
- }
12
-
13
- export function autoScrollByItem(props: AutoScrollByItemProps) {
14
- const {
15
- chart,
16
- xAxisData,
17
- windowSize = 10,
18
- interval = 2000,
19
- startIndex = 0,
20
- autoPlay = true,
21
- enableWheelScroll = true,
22
- } = props;
23
- const total = xAxisData?.length ?? 0;
24
- if (total <= 0) {
25
- return {
26
- pause: () => {},
27
- resume: () => {},
28
- dispose: () => {},
29
- };
30
- }
31
-
32
- const initialStartIndex = Math.max(
33
- 0,
34
- Math.min(startIndex, Math.max(total - 1, 0)),
35
- );
36
- const stepPercent = total > 0 ? (1 / total) * 100 : 0;
37
- const windowSizePercent = total > 0 ? (windowSize / total) * 100 : 100;
38
- const initialStartPercent = total > 0 ? (initialStartIndex / total) * 100 : 0;
39
- let start = initialStartPercent;
40
- let end = Math.min(initialStartPercent + windowSizePercent, 100);
41
-
42
- const syncDataZoomRange = () => {
43
- const option = chart.getOption() as {
44
- dataZoom?: Array<Record<string, unknown>>;
45
- };
46
- const currentDataZoom = option?.dataZoom;
47
- if (!currentDataZoom?.length) return;
48
- chart.setOption({
49
- dataZoom: currentDataZoom.map((dz) => ({
50
- ...dz,
51
- start,
52
- end,
53
- })),
54
- });
55
- };
56
-
57
- syncDataZoomRange();
58
-
59
- let timer: NodeJS.Timeout | null = null;
60
- if (autoPlay) {
61
- timer = setInterval(tick, interval);
62
- }
63
-
64
- function tick() {
65
- start += stepPercent;
66
- end += stepPercent;
67
-
68
- if (end > 100) {
69
- start = 0;
70
- end = windowSizePercent;
71
- }
72
-
73
- syncDataZoomRange();
74
- }
75
-
76
- if (autoPlay) {
77
- chart.getZr().on("mouseover", pause);
78
- chart.getZr().on("mouseout", resume);
79
- }
80
-
81
- function pause() {
82
- if (timer) {
83
- clearInterval(timer);
84
- timer = null;
85
- }
86
- }
87
- function resume() {
88
- if (autoPlay && !timer) {
89
- timer = setInterval(tick, interval);
90
- }
91
- }
92
-
93
- const chartDom = chart.getDom();
94
- const applyWheelDelta = (delta: number) => {
95
- if (delta === 0) return;
96
- const direction = delta > 0 ? 1 : -1;
97
-
98
- start += direction * stepPercent;
99
- end += direction * stepPercent;
100
-
101
- if (start < 0) {
102
- start = 0;
103
- end = windowSizePercent;
104
- }
105
- if (end > 100) {
106
- end = 100;
107
- start = Math.max(0, 100 - windowSizePercent);
108
- }
109
-
110
- syncDataZoomRange();
111
- };
112
-
113
- function handleWheel(event: Event) {
114
- if (!enableWheelScroll) return;
115
- const wheelEvent = event as WheelEvent;
116
- wheelEvent.preventDefault();
117
- applyWheelDelta(wheelEvent.deltaY);
118
- }
119
-
120
- function handleZrMouseWheel(params: unknown) {
121
- if (!enableWheelScroll) return;
122
- const eventLike = (params as { event?: Record<string, unknown> })?.event;
123
- const nativeEvent = eventLike?.event as WheelEvent | undefined;
124
- const deltaFromNative = nativeEvent?.deltaY;
125
- const deltaFromEventLike =
126
- (eventLike?.deltaY as number | undefined) ??
127
- (eventLike?.zrDelta as number | undefined);
128
- const wheelDelta = eventLike?.wheelDelta as number | undefined;
129
- const resolvedDelta =
130
- deltaFromNative ??
131
- deltaFromEventLike ??
132
- (typeof wheelDelta === "number" ? -wheelDelta : undefined);
133
-
134
- if (typeof resolvedDelta !== "number") return;
135
- nativeEvent?.preventDefault();
136
- applyWheelDelta(resolvedDelta);
137
- }
138
-
139
- if (enableWheelScroll) {
140
- chartDom.addEventListener("wheel", handleWheel, { passive: false });
141
- chart.getZr().on("mousewheel", handleZrMouseWheel);
142
- }
143
-
144
- const handleWindowResize = () => {
145
- chart.resize();
146
- syncDataZoomRange();
147
- };
148
- window.addEventListener("resize", handleWindowResize);
149
-
150
- function dispose() {
151
- pause();
152
- if (autoPlay) {
153
- chart.getZr().off("mouseover", pause);
154
- chart.getZr().off("mouseout", resume);
155
- }
156
- if (enableWheelScroll) {
157
- chartDom.removeEventListener("wheel", handleWheel);
158
- chart.getZr().off("mousewheel", handleZrMouseWheel);
159
- }
160
- window.removeEventListener("resize", handleWindowResize);
161
- }
162
-
163
- return { pause, resume, dispose };
164
- }
1
+ import * as echarts from "echarts";
2
+
3
+ export interface AutoScrollByItemProps {
4
+ chart: echarts.ECharts;
5
+ xAxisData?: Array<string>;
6
+ windowSize?: number;
7
+ interval?: number;
8
+ startIndex?: number;
9
+ autoPlay?: boolean;
10
+ enableWheelScroll?: boolean;
11
+ /** 窗口变化回调(创建同步、自动滚动、滚轮、resize 均触发),参数为当前窗口 start/end 百分比 */
12
+ onWindowChange?: (startPercent: number, endPercent: number) => void;
13
+ }
14
+
15
+ export function autoScrollByItem(props: AutoScrollByItemProps) {
16
+ const {
17
+ chart,
18
+ xAxisData,
19
+ windowSize = 10,
20
+ interval = 2000,
21
+ startIndex = 0,
22
+ autoPlay = true,
23
+ enableWheelScroll = true,
24
+ onWindowChange,
25
+ } = props;
26
+ const total = xAxisData?.length ?? 0;
27
+ if (total <= 0) {
28
+ return {
29
+ pause: () => {},
30
+ resume: () => {},
31
+ dispose: () => {},
32
+ };
33
+ }
34
+
35
+ const initialStartIndex = Math.max(
36
+ 0,
37
+ Math.min(startIndex, Math.max(total - 1, 0)),
38
+ );
39
+ const stepPercent = total > 0 ? (1 / total) * 100 : 0;
40
+ const windowSizePercent = total > 0 ? (windowSize / total) * 100 : 100;
41
+ const initialStartPercent = total > 0 ? (initialStartIndex / total) * 100 : 0;
42
+ let start = initialStartPercent;
43
+ let end = Math.min(initialStartPercent + windowSizePercent, 100);
44
+
45
+ // 图表已有 dataZoom 窗口时(组件重渲染重建滚动器)从当前位置继续,
46
+ // 避免图例点选、坐标轴重算等触发的重渲染把已滚动位置重置回初始窗口
47
+ const currentZoom = (
48
+ chart.getOption() as { dataZoom?: Array<{ start?: number; end?: number }> }
49
+ )?.dataZoom?.[0];
50
+ if (
51
+ typeof currentZoom?.start === "number" &&
52
+ typeof currentZoom?.end === "number"
53
+ ) {
54
+ start = currentZoom.start;
55
+ end = currentZoom.end;
56
+ }
57
+
58
+ const syncDataZoomRange = () => {
59
+ const option = chart.getOption() as {
60
+ dataZoom?: Array<Record<string, unknown>>;
61
+ };
62
+ const currentDataZoom = option?.dataZoom;
63
+ if (!currentDataZoom?.length) return;
64
+ chart.setOption({
65
+ dataZoom: currentDataZoom.map((dz) => ({
66
+ ...dz,
67
+ start,
68
+ end,
69
+ })),
70
+ });
71
+ onWindowChange?.(start, end);
72
+ };
73
+
74
+ syncDataZoomRange();
75
+
76
+ let timer: NodeJS.Timeout | null = null;
77
+ if (autoPlay) {
78
+ timer = setInterval(tick, interval);
79
+ }
80
+
81
+ function tick() {
82
+ start += stepPercent;
83
+ end += stepPercent;
84
+
85
+ if (end > 100) {
86
+ start = 0;
87
+ end = windowSizePercent;
88
+ }
89
+
90
+ syncDataZoomRange();
91
+ }
92
+
93
+ if (autoPlay) {
94
+ chart.getZr().on("mouseover", pause);
95
+ chart.getZr().on("mouseout", resume);
96
+ }
97
+
98
+ function pause() {
99
+ if (timer) {
100
+ clearInterval(timer);
101
+ timer = null;
102
+ }
103
+ }
104
+ function resume() {
105
+ if (autoPlay && !timer) {
106
+ timer = setInterval(tick, interval);
107
+ }
108
+ }
109
+
110
+ const chartDom = chart.getDom();
111
+ const applyWheelDelta = (delta: number) => {
112
+ if (delta === 0) return;
113
+ const direction = delta > 0 ? 1 : -1;
114
+
115
+ start += direction * stepPercent;
116
+ end += direction * stepPercent;
117
+
118
+ if (start < 0) {
119
+ start = 0;
120
+ end = windowSizePercent;
121
+ }
122
+ if (end > 100) {
123
+ end = 100;
124
+ start = Math.max(0, 100 - windowSizePercent);
125
+ }
126
+
127
+ syncDataZoomRange();
128
+ };
129
+
130
+ function handleWheel(event: Event) {
131
+ if (!enableWheelScroll) return;
132
+ const wheelEvent = event as WheelEvent;
133
+ wheelEvent.preventDefault();
134
+ applyWheelDelta(wheelEvent.deltaY);
135
+ }
136
+
137
+ function handleZrMouseWheel(params: unknown) {
138
+ if (!enableWheelScroll) return;
139
+ const eventLike = (params as { event?: Record<string, unknown> })?.event;
140
+ const nativeEvent = eventLike?.event as WheelEvent | undefined;
141
+ const deltaFromNative = nativeEvent?.deltaY;
142
+ const deltaFromEventLike =
143
+ (eventLike?.deltaY as number | undefined) ??
144
+ (eventLike?.zrDelta as number | undefined);
145
+ const wheelDelta = eventLike?.wheelDelta as number | undefined;
146
+ const resolvedDelta =
147
+ deltaFromNative ??
148
+ deltaFromEventLike ??
149
+ (typeof wheelDelta === "number" ? -wheelDelta : undefined);
150
+
151
+ if (typeof resolvedDelta !== "number") return;
152
+ nativeEvent?.preventDefault();
153
+ applyWheelDelta(resolvedDelta);
154
+ }
155
+
156
+ if (enableWheelScroll) {
157
+ chartDom.addEventListener("wheel", handleWheel, { passive: false });
158
+ chart.getZr().on("mousewheel", handleZrMouseWheel);
159
+ }
160
+
161
+ const handleWindowResize = () => {
162
+ chart.resize();
163
+ syncDataZoomRange();
164
+ };
165
+ window.addEventListener("resize", handleWindowResize);
166
+
167
+ function dispose() {
168
+ pause();
169
+ if (autoPlay) {
170
+ chart.getZr().off("mouseover", pause);
171
+ chart.getZr().off("mouseout", resume);
172
+ }
173
+ if (enableWheelScroll) {
174
+ chartDom.removeEventListener("wheel", handleWheel);
175
+ chart.getZr().off("mousewheel", handleZrMouseWheel);
176
+ }
177
+ window.removeEventListener("resize", handleWindowResize);
178
+ }
179
+
180
+ return { pause, resume, dispose };
181
+ }
@@ -21,6 +21,34 @@ export interface NormalizedScrollConfig {
21
21
  wheelModeWhenSliderHidden: "scroll" | "none";
22
22
  }
23
23
 
24
+ /** dataZoom 当前可见窗口对应的 x 轴索引区间(闭区间) */
25
+ export interface DataZoomIndexWindow {
26
+ startIndex: number;
27
+ endIndex: number;
28
+ }
29
+
30
+ /**
31
+ * 把 dataZoom 的 start/end 百分比换算为 x 轴索引窗口。
32
+ * 与本组件族写入 dataZoom 的百分比约定一致(index / total * 100),
33
+ * 对 echarts 原生交互产生的百分比做外扩取整,边界最多多含一项,不影响坐标轴量级。
34
+ */
35
+ export const percentWindowToIndexWindow = (
36
+ startPercent: number,
37
+ endPercent: number,
38
+ total: number,
39
+ ): DataZoomIndexWindow => {
40
+ if (total <= 0) return { startIndex: 0, endIndex: 0 };
41
+ const startIndex = Math.max(
42
+ 0,
43
+ Math.min(total - 1, Math.floor((startPercent / 100) * total)),
44
+ );
45
+ const endIndex = Math.max(
46
+ startIndex,
47
+ Math.min(total - 1, Math.ceil((endPercent / 100) * total) - 1),
48
+ );
49
+ return { startIndex, endIndex };
50
+ };
51
+
24
52
  export const createDefaultCategoryXAxis = (
25
53
  xAxisData?: Array<string>,
26
54
  ): ChartOptionType => ({
@@ -22,6 +22,8 @@ export interface ChartTooltipFormatterProps {
22
22
  hideMarker?: boolean;
23
23
  textStyle?: Record<string, unknown>;
24
24
  unit?: string;
25
+ /** 多系列时按数值从大到小排序展示(大的在上) */
26
+ sortDescending?: boolean;
25
27
  }
26
28
 
27
29
  const chartTooltipFormatter = (props: ChartTooltipFormatterProps) => {
@@ -31,6 +33,7 @@ const chartTooltipFormatter = (props: ChartTooltipFormatterProps) => {
31
33
  hideMarker,
32
34
  textStyle = { fontSize: 14, color: "#666", fontWeight: 400 },
33
35
  unit,
36
+ sortDescending,
34
37
  } = props;
35
38
 
36
39
  if (!Array.isArray(params)) {
@@ -77,13 +80,19 @@ const chartTooltipFormatter = (props: ChartTooltipFormatterProps) => {
77
80
  `;
78
81
  }
79
82
 
80
- const items = params
83
+ const sortedParams = sortDescending
84
+ ? [...params].sort(
85
+ (a, b) => (Number(b.value) || 0) - (Number(a.value) || 0),
86
+ )
87
+ : params;
88
+
89
+ const items = sortedParams
81
90
  ?.map((item, idx) => {
82
91
  const value = item.value ?? "";
83
92
 
84
93
  return `
85
94
  <div style="margin: 0 0 ${
86
- idx === params.length - 1 ? "0" : "10px"
95
+ idx === sortedParams.length - 1 ? "0" : "10px"
87
96
  } 0;line-height:1;">
88
97
  <div style="margin: 0px 0 0;line-height:1;">
89
98
  ${hideMarker ? "" : `${item?.marker}`}
@@ -1,37 +1,53 @@
1
- import chartTooltipFormatter from "./chartTooltipFormatter";
2
- import {
3
- TooltipParams,
4
- ChartTooltipFormatterProps,
5
- } from "./chartTooltipFormatter";
6
- import {
7
- autoScrollLegend,
8
- AutoScrollLegendProps,
9
- } from "../_utils/autoScrollLegend";
10
- import { calculateAxisConfig } from "./calculateAxisConfig";
11
- import {
12
- MB_PER_GB,
13
- MB_PER_TB,
14
- trimAxisNumber,
15
- chineseMagnitudeDivisor,
16
- formatChineseMagnitudeTick,
17
- mbDisplayTier,
18
- formatMbAxisTick,
19
- } from "./yAxisDisplayUnit";
20
-
21
- export {
22
- chartTooltipFormatter,
23
- autoScrollLegend,
24
- calculateAxisConfig,
25
- MB_PER_GB,
26
- MB_PER_TB,
27
- trimAxisNumber,
28
- chineseMagnitudeDivisor,
29
- formatChineseMagnitudeTick,
30
- mbDisplayTier,
31
- formatMbAxisTick,
32
- };
33
- export type {
34
- TooltipParams,
35
- ChartTooltipFormatterProps,
36
- AutoScrollLegendProps,
37
- };
1
+ import chartTooltipFormatter from "./chartTooltipFormatter";
2
+ import {
3
+ TooltipParams,
4
+ ChartTooltipFormatterProps,
5
+ } from "./chartTooltipFormatter";
6
+ import {
7
+ autoScrollLegend,
8
+ AutoScrollLegendProps,
9
+ } from "../_utils/autoScrollLegend";
10
+ import { calculateAxisConfig } from "./calculateAxisConfig";
11
+ import {
12
+ useLegendSelection,
13
+ LegendSelectionResult,
14
+ } from "./useLegendSelection";
15
+ import {
16
+ useDataZoomWindow,
17
+ DataZoomWindowOptions,
18
+ DataZoomWindowResult,
19
+ } from "./useDataZoomWindow";
20
+ import { DataZoomIndexWindow } from "../_utils/cartesian";
21
+ import {
22
+ MB_PER_GB,
23
+ MB_PER_TB,
24
+ trimAxisNumber,
25
+ chineseMagnitudeDivisor,
26
+ formatChineseMagnitudeTick,
27
+ mbDisplayTier,
28
+ formatMbAxisTick,
29
+ } from "./yAxisDisplayUnit";
30
+
31
+ export {
32
+ chartTooltipFormatter,
33
+ autoScrollLegend,
34
+ calculateAxisConfig,
35
+ useLegendSelection,
36
+ useDataZoomWindow,
37
+ MB_PER_GB,
38
+ MB_PER_TB,
39
+ trimAxisNumber,
40
+ chineseMagnitudeDivisor,
41
+ formatChineseMagnitudeTick,
42
+ mbDisplayTier,
43
+ formatMbAxisTick,
44
+ };
45
+ export type {
46
+ TooltipParams,
47
+ ChartTooltipFormatterProps,
48
+ AutoScrollLegendProps,
49
+ LegendSelectionResult,
50
+ DataZoomWindowOptions,
51
+ DataZoomWindowResult,
52
+ DataZoomIndexWindow,
53
+ };
@@ -0,0 +1,61 @@
1
+ import { useCallback, useState } from "react";
2
+ import { DataZoomIndexWindow } from "../_utils/cartesian";
3
+
4
+ export interface DataZoomWindowOptions {
5
+ /** 开关:是否按 dataZoom 当前可见窗口重算坐标轴,默认开启 */
6
+ enabled?: boolean;
7
+ }
8
+
9
+ export interface DataZoomWindowResult {
10
+ /** 当前可见窗口;开关关闭或尚未收到回调时为 null(表示全量) */
11
+ zoomWindow: DataZoomIndexWindow | null;
12
+ /** 传给 Chart.Bar / Chart.Line 的 onDataZoomWindowChanged;开关关闭时为 undefined(不绑定事件) */
13
+ onDataZoomWindowChanged?: (window: DataZoomIndexWindow) => void;
14
+ /** 按当前可见窗口裁剪系列数据,配合 calculateAxisConfig 只对展示部分重算坐标轴 */
15
+ sliceByZoomWindow: <T>(values?: T[] | null) => T[];
16
+ }
17
+
18
+ /**
19
+ * dataZoom 可见窗口管理:配合 Chart.Bar / Chart.Line 的 onDataZoomWindowChanged,
20
+ * 在调用方按"当前可见窗口"裁剪数据后重算 Y 轴 min/max/interval(calculateAxisConfig),
21
+ * 实现滑块拖动/滚轮/自动滚动时坐标轴跟随展示部分动态重算;可与 useLegendSelection 叠加。
22
+ */
23
+ export function useDataZoomWindow(
24
+ options?: DataZoomWindowOptions,
25
+ ): DataZoomWindowResult {
26
+ const enabled = options?.enabled ?? true;
27
+ const [zoomWindow, setZoomWindow] = useState<DataZoomIndexWindow | null>(
28
+ null,
29
+ );
30
+
31
+ const onDataZoomWindowChanged = useCallback((next: DataZoomIndexWindow) => {
32
+ // 窗口未变化时保持原引用,避免重渲染 → 同步回调 → 再重渲染的循环
33
+ setZoomWindow((prev) =>
34
+ prev &&
35
+ prev.startIndex === next.startIndex &&
36
+ prev.endIndex === next.endIndex
37
+ ? prev
38
+ : next,
39
+ );
40
+ }, []);
41
+
42
+ const effectiveWindow = enabled ? zoomWindow : null;
43
+
44
+ const sliceByZoomWindow = useCallback(
45
+ <T>(values?: T[] | null): T[] => {
46
+ if (!values) return [];
47
+ if (!effectiveWindow) return values;
48
+ return values.slice(
49
+ effectiveWindow.startIndex,
50
+ effectiveWindow.endIndex + 1,
51
+ );
52
+ },
53
+ [effectiveWindow],
54
+ );
55
+
56
+ return {
57
+ zoomWindow: effectiveWindow,
58
+ onDataZoomWindowChanged: enabled ? onDataZoomWindowChanged : undefined,
59
+ sliceByZoomWindow,
60
+ };
61
+ }
@@ -0,0 +1,35 @@
1
+ import { useCallback, useState } from "react";
2
+
3
+ export interface LegendSelectionResult {
4
+ /** 传给图表 legend.selected,保证重渲染(setOption notMerge)后隐藏状态不丢 */
5
+ legendSelected: Record<string, boolean>;
6
+ /** 传给图表 onLegendSelectChanged */
7
+ onLegendSelectChanged: (selected: Record<string, boolean>) => void;
8
+ /** 判断某系列当前是否可见(未点过的系列默认可见) */
9
+ isSeriesVisible: (name?: string | null) => boolean;
10
+ }
11
+
12
+ /**
13
+ * 图例选中状态管理:配合 Chart.Bar / Chart.Line 的 onLegendSelectChanged,
14
+ * 在调用方按"当前可见系列"重算 Y 轴 min/max/interval(calculateAxisConfig),
15
+ * 实现图例隐藏某一项后坐标轴自动重算。
16
+ */
17
+ export function useLegendSelection(): LegendSelectionResult {
18
+ const [legendSelected, setLegendSelected] = useState<Record<string, boolean>>(
19
+ {},
20
+ );
21
+
22
+ const onLegendSelectChanged = useCallback(
23
+ (selected: Record<string, boolean>) => {
24
+ setLegendSelected({ ...selected });
25
+ },
26
+ [],
27
+ );
28
+
29
+ const isSeriesVisible = useCallback(
30
+ (name?: string | null) => name == null || legendSelected[name] !== false,
31
+ [legendSelected],
32
+ );
33
+
34
+ return { legendSelected, onLegendSelectChanged, isSeriesVisible };
35
+ }
@@ -46,6 +46,8 @@ export interface ItemContainerProps extends FormItemProps {
46
46
  labelBreak?: boolean;
47
47
  hideAdditiona?: boolean;
48
48
  hideLabel?: boolean;
49
+ /** 显隐开关,由 FormItem 消费;在此解构剥离,避免透传到 DOM */
50
+ visible?: boolean;
49
51
  }
50
52
 
51
53
  const ItemContainer: React.FC<ItemContainerProps> = (props) => {
@@ -84,6 +86,7 @@ const ItemContainer: React.FC<ItemContainerProps> = (props) => {
84
86
  labelBreak = false,
85
87
  hideAdditiona = false,
86
88
  hideLabel = false,
89
+ visible: _visible,
87
90
  ...formItemProps
88
91
  } = props;
89
92
  const { icon = "material-symbols:help", iconClassName, ...tipsConfig } = tips;
@@ -198,15 +201,9 @@ const ItemContainer: React.FC<ItemContainerProps> = (props) => {
198
201
  return null;
199
202
  }
200
203
 
201
- // 页面层 FormItemProps 的展示控制属性(如 visible)不属于 antd Form.Item,
202
- // 剥离后再透传,避免被 antd 转发到 DOM 触发 React 非法属性警告。
203
- const restFormItemProps = Object.fromEntries(
204
- Object.entries(formItemProps).filter(([key]) => key !== "visible")
205
- );
206
-
207
204
  return (
208
205
  <Form.Item
209
- {...restFormItemProps}
206
+ {...formItemProps}
210
207
  name={name}
211
208
  rules={[
212
209
  {
@@ -62,6 +62,7 @@
62
62
  align-items: center;
63
63
  justify-content: flex-end;
64
64
  column-gap: 10px;
65
+ margin-left: auto; // title 为空时仍保持靠右
65
66
  }
66
67
  }
67
68
  }