@hsu-react/ui 0.0.17 → 0.0.19

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 (36) hide show
  1. package/es/components/Chart/Bar/index.js +21 -6
  2. package/es/components/Chart/Line/index.js +21 -6
  3. package/es/components/Chart/_utils/autoScrollLegend.d.ts +5 -0
  4. package/es/components/Chart/_utils/autoScrollLegend.js +16 -6
  5. package/es/components/FilePreview/_components/XlsxPreviewPane/index.d.ts +16 -0
  6. package/es/components/FilePreview/_components/XlsxPreviewPane/index.js +27 -0
  7. package/es/components/FilePreview/index.js +52 -23
  8. package/es/components/FormItem/FormInput/FormPasswordStrength/index.js +43 -4
  9. package/es/components/FormItem/index.d.ts +2 -2
  10. package/es/components/FormItem/index.js +46 -5
  11. package/es/components/SecondConf/index.d.ts +13 -2
  12. package/es/components/SecondConf/index.js +66 -26
  13. package/lib/components/Chart/Bar/index.js +18 -3
  14. package/lib/components/Chart/Line/index.js +18 -3
  15. package/lib/components/Chart/_utils/autoScrollLegend.d.ts +5 -0
  16. package/lib/components/Chart/_utils/autoScrollLegend.js +14 -6
  17. package/lib/components/FilePreview/_components/XlsxPreviewPane/index.d.ts +16 -0
  18. package/lib/components/FilePreview/_components/XlsxPreviewPane/index.js +35 -0
  19. package/lib/components/FilePreview/index.js +47 -23
  20. package/lib/components/FormItem/FormInput/FormPasswordStrength/index.js +37 -5
  21. package/lib/components/FormItem/index.d.ts +2 -2
  22. package/lib/components/FormItem/index.js +43 -7
  23. package/lib/components/SecondConf/index.d.ts +13 -2
  24. package/lib/components/SecondConf/index.js +55 -24
  25. package/package.json +4 -3
  26. package/src/components/Chart/Bar/index.tsx +26 -6
  27. package/src/components/Chart/Line/index.tsx +26 -6
  28. package/src/components/Chart/_utils/autoScrollLegend.ts +17 -3
  29. package/src/components/FilePreview/_components/XlsxPreviewPane/index.tsx +33 -0
  30. package/src/components/FilePreview/index.md +11 -0
  31. package/src/components/FilePreview/index.tsx +46 -19
  32. package/src/components/FormItem/FormInput/FormPasswordStrength/index.tsx +43 -4
  33. package/src/components/FormItem/index.md +19 -0
  34. package/src/components/FormItem/index.tsx +44 -5
  35. package/src/components/SecondConf/index.md +42 -0
  36. package/src/components/SecondConf/index.tsx +72 -22
@@ -185,7 +185,7 @@ var ChartBar = function ChartBar(props) {
185
185
 
186
186
  // Initialize the chart
187
187
  useEffect(function () {
188
- var _xAxisData$join, _chart$getOption, _opt$legend$, _opt$legend, _ref3;
188
+ var _xAxisData$join, _chart$getOption, _chart$getOption2, _opt$legend$, _opt$legend, _ref3;
189
189
  if (!chartRef.current) return;
190
190
 
191
191
  // Initialize or reuse the existing instance
@@ -198,9 +198,20 @@ var ChartBar = function ChartBar(props) {
198
198
  // Set the option: notMerge resets the dataZoom window to its initial position,
199
199
  // so when x-axis data is unchanged (e.g. re-render triggered by axis recalculation / legend selection), record the current window first and restore it afterwards
200
200
  var xAxisKey = (_xAxisData$join = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.join("\x01")) !== null && _xAxisData$join !== void 0 ? _xAxisData$join : "";
201
- var prevZoomRanges = prevXAxisKeyRef.current === xAxisKey ? (_chart$getOption = chart.getOption()) === null || _chart$getOption === void 0 ? void 0 : _chart$getOption.dataZoom : undefined;
201
+ var sameXAxis = prevXAxisKeyRef.current === xAxisKey;
202
+ var prevZoomRanges = sameXAxis ? (_chart$getOption = chart.getOption()) === null || _chart$getOption === void 0 ? void 0 : _chart$getOption.dataZoom : undefined;
203
+ // 滚动图例的翻页位置同样会被 notMerge 重置,x 轴未变时恢复,
204
+ // 否则点一次图例、或坐标轴重算触发一次重渲染,图例就跳回第一页
205
+ var prevLegendScrollIndex = sameXAxis ? (_chart$getOption2 = chart.getOption()) === null || _chart$getOption2 === void 0 || (_chart$getOption2 = _chart$getOption2.legend) === null || _chart$getOption2 === void 0 || (_chart$getOption2 = _chart$getOption2[0]) === null || _chart$getOption2 === void 0 ? void 0 : _chart$getOption2.scrollDataIndex : undefined;
202
206
  prevXAxisKeyRef.current = xAxisKey;
203
207
  chart.setOption(chartOption, true);
208
+ if (prevLegendScrollIndex) {
209
+ chart.setOption({
210
+ legend: {
211
+ scrollDataIndex: prevLegendScrollIndex
212
+ }
213
+ });
214
+ }
204
215
  var nextZooms = chartOption.dataZoom;
205
216
  if (prevZoomRanges !== null && prevZoomRanges !== void 0 && prevZoomRanges.length && Array.isArray(nextZooms) && nextZooms.length === prevZoomRanges.length) {
206
217
  chart.setOption({
@@ -215,8 +226,8 @@ var ChartBar = function ChartBar(props) {
215
226
 
216
227
  // Sync the current visible window to the caller (on initial render and after restore), used to recalculate axes based on the displayed portion
217
228
  if (onDataZoomWindowChanged) {
218
- var _chart$getOption2, _xAxisData$length2;
219
- var zooms = (_chart$getOption2 = chart.getOption()) === null || _chart$getOption2 === void 0 ? void 0 : _chart$getOption2.dataZoom;
229
+ var _chart$getOption3, _xAxisData$length2;
230
+ var zooms = (_chart$getOption3 = chart.getOption()) === null || _chart$getOption3 === void 0 ? void 0 : _chart$getOption3.dataZoom;
220
231
  var zoom = zooms === null || zooms === void 0 ? void 0 : zooms[0];
221
232
  var totalLen = (_xAxisData$length2 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length2 !== void 0 ? _xAxisData$length2 : 0;
222
233
  if (typeof (zoom === null || zoom === void 0 ? void 0 : zoom.start) === "number" && typeof (zoom === null || zoom === void 0 ? void 0 : zoom.end) === "number") {
@@ -288,7 +299,9 @@ var ChartBar = function ChartBar(props) {
288
299
  total: legendTotal,
289
300
  visibleCount: legendVisibleCount,
290
301
  interval: legendScrollInterval,
291
- autoStart: true
302
+ autoStart: true,
303
+ // 滚轮已被 x 轴平移占用时不再让图例抢,否则一次滚动两处都动
304
+ enableWheel: !normalizedScroll.zoomEnabled || normalizedScroll.wheelModeWhenSliderHidden !== "scroll"
292
305
  });
293
306
  }
294
307
 
@@ -312,7 +325,9 @@ var ChartBar = function ChartBar(props) {
312
325
  legendScrollRef.current = null;
313
326
  }
314
327
  };
315
- }, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval]);
328
+ }, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
329
+ // 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
330
+ normalizedScroll]);
316
331
 
317
332
  // Handle auto play
318
333
  useEffect(function () {
@@ -181,7 +181,7 @@ var ChartLine = function ChartLine(props) {
181
181
 
182
182
  // Initialize the chart
183
183
  useEffect(function () {
184
- var _xAxisData$join, _chart$getOption, _opt$legend$, _opt$legend, _ref3;
184
+ var _xAxisData$join, _chart$getOption, _chart$getOption2, _opt$legend$, _opt$legend, _ref3;
185
185
  if (!chartRef.current) return;
186
186
 
187
187
  // Initialize or reuse the existing instance
@@ -194,9 +194,20 @@ var ChartLine = function ChartLine(props) {
194
194
  // Set the option: notMerge resets the dataZoom window to its initial position,
195
195
  // so when x-axis data is unchanged (e.g. re-render triggered by axis recalculation / legend selection), record the current window first and restore it afterwards
196
196
  var xAxisKey = (_xAxisData$join = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.join("\x01")) !== null && _xAxisData$join !== void 0 ? _xAxisData$join : "";
197
- var prevZoomRanges = prevXAxisKeyRef.current === xAxisKey ? (_chart$getOption = chart.getOption()) === null || _chart$getOption === void 0 ? void 0 : _chart$getOption.dataZoom : undefined;
197
+ var sameXAxis = prevXAxisKeyRef.current === xAxisKey;
198
+ var prevZoomRanges = sameXAxis ? (_chart$getOption = chart.getOption()) === null || _chart$getOption === void 0 ? void 0 : _chart$getOption.dataZoom : undefined;
199
+ // 滚动图例的翻页位置同样会被 notMerge 重置,x 轴未变时恢复,
200
+ // 否则点一次图例、或坐标轴重算触发一次重渲染,图例就跳回第一页
201
+ var prevLegendScrollIndex = sameXAxis ? (_chart$getOption2 = chart.getOption()) === null || _chart$getOption2 === void 0 || (_chart$getOption2 = _chart$getOption2.legend) === null || _chart$getOption2 === void 0 || (_chart$getOption2 = _chart$getOption2[0]) === null || _chart$getOption2 === void 0 ? void 0 : _chart$getOption2.scrollDataIndex : undefined;
198
202
  prevXAxisKeyRef.current = xAxisKey;
199
203
  chart.setOption(chartOption, true);
204
+ if (prevLegendScrollIndex) {
205
+ chart.setOption({
206
+ legend: {
207
+ scrollDataIndex: prevLegendScrollIndex
208
+ }
209
+ });
210
+ }
200
211
  var nextZooms = chartOption.dataZoom;
201
212
  if (prevZoomRanges !== null && prevZoomRanges !== void 0 && prevZoomRanges.length && Array.isArray(nextZooms) && nextZooms.length === prevZoomRanges.length) {
202
213
  chart.setOption({
@@ -211,8 +222,8 @@ var ChartLine = function ChartLine(props) {
211
222
 
212
223
  // Sync the current visible window to the caller (on initial render and after restore), used to recalculate axes based on the displayed portion
213
224
  if (onDataZoomWindowChanged) {
214
- var _chart$getOption2, _xAxisData$length2;
215
- var zooms = (_chart$getOption2 = chart.getOption()) === null || _chart$getOption2 === void 0 ? void 0 : _chart$getOption2.dataZoom;
225
+ var _chart$getOption3, _xAxisData$length2;
226
+ var zooms = (_chart$getOption3 = chart.getOption()) === null || _chart$getOption3 === void 0 ? void 0 : _chart$getOption3.dataZoom;
216
227
  var zoom = zooms === null || zooms === void 0 ? void 0 : zooms[0];
217
228
  var totalLen = (_xAxisData$length2 = xAxisData === null || xAxisData === void 0 ? void 0 : xAxisData.length) !== null && _xAxisData$length2 !== void 0 ? _xAxisData$length2 : 0;
218
229
  if (typeof (zoom === null || zoom === void 0 ? void 0 : zoom.start) === "number" && typeof (zoom === null || zoom === void 0 ? void 0 : zoom.end) === "number") {
@@ -284,7 +295,9 @@ var ChartLine = function ChartLine(props) {
284
295
  total: legendTotal,
285
296
  visibleCount: legendVisibleCount,
286
297
  interval: legendScrollInterval,
287
- autoStart: true
298
+ autoStart: true,
299
+ // 滚轮已被 x 轴平移占用时不再让图例抢,否则一次滚动两处都动
300
+ enableWheel: !normalizedScroll.zoomEnabled || normalizedScroll.wheelModeWhenSliderHidden !== "scroll"
288
301
  });
289
302
  }
290
303
 
@@ -308,7 +321,9 @@ var ChartLine = function ChartLine(props) {
308
321
  legendScrollRef.current = null;
309
322
  }
310
323
  };
311
- }, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval]);
324
+ }, [chartOption, handleResize, onClick, onLegendSelectChanged, onDataZoomWindowChanged, xAxisData, enableLegendAutoScroll, legendVisibleCount, legendScrollInterval,
325
+ // 图例是否接管滚轮由它推导,漏了会拿到过期的滚动配置
326
+ normalizedScroll]);
312
327
 
313
328
  // Handle auto play
314
329
  useEffect(function () {
@@ -6,6 +6,11 @@ export interface AutoScrollLegendProps {
6
6
  interval?: number;
7
7
  autoStart?: boolean;
8
8
  stopOnWheel?: boolean;
9
+ /**
10
+ * 是否接管滚轮翻图例,默认 true。
11
+ * 图表自身已用滚轮平移 x 轴时传 false,避免一次滚动既翻图例又移坐标轴。
12
+ */
13
+ enableWheel?: boolean;
9
14
  }
10
15
  export declare function autoScrollLegend(props: AutoScrollLegendProps): {
11
16
  start: () => void;
@@ -1,4 +1,5 @@
1
1
  export function autoScrollLegend(props) {
2
+ var _chart$getOption, _legendOption$scrollD;
2
3
  var chart = props.chart,
3
4
  total = props.total,
4
5
  _props$visibleCount = props.visibleCount,
@@ -8,8 +9,13 @@ export function autoScrollLegend(props) {
8
9
  _props$autoStart = props.autoStart,
9
10
  autoStart = _props$autoStart === void 0 ? true : _props$autoStart,
10
11
  _props$stopOnWheel = props.stopOnWheel,
11
- stopOnWheel = _props$stopOnWheel === void 0 ? true : _props$stopOnWheel;
12
- var currentIndex = 0;
12
+ stopOnWheel = _props$stopOnWheel === void 0 ? true : _props$stopOnWheel,
13
+ _props$enableWheel = props.enableWheel,
14
+ enableWheel = _props$enableWheel === void 0 ? true : _props$enableWheel;
15
+
16
+ // 组件重渲染会重建滚动器,从图例当前位置接着轮播,避免每次都跳回第一项
17
+ var legendOption = (_chart$getOption = chart.getOption()) === null || _chart$getOption === void 0 || (_chart$getOption = _chart$getOption.legend) === null || _chart$getOption === void 0 ? void 0 : _chart$getOption[0];
18
+ var currentIndex = (_legendOption$scrollD = legendOption === null || legendOption === void 0 ? void 0 : legendOption.scrollDataIndex) !== null && _legendOption$scrollD !== void 0 ? _legendOption$scrollD : 0;
13
19
  var scrollInterval = null;
14
20
  var isManualScrolling = false;
15
21
  function start() {
@@ -69,14 +75,18 @@ export function autoScrollLegend(props) {
69
75
  var chartDom = chart.getDom();
70
76
  chartDom.addEventListener("mouseover", handleMouseOver);
71
77
  chartDom.addEventListener("mouseout", handleMouseOut);
72
- chartDom.addEventListener("wheel", handleWheel, {
73
- passive: false
74
- });
78
+ if (enableWheel) {
79
+ chartDom.addEventListener("wheel", handleWheel, {
80
+ passive: false
81
+ });
82
+ }
75
83
  function dispose() {
76
84
  stop();
77
85
  chartDom.removeEventListener("mouseover", handleMouseOver);
78
86
  chartDom.removeEventListener("mouseout", handleMouseOut);
79
- chartDom.removeEventListener("wheel", handleWheel);
87
+ if (enableWheel) {
88
+ chartDom.removeEventListener("wheel", handleWheel);
89
+ }
80
90
  }
81
91
  if (autoStart) {
82
92
  start();
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ export interface XlsxPreviewPaneProps {
3
+ fileUrl?: string;
4
+ fileType?: string;
5
+ onClose?: () => void;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * xlsx 预览的完整单元:取数(useXlsxData → xlsx)+ 渲染(XlsxPreview → x-data-spreadsheet)。
10
+ *
11
+ * 单独成文件是为了让 FilePreview 能整体 lazy 掉它。useXlsxData 是 hook,不能写在
12
+ * switch 的某个分支里,若留在 FilePreview 顶层就会把 xlsx 静态拖进依赖图——那正是
13
+ * 要避免的。把「取数 + 渲染」收进同一个组件,整块按需加载。
14
+ */
15
+ declare const XlsxPreviewPane: React.FC<XlsxPreviewPaneProps>;
16
+ export default XlsxPreviewPane;
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ import XlsxPreview from "../XlsxPreview";
3
+ import { useXlsxData } from "../../_hooks";
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ /**
6
+ * xlsx 预览的完整单元:取数(useXlsxData → xlsx)+ 渲染(XlsxPreview → x-data-spreadsheet)。
7
+ *
8
+ * 单独成文件是为了让 FilePreview 能整体 lazy 掉它。useXlsxData 是 hook,不能写在
9
+ * switch 的某个分支里,若留在 FilePreview 顶层就会把 xlsx 静态拖进依赖图——那正是
10
+ * 要避免的。把「取数 + 渲染」收进同一个组件,整块按需加载。
11
+ */
12
+ var XlsxPreviewPane = function XlsxPreviewPane(_ref) {
13
+ var fileUrl = _ref.fileUrl,
14
+ fileType = _ref.fileType,
15
+ onClose = _ref.onClose,
16
+ className = _ref.className;
17
+ var xlsxData = useXlsxData({
18
+ fileType: fileType,
19
+ fileUrl: fileUrl
20
+ });
21
+ return /*#__PURE__*/_jsx(XlsxPreview, {
22
+ xlsxData: xlsxData,
23
+ onClose: onClose,
24
+ className: className
25
+ });
26
+ };
27
+ export default XlsxPreviewPane;
@@ -1,14 +1,37 @@
1
- import React from "react";
2
- import PdfPreview from "./_components/PdfPreview";
1
+ import React, { Suspense, lazy } from "react";
3
2
  import VideoPreview from "./_components/VideoPreview";
4
3
  import TextPreview from "./_components/TextPreview";
5
- import MarkdownPreview from "./_components/MarkdownPreview";
6
4
  import ImagePreview from "./_components/ImagePreview";
7
- import XlsxPreview from "./_components/XlsxPreview";
8
- import { useXlsxData } from "./_hooks";
9
5
  import { FilePreviewTypeArr } from "./_utils";
10
6
  import { jsx as _jsx } from "react/jsx-runtime";
11
7
  export { FilePreviewTypeArr };
8
+
9
+ /**
10
+ * 重型格式按需加载。
11
+ *
12
+ * FilePreview 是个按 fileType 分发的 dispatcher,而它处在 Upload / FormItem 的静态
13
+ * 依赖图上(FormItem → FormUpload → Upload → FilePreview),业务侧只要用到任何一种
14
+ * 表单项,下面这些只服务于特定格式的库就会被打进首屏:
15
+ *
16
+ * pdf → PdfPreview → hsu-utils 的 RenderPDF → pdfjs-dist 约 374 KB
17
+ * xlsx → XlsxPreviewPane → xlsx + x-data-spreadsheet
18
+ * md → MarkdownPreview → Markdown → katex 等
19
+ *
20
+ * 修 dispatcher 而不是逐个改它的引用方:这里改一次,所有静态 import FilePreview 的
21
+ * 地方(Upload、UploadedItem、FormImage…)都受益,也不会因为将来多一个引用方而回归。
22
+ *
23
+ * 图片/文本/视频三种是轻量实现,保持静态——它们也是最常命中的格式,不值得为其
24
+ * 付一次异步往返。
25
+ */
26
+ var PdfPreview = /*#__PURE__*/lazy(function () {
27
+ return import("./_components/PdfPreview");
28
+ });
29
+ var MarkdownPreview = /*#__PURE__*/lazy(function () {
30
+ return import("./_components/MarkdownPreview");
31
+ });
32
+ var XlsxPreviewPane = /*#__PURE__*/lazy(function () {
33
+ return import("./_components/XlsxPreviewPane");
34
+ });
12
35
  var FilePreview = function FilePreview(props) {
13
36
  var fileUrl = props.fileUrl,
14
37
  fileType = props.fileType,
@@ -17,10 +40,6 @@ var FilePreview = function FilePreview(props) {
17
40
  text = props.text,
18
41
  className = props.className,
19
42
  pagination = props.pagination;
20
- var xlsxData = useXlsxData({
21
- fileType: fileType,
22
- fileUrl: fileUrl
23
- });
24
43
  if (!open) {
25
44
  return null;
26
45
  }
@@ -35,12 +54,15 @@ var FilePreview = function FilePreview(props) {
35
54
  }
36
55
  case "pdf":
37
56
  {
38
- return /*#__PURE__*/_jsx(PdfPreview, {
39
- fileUrl: fileUrl,
40
- open: open,
41
- onClose: onClose,
42
- className: className,
43
- pagination: pagination
57
+ return /*#__PURE__*/_jsx(Suspense, {
58
+ fallback: null,
59
+ children: /*#__PURE__*/_jsx(PdfPreview, {
60
+ fileUrl: fileUrl,
61
+ open: open,
62
+ onClose: onClose,
63
+ className: className,
64
+ pagination: pagination
65
+ })
44
66
  });
45
67
  }
46
68
  case "jpg":
@@ -64,18 +86,25 @@ var FilePreview = function FilePreview(props) {
64
86
  }
65
87
  case "md":
66
88
  {
67
- return /*#__PURE__*/_jsx(MarkdownPreview, {
68
- text: text,
69
- onClose: onClose,
70
- className: className
89
+ return /*#__PURE__*/_jsx(Suspense, {
90
+ fallback: null,
91
+ children: /*#__PURE__*/_jsx(MarkdownPreview, {
92
+ text: text,
93
+ onClose: onClose,
94
+ className: className
95
+ })
71
96
  });
72
97
  }
73
98
  case "xlsx":
74
99
  {
75
- return /*#__PURE__*/_jsx(XlsxPreview, {
76
- xlsxData: xlsxData,
77
- onClose: onClose,
78
- className: className
100
+ return /*#__PURE__*/_jsx(Suspense, {
101
+ fallback: null,
102
+ children: /*#__PURE__*/_jsx(XlsxPreviewPane, {
103
+ fileUrl: fileUrl,
104
+ fileType: fileType,
105
+ onClose: onClose,
106
+ className: className
107
+ })
79
108
  });
80
109
  }
81
110
  default:
@@ -16,11 +16,34 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
16
16
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
17
17
  import Input from "../../../Input";
18
18
  import ItemContainer from "../../ItemContainer";
19
- import React, { useState } from "react";
19
+ import React, { useEffect, useRef, useState } from "react";
20
20
  import styles from "./index.module.scss";
21
- import zxcvbn from "zxcvbn";
21
+
22
+ /**
23
+ * zxcvbn 约 793 KB(未压缩),却只在这一个字段的 onChange 里用来算强度分。
24
+ * 静态 import 会让它跟着 FormInput → FormItem 进入每个引入过表单项的页面的
25
+ * 首屏 chunk。改成动态 import:只有真的渲染了 PASSWORDSTRENGTH 字段才去拉。
26
+ *
27
+ * 模块级缓存 Promise,多个密码框共用一次加载;失败时清掉缓存,下次重试。
28
+ */
22
29
  import { jsx as _jsx } from "react/jsx-runtime";
23
30
  import { jsxs as _jsxs } from "react/jsx-runtime";
31
+ var zxcvbnPromise;
32
+ var loadZxcvbn = function loadZxcvbn() {
33
+ if (!zxcvbnPromise) {
34
+ zxcvbnPromise = import("zxcvbn").then(function (mod) {
35
+ var _m$default;
36
+ // zxcvbn 是 `export =` 的 CJS 模块:不同打包器/interop 下动态 import 拿到的
37
+ // 可能是函数本身,也可能是 { default: 函数 },两种都要兼容
38
+ var m = mod;
39
+ return (_m$default = m.default) !== null && _m$default !== void 0 ? _m$default : m;
40
+ }).catch(function (err) {
41
+ zxcvbnPromise = undefined;
42
+ throw err;
43
+ });
44
+ }
45
+ return zxcvbnPromise;
46
+ };
24
47
  var PasswordStrength = function PasswordStrength(props) {
25
48
  var placeholder = props.placeholder,
26
49
  _onChange = props.onChange,
@@ -29,14 +52,30 @@ var PasswordStrength = function PasswordStrength(props) {
29
52
  _useState2 = _slicedToArray(_useState, 2),
30
53
  fraction = _useState2[0],
31
54
  setFraction = _useState2[1];
55
+ // 挂载即预取:chunk 仍是独立的,但用户敲第一个字符时通常已经就绪
56
+ useEffect(function () {
57
+ loadZxcvbn().catch(function () {
58
+ return undefined;
59
+ });
60
+ }, []);
61
+
62
+ // 打字比加载快时会有多次并发计算,迟到的结果不能盖掉最新一次
63
+ var seqRef = useRef(0);
32
64
  return /*#__PURE__*/_jsxs("div", {
33
65
  className: styles.passwordStrength,
34
66
  children: [/*#__PURE__*/_jsx(Input.Password, _objectSpread(_objectSpread({}, inputConfig), {}, {
35
67
  placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "请输入",
36
68
  onChange: function onChange(value) {
37
69
  _onChange && _onChange(value);
38
- var _fraction = zxcvbn(value).guesses_log10;
39
- setFraction(_fraction);
70
+ var seq = ++seqRef.current;
71
+ loadZxcvbn().then(function (zxcvbn) {
72
+ if (seq !== seqRef.current) return;
73
+ setFraction(zxcvbn(value).guesses_log10);
74
+ })
75
+ // 强度条只是辅助提示,拉不到就不显示,不打断用户输入
76
+ .catch(function () {
77
+ return undefined;
78
+ });
40
79
  },
41
80
  allowClear: true,
42
81
  autoComplete: "new-password"
@@ -1,7 +1,7 @@
1
1
  import { FormAutoProps } from "./FormAuto";
2
2
  import { FormCheckboxGroupProps, FormCheckboxProps } from "./FormCheckbox";
3
3
  import { FormDatePickerProps, FormRangePickerProps, FormStepPickerProps } from "./FormDatePicker";
4
- import { FormEditorProps } from "./FormEditor";
4
+ import type { FormEditorProps } from "./FormEditor";
5
5
  import { FormInputNumberProps, FormInputProps, FormPasswordProps, FormPasswordStrengthProps, FormRangeInputProps, FormTextAreaInputProps } from "./FormInput";
6
6
  import { FormRadioProps } from "./FormRadio";
7
7
  import { FormSegmentedProps } from "./FormSegmented";
@@ -12,7 +12,7 @@ import { FormTreeProps } from "./FormTree";
12
12
  import { FormImageProps, FormUploadProps } from "./FormUpload";
13
13
  import ItemContainer, { ItemContainerProps } from "./ItemContainer";
14
14
  import { FormTextProps } from "./FormText";
15
- import { FormCodeMirrorProps } from "./FormCodeMirror";
15
+ import type { FormCodeMirrorProps } from "./FormCodeMirror";
16
16
  import React from "react";
17
17
  export { ItemContainer as FormItemContainer };
18
18
  export type { ItemContainerProps as FormItemContainerProps };
@@ -7,7 +7,6 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
7
7
  import FormAuto from "./FormAuto";
8
8
  import FormCheckbox from "./FormCheckbox";
9
9
  import FormDatePicker from "./FormDatePicker";
10
- import FormEditor from "./FormEditor";
11
10
  import FormInput from "./FormInput";
12
11
  import FormRadio from "./FormRadio";
13
12
  import FormSegmented from "./FormSegmented";
@@ -18,9 +17,47 @@ import FormTree from "./FormTree";
18
17
  import FormUpload from "./FormUpload";
19
18
  import ItemContainer from "./ItemContainer";
20
19
  import FormText from "./FormText";
21
- import FormCodeMirror from "./FormCodeMirror";
22
- import React from "react";
20
+ import React, { Suspense, lazy } from "react";
21
+
22
+ /**
23
+ * 重型字段按需加载。
24
+ *
25
+ * FormItem 是个静态分发器,几乎每个业务页面都会引入它。若在这里静态 import
26
+ * 全部渲染器,那么**只要用到任何一种表单项**,富文本、代码编辑器这些巨型依赖
27
+ * 就会被一并拉进消费方的首屏 chunk:
28
+ *
29
+ * FormItem → FormEditor → Editor → @wangeditor/editor (约 814 KB)
30
+ * FormItem → FormCodeMirror → CodeMirror → @codemirror/* (约 380 KB)
31
+ *
32
+ * 消费方实测:某后台项目仅因入口图里存在 FormItem,首屏就多背了约 2.5 MB
33
+ * 未压缩的三方库;改为按需加载后首屏从 3.72 MB 降到 965 KB(gzip)。
34
+ *
35
+ * 只有 type 真的命中 EDITOR / CODEMIRROR 时才会去拉对应 chunk。类型仍走静态
36
+ * `import type`(编译期擦除,不产生运行时依赖),所以 FormItemMap 不受影响。
37
+ * 同一目录下的 CodeMirror 早就用 `import()` 按需加载语言包/校验器,这里是同一思路。
38
+ */
23
39
  import { jsx as _jsx } from "react/jsx-runtime";
40
+ var FormEditor = /*#__PURE__*/lazy(function () {
41
+ return import("./FormEditor");
42
+ });
43
+ var FormCodeMirror = /*#__PURE__*/lazy(function () {
44
+ return import("./FormCodeMirror");
45
+ });
46
+
47
+ /**
48
+ * 重型字段的 Suspense 包装。
49
+ *
50
+ * fallback 用 null 而不是骨架:这些字段都由 ItemContainer 渲染 antd 的
51
+ * Form.Item,加载期间不占位反而不会让表单布局跳动;antd Form 的值存在 store 里,
52
+ * 字段挂载晚于 setFieldsValue 也能正确回填,不影响编辑态回显。
53
+ */
54
+ var LazyField = function LazyField(_ref) {
55
+ var children = _ref.children;
56
+ return /*#__PURE__*/_jsx(Suspense, {
57
+ fallback: null,
58
+ children: children
59
+ });
60
+ };
24
61
  export { ItemContainer as FormItemContainer };
25
62
 
26
63
  // Common base type
@@ -198,9 +235,13 @@ var FormItem = function FormItem(props) {
198
235
  case "SLIDER":
199
236
  return /*#__PURE__*/_jsx(FormSlider, _objectSpread({}, props));
200
237
  case "EDITOR":
201
- return /*#__PURE__*/_jsx(FormEditor, _objectSpread({}, props));
238
+ return /*#__PURE__*/_jsx(LazyField, {
239
+ children: /*#__PURE__*/_jsx(FormEditor, _objectSpread({}, props))
240
+ });
202
241
  case "CODEMIRROR":
203
- return /*#__PURE__*/_jsx(FormCodeMirror, _objectSpread({}, props));
242
+ return /*#__PURE__*/_jsx(LazyField, {
243
+ children: /*#__PURE__*/_jsx(FormCodeMirror, _objectSpread({}, props))
244
+ });
204
245
  case "TEXT":
205
246
  return /*#__PURE__*/_jsx(FormText, _objectSpread({}, props));
206
247
  default:
@@ -1,8 +1,19 @@
1
- import React, { ReactNode } from "react";
1
+ import React, { ReactElement, ReactNode } from "react";
2
2
  import { ModalProps } from "../Modal";
3
- interface SecondConfProps extends Omit<ModalProps, "title"> {
3
+ export interface SecondConfProps extends Omit<ModalProps, "title" | "children"> {
4
4
  contentTitle?: ReactNode;
5
5
  contentText?: ReactNode;
6
+ /**
7
+ * Trigger element (button/icon). When provided and `open` is omitted, the
8
+ * dialog owns its open state, so the caller does not have to keep one flag
9
+ * per confirmable action — which is otherwise impossible inside a list
10
+ * `map()`. The child's own `onClick` still fires first, and the click stops
11
+ * propagating so a trigger nested in a clickable row or card does not also
12
+ * activate that row.
13
+ */
14
+ children?: ReactElement<{
15
+ onClick?: (e: React.MouseEvent) => void;
16
+ }>;
6
17
  }
7
18
  declare const SecondConf: React.FC<SecondConfProps>;
8
19
  export default SecondConf;
@@ -1,47 +1,87 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["classNames", "contentTitle", "contentText"];
2
+ var _excluded = ["classNames", "contentTitle", "contentText", "children", "open", "onOk", "onCancel"];
3
3
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
4
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
5
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
7
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
8
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
9
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
10
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
11
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
12
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
13
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
8
14
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
9
15
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
10
- import React from "react";
16
+ import React, { cloneElement, useState } from "react";
11
17
  import styles from "./index.module.scss";
12
18
  import Icon from "../Icon";
13
19
  import Modal from "../Modal";
14
20
  import { jsx as _jsx } from "react/jsx-runtime";
15
21
  import { jsxs as _jsxs } from "react/jsx-runtime";
22
+ import { Fragment as _Fragment } from "react/jsx-runtime";
16
23
  var SecondConf = function SecondConf(props) {
17
24
  var classNames = props.classNames,
18
25
  contentTitle = props.contentTitle,
19
26
  contentText = props.contentText,
27
+ children = props.children,
28
+ open = props.open,
29
+ onOk = props.onOk,
30
+ onCancel = props.onCancel,
20
31
  modalConfig = _objectWithoutProperties(props, _excluded);
21
- return /*#__PURE__*/_jsxs(Modal, _objectSpread(_objectSpread({
22
- width: 800
23
- }, modalConfig), {}, {
24
- centered: true,
25
- className: styles.SecondConf,
26
- classNames: _objectSpread({
27
- body: "".concat(styles.body, " ").concat((classNames === null || classNames === void 0 ? void 0 : classNames.body) || "")
28
- }, classNames),
29
- maskClosable: false,
30
- mask: false,
31
- title: " ",
32
- children: [/*#__PURE__*/_jsx(Icon, {
33
- icon: "mingcute:question-line",
34
- className: styles.icon
35
- }), /*#__PURE__*/_jsxs("div", {
36
- className: styles.content,
37
- children: [/*#__PURE__*/_jsxs("div", {
38
- className: styles.title,
39
- children: ["\u786E\u8BA4", contentTitle, "\u5417\uFF1F"]
40
- }), /*#__PURE__*/_jsx("div", {
41
- className: styles.text,
42
- children: contentText
32
+ var _useState = useState(false),
33
+ _useState2 = _slicedToArray(_useState, 2),
34
+ selfOpen = _useState2[0],
35
+ setSelfOpen = _useState2[1];
36
+
37
+ // Controlled whenever `open` is supplied; self-managed only in trigger mode.
38
+ var isControlled = open !== undefined;
39
+ var visible = isControlled ? open : selfOpen;
40
+ var trigger = children && /*#__PURE__*/cloneElement(children, {
41
+ onClick: function onClick(e) {
42
+ var _children$props$onCli, _children$props;
43
+ e.stopPropagation();
44
+ (_children$props$onCli = (_children$props = children.props).onClick) === null || _children$props$onCli === void 0 || _children$props$onCli.call(_children$props, e);
45
+ if (!isControlled) setSelfOpen(true);
46
+ }
47
+ });
48
+ var handleOk = function handleOk(e) {
49
+ if (!isControlled) setSelfOpen(false);
50
+ onOk === null || onOk === void 0 || onOk(e);
51
+ };
52
+ var handleCancel = function handleCancel(e) {
53
+ if (!isControlled) setSelfOpen(false);
54
+ onCancel === null || onCancel === void 0 || onCancel(e);
55
+ };
56
+ return /*#__PURE__*/_jsxs(_Fragment, {
57
+ children: [trigger, /*#__PURE__*/_jsxs(Modal, _objectSpread(_objectSpread({
58
+ width: 800
59
+ }, modalConfig), {}, {
60
+ open: visible,
61
+ onOk: handleOk,
62
+ onCancel: handleCancel,
63
+ centered: true,
64
+ className: styles.SecondConf,
65
+ classNames: _objectSpread({
66
+ body: "".concat(styles.body, " ").concat((classNames === null || classNames === void 0 ? void 0 : classNames.body) || "")
67
+ }, classNames),
68
+ maskClosable: false,
69
+ mask: false,
70
+ title: " ",
71
+ children: [/*#__PURE__*/_jsx(Icon, {
72
+ icon: "mingcute:question-line",
73
+ className: styles.icon
74
+ }), /*#__PURE__*/_jsxs("div", {
75
+ className: styles.content,
76
+ children: [/*#__PURE__*/_jsxs("div", {
77
+ className: styles.title,
78
+ children: ["\u786E\u8BA4", contentTitle, "\u5417\uFF1F"]
79
+ }), /*#__PURE__*/_jsx("div", {
80
+ className: styles.text,
81
+ children: contentText
82
+ })]
43
83
  })]
44
- })]
45
- }));
84
+ }))]
85
+ });
46
86
  };
47
87
  export default SecondConf;