@canvas-components/react-list-table 0.3.20 → 0.3.21
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/README.md +2 -0
- package/dist/index.cjs +122 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +123 -9
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -321,6 +321,8 @@ import {
|
|
|
321
321
|
| `scrollTo` | `(options) => void` | 滚动到指定行 |
|
|
322
322
|
| `getDebugSnapshot` | `() => ListTableDebugSnapshot \| null` | 获取调试快照 |
|
|
323
323
|
|
|
324
|
+
导出文件名弹窗使用 `react-components` 的 `ReactModal`、`ReactInput`,默认开启,文件后缀不可编辑。通过表格 `exportOptions={{ fileName: "报表", promptFileName: false }}` 可配置默认名称并跳过弹窗;工具栏 `toolbar.exportOptions` 或实例 `exportXlsx` 的同名选项可覆盖默认配置。取消不会生成文件。XLSX 默认追加当前已显示的汇总行,传入 `includeSummary: false` 可关闭。
|
|
325
|
+
|
|
324
326
|
## 类型别名
|
|
325
327
|
|
|
326
328
|
| 类型 | 说明 |
|
package/dist/index.cjs
CHANGED
|
@@ -2680,6 +2680,58 @@ var toolButtonStyle = {
|
|
|
2680
2680
|
lineHeight: 1,
|
|
2681
2681
|
cursor: "pointer"
|
|
2682
2682
|
};
|
|
2683
|
+
function ReactListTableExportNameDialog({
|
|
2684
|
+
request
|
|
2685
|
+
}) {
|
|
2686
|
+
const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
|
|
2687
|
+
const [fileName, setFileName] = react.useState(
|
|
2688
|
+
extension ? request.fileName.slice(0, -extension.length) : request.fileName
|
|
2689
|
+
);
|
|
2690
|
+
const [invalid, setInvalid] = react.useState(false);
|
|
2691
|
+
const confirm = () => {
|
|
2692
|
+
if (!fileName.trim()) {
|
|
2693
|
+
setInvalid(true);
|
|
2694
|
+
return;
|
|
2695
|
+
}
|
|
2696
|
+
request.onConfirm(`${fileName.trim()}${extension}`);
|
|
2697
|
+
};
|
|
2698
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2699
|
+
reactComponents.ReactModal,
|
|
2700
|
+
{
|
|
2701
|
+
open: true,
|
|
2702
|
+
title: "\u5BFC\u51FA\u6587\u4EF6",
|
|
2703
|
+
width: 420,
|
|
2704
|
+
fullscreenable: false,
|
|
2705
|
+
onCancel: request.onCancel,
|
|
2706
|
+
onOk: confirm,
|
|
2707
|
+
okText: "\u5BFC\u51FA",
|
|
2708
|
+
cancelText: "\u53D6\u6D88",
|
|
2709
|
+
children: [
|
|
2710
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
2711
|
+
"\u6587\u4EF6\u540D\u79F0",
|
|
2712
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
2713
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2714
|
+
reactComponents.ReactInput,
|
|
2715
|
+
{
|
|
2716
|
+
autoFocus: true,
|
|
2717
|
+
value: fileName,
|
|
2718
|
+
placeholder: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0",
|
|
2719
|
+
onFocus: (event) => event.target.select(),
|
|
2720
|
+
onChange: (event) => {
|
|
2721
|
+
setFileName(event.target.value);
|
|
2722
|
+
setInvalid(false);
|
|
2723
|
+
},
|
|
2724
|
+
onPressEnter: confirm
|
|
2725
|
+
}
|
|
2726
|
+
),
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", style: { flexShrink: 0 }, children: extension })
|
|
2728
|
+
] })
|
|
2729
|
+
] }),
|
|
2730
|
+
invalid ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0" }) : null
|
|
2731
|
+
]
|
|
2732
|
+
}
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2683
2735
|
|
|
2684
2736
|
// src/features/editor/utils.ts
|
|
2685
2737
|
function toNumberValue(value) {
|
|
@@ -2781,12 +2833,14 @@ function ReactTableEditorOverlay(props) {
|
|
|
2781
2833
|
if (!input) {
|
|
2782
2834
|
return;
|
|
2783
2835
|
}
|
|
2784
|
-
focusAndSelectEditorInput(input);
|
|
2836
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2785
2837
|
}, [request]);
|
|
2786
2838
|
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactContentScaleProvider, { scale: contentZoom, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: editorHostRef, children: renderEditorByType(request, style) }, request.editorKey) });
|
|
2787
2839
|
}
|
|
2788
2840
|
function renderEditorByType(request, style) {
|
|
2789
2841
|
switch (request.config.valueType ?? "text") {
|
|
2842
|
+
case "tree-select":
|
|
2843
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TreeSelectEditor, { request, style });
|
|
2790
2844
|
case "cascader":
|
|
2791
2845
|
return /* @__PURE__ */ jsxRuntime.jsx(CascaderEditor, { request, style });
|
|
2792
2846
|
case "number":
|
|
@@ -2828,7 +2882,7 @@ function TextEditor(props) {
|
|
|
2828
2882
|
const skipBlurCommitRef = react.useRef(false);
|
|
2829
2883
|
react.useLayoutEffect(() => {
|
|
2830
2884
|
const input = hostRef.current?.querySelector("input");
|
|
2831
|
-
focusAndSelectEditorInput(input);
|
|
2885
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2832
2886
|
}, [request]);
|
|
2833
2887
|
react.useEffect(() => {
|
|
2834
2888
|
setValue(String(request.value ?? ""));
|
|
@@ -2868,7 +2922,7 @@ function NumberEditor(props) {
|
|
|
2868
2922
|
const skipBlurCommitRef = react.useRef(false);
|
|
2869
2923
|
react.useLayoutEffect(() => {
|
|
2870
2924
|
const input = hostRef.current?.querySelector("input");
|
|
2871
|
-
focusAndSelectEditorInput(input);
|
|
2925
|
+
focusAndSelectEditorInput(input, request.selectOnFocus);
|
|
2872
2926
|
}, [request]);
|
|
2873
2927
|
react.useEffect(() => {
|
|
2874
2928
|
setValue(toNumberValue(request.value));
|
|
@@ -3077,14 +3131,56 @@ function DateEditor(props) {
|
|
|
3077
3131
|
}
|
|
3078
3132
|
) });
|
|
3079
3133
|
}
|
|
3080
|
-
function
|
|
3134
|
+
function TreeSelectEditor({
|
|
3081
3135
|
request,
|
|
3082
3136
|
style
|
|
3083
3137
|
}) {
|
|
3084
3138
|
const [value, setValue] = react.useState(
|
|
3085
|
-
|
|
3139
|
+
request.value ?? null
|
|
3086
3140
|
);
|
|
3087
3141
|
const skipBlurCommitRef = react.useRef(false);
|
|
3142
|
+
react.useEffect(() => {
|
|
3143
|
+
setValue(request.value ?? null);
|
|
3144
|
+
}, [request.value]);
|
|
3145
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3146
|
+
reactComponents.ReactTreeSelect,
|
|
3147
|
+
{
|
|
3148
|
+
autoFocus: true,
|
|
3149
|
+
value,
|
|
3150
|
+
treeData: request.config.treeData,
|
|
3151
|
+
multiple: request.config.multiple,
|
|
3152
|
+
showSearch: request.config.showSearch,
|
|
3153
|
+
treeDefaultExpandAll: request.config.treeDefaultExpandAll,
|
|
3154
|
+
treeDefaultExpandedKeys: request.config.treeDefaultExpandedKeys,
|
|
3155
|
+
allowClear: request.config.allowClear,
|
|
3156
|
+
placeholder: request.config.placeholder,
|
|
3157
|
+
style: getEditorInputStyle(request),
|
|
3158
|
+
onChange: (next, _nodes, info) => {
|
|
3159
|
+
setValue(next);
|
|
3160
|
+
request.onChange(next);
|
|
3161
|
+
if (info.complete && info.trigger !== "clear") {
|
|
3162
|
+
skipBlurCommitRef.current = true;
|
|
3163
|
+
request.onCommit();
|
|
3164
|
+
}
|
|
3165
|
+
},
|
|
3166
|
+
onBlur: (event) => handleEditorBlur(event, skipBlurCommitRef, request),
|
|
3167
|
+
onKeyDown: (event) => {
|
|
3168
|
+
if (event.key === "Tab")
|
|
3169
|
+
handleEditorNavigationKey(event, request, skipBlurCommitRef);
|
|
3170
|
+
if (event.key === "Escape") {
|
|
3171
|
+
skipBlurCommitRef.current = true;
|
|
3172
|
+
handleEditorEscapeKey(event, request);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
3176
|
+
) });
|
|
3177
|
+
}
|
|
3178
|
+
function CascaderEditor({
|
|
3179
|
+
request,
|
|
3180
|
+
style
|
|
3181
|
+
}) {
|
|
3182
|
+
const [value, setValue] = react.useState(Array.isArray(request.value) ? request.value : []);
|
|
3183
|
+
const skipBlurCommitRef = react.useRef(false);
|
|
3088
3184
|
react.useEffect(() => {
|
|
3089
3185
|
setValue(Array.isArray(request.value) ? request.value : []);
|
|
3090
3186
|
}, [request.value]);
|
|
@@ -3098,6 +3194,8 @@ function CascaderEditor({
|
|
|
3098
3194
|
showSearch: request.config.showSearch,
|
|
3099
3195
|
allowClear: request.config.allowClear,
|
|
3100
3196
|
changeOnSelect: request.config.changeOnSelect,
|
|
3197
|
+
multiple: request.config.multiple,
|
|
3198
|
+
showCheckedStrategy: request.config.showCheckedStrategy,
|
|
3101
3199
|
expandTrigger: request.config.expandTrigger,
|
|
3102
3200
|
displayRender: request.config.displayRender,
|
|
3103
3201
|
style: getEditorInputStyle(request),
|
|
@@ -3451,13 +3549,14 @@ function handleRangeInputTab(event) {
|
|
|
3451
3549
|
focusAndSelectEditorInput(nextInput);
|
|
3452
3550
|
return true;
|
|
3453
3551
|
}
|
|
3454
|
-
function focusAndSelectEditorInput(input) {
|
|
3552
|
+
function focusAndSelectEditorInput(input, selectOnFocus = true) {
|
|
3455
3553
|
if (!input) {
|
|
3456
3554
|
return;
|
|
3457
3555
|
}
|
|
3458
3556
|
input.focus();
|
|
3459
3557
|
try {
|
|
3460
|
-
input.select();
|
|
3558
|
+
if (selectOnFocus) input.select();
|
|
3559
|
+
else input.setSelectionRange(input.value.length, input.value.length);
|
|
3461
3560
|
} catch {
|
|
3462
3561
|
}
|
|
3463
3562
|
}
|
|
@@ -4223,9 +4322,14 @@ function useReactListTableState(options) {
|
|
|
4223
4322
|
const [searchRequest, setSearchRequest] = react.useState(null);
|
|
4224
4323
|
const [imagePreviewRequest, setImagePreviewRequest] = react.useState(null);
|
|
4225
4324
|
const [dangerConfirmRequest, setDangerConfirmRequest] = react.useState(null);
|
|
4325
|
+
const [exportNameRequest, setExportNameRequest] = react.useState(null);
|
|
4226
4326
|
const uiOptions = react.useMemo(
|
|
4227
4327
|
() => ({
|
|
4228
4328
|
...options.ui,
|
|
4329
|
+
onExportNameRequest: (request) => {
|
|
4330
|
+
setExportNameRequest(request);
|
|
4331
|
+
options.ui?.onExportNameRequest?.(request);
|
|
4332
|
+
},
|
|
4229
4333
|
onEditorRequest: (request) => {
|
|
4230
4334
|
setEditorRequest(request);
|
|
4231
4335
|
options.ui?.onEditorRequest?.(request);
|
|
@@ -4293,6 +4397,7 @@ function useReactListTableState(options) {
|
|
|
4293
4397
|
setSearchRequest(null);
|
|
4294
4398
|
setImagePreviewRequest(null);
|
|
4295
4399
|
setDangerConfirmRequest(null);
|
|
4400
|
+
setExportNameRequest(null);
|
|
4296
4401
|
};
|
|
4297
4402
|
}, []);
|
|
4298
4403
|
react.useEffect(() => {
|
|
@@ -4314,6 +4419,7 @@ function useReactListTableState(options) {
|
|
|
4314
4419
|
searchRequest,
|
|
4315
4420
|
imagePreviewRequest,
|
|
4316
4421
|
dangerConfirmRequest,
|
|
4422
|
+
exportNameRequest,
|
|
4317
4423
|
closeDangerConfirmRequest: () => {
|
|
4318
4424
|
setDangerConfirmRequest(null);
|
|
4319
4425
|
options.ui?.onDangerConfirmRequest?.(null);
|
|
@@ -4418,7 +4524,8 @@ function ReactListTableInner(props, ref) {
|
|
|
4418
4524
|
rowDrag,
|
|
4419
4525
|
debug,
|
|
4420
4526
|
title,
|
|
4421
|
-
toolbar
|
|
4527
|
+
toolbar,
|
|
4528
|
+
exportOptions
|
|
4422
4529
|
} = props;
|
|
4423
4530
|
const inheritedDebugEnabled = useReactListTableDebugEnabled();
|
|
4424
4531
|
const resolvedDebug = react.useMemo(
|
|
@@ -4459,6 +4566,7 @@ function ReactListTableInner(props, ref) {
|
|
|
4459
4566
|
);
|
|
4460
4567
|
const options = react.useMemo(() => {
|
|
4461
4568
|
const nextOptions = buildListTableOptions({
|
|
4569
|
+
exportOptions,
|
|
4462
4570
|
width,
|
|
4463
4571
|
height,
|
|
4464
4572
|
emptyText,
|
|
@@ -4520,6 +4628,7 @@ function ReactListTableInner(props, ref) {
|
|
|
4520
4628
|
}
|
|
4521
4629
|
};
|
|
4522
4630
|
}, [
|
|
4631
|
+
exportOptions,
|
|
4523
4632
|
width,
|
|
4524
4633
|
height,
|
|
4525
4634
|
emptyText,
|
|
@@ -4575,6 +4684,7 @@ function ReactListTableInner(props, ref) {
|
|
|
4575
4684
|
searchRequest,
|
|
4576
4685
|
imagePreviewRequest,
|
|
4577
4686
|
dangerConfirmRequest,
|
|
4687
|
+
exportNameRequest,
|
|
4578
4688
|
closeDangerConfirmRequest
|
|
4579
4689
|
} = useReactListTableState(options);
|
|
4580
4690
|
const hasPagination = paginationConfig != null;
|
|
@@ -4754,6 +4864,10 @@ function ReactListTableInner(props, ref) {
|
|
|
4754
4864
|
/* @__PURE__ */ jsxRuntime.jsx(ReactListTableSearchDialog, { request: searchRequest }),
|
|
4755
4865
|
document.body
|
|
4756
4866
|
) : null,
|
|
4867
|
+
exportNameRequest ? reactDom.createPortal(
|
|
4868
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReactListTableExportNameDialog, { request: exportNameRequest }),
|
|
4869
|
+
document.body
|
|
4870
|
+
) : null,
|
|
4757
4871
|
dangerConfirmRequest ? reactDom.createPortal(
|
|
4758
4872
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4759
4873
|
ReactTableDangerConfirmView,
|