@canvas-components/react-list-table 0.3.36 → 0.3.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3573,6 +3573,37 @@ var toolButtonStyle = {
3573
3573
  lineHeight: 1,
3574
3574
  cursor: "pointer"
3575
3575
  };
3576
+ function readExportCache(storageKey) {
3577
+ if (!storageKey) return null;
3578
+ try {
3579
+ const value = JSON.parse(localStorage.getItem(`canvas-table-export:${storageKey}`) ?? "null");
3580
+ if (value?.version !== 1 || !Array.isArray(value.rows) || !Array.isArray(value.selectedKeys) || !value.selectedKeys.every((key) => typeof key === "string") || typeof value.includeSummary !== "boolean") return null;
3581
+ if (!value.rows.every((row) => row && typeof row.key === "string" && ["default", "ascend", "descend"].includes(row.sortOrder) && summaryOptions.some((option) => option.value === row.summaryType) && roundingOptions.some((option) => option.value === row.roundingMode) && ["yes", "no"].includes(row.showTypePrefix) && ["yes", "no"].includes(row.preserveTrailingZeros) && (row.precision == null || Number.isInteger(row.precision) && row.precision >= 0 && row.precision <= 20) && (row.sortIndex == null || Number.isFinite(row.sortIndex)) && (row.sortPriority == null || Number.isFinite(row.sortPriority)))) return null;
3582
+ return value;
3583
+ } catch {
3584
+ return null;
3585
+ }
3586
+ }
3587
+ function writeExportCache(storageKey, value) {
3588
+ if (!storageKey) return;
3589
+ try {
3590
+ const key = `canvas-table-export:${storageKey}`;
3591
+ if (value) localStorage.setItem(key, JSON.stringify(value));
3592
+ else localStorage.removeItem(key);
3593
+ } catch {
3594
+ }
3595
+ }
3596
+ function restoreExportRows(columns, cache) {
3597
+ const current = new Map(createExportDialogRows(columns).map((row) => [row.key, row]));
3598
+ const rows = [];
3599
+ cache?.rows.forEach((saved) => {
3600
+ const row = current.get(saved.key);
3601
+ if (!row) return;
3602
+ rows.push({ ...saved, key: row.key, title: row.title });
3603
+ current.delete(saved.key);
3604
+ });
3605
+ return [...rows, ...current.values()];
3606
+ }
3576
3607
  var sortOptions = [
3577
3608
  { value: "default", label: "\u9ED8\u8BA4" },
3578
3609
  { value: "ascend", label: "\u5347\u5E8F" },
@@ -3644,18 +3675,34 @@ function buildExportDialogSettings(rows, selectedKeys, includeSummary) {
3644
3675
  function ReactListTableExportNameDialog({
3645
3676
  request,
3646
3677
  onClose,
3647
- renderTable
3678
+ renderTable,
3679
+ storageKey
3648
3680
  }) {
3649
3681
  const tableId = react.useId();
3682
+ const tableHostRef = react.useRef(null);
3683
+ const [tableWidth, setTableWidth] = react.useState(0);
3684
+ react.useEffect(() => {
3685
+ const host = tableHostRef.current;
3686
+ if (!host || typeof ResizeObserver === "undefined") return;
3687
+ const update = () => setTableWidth(host.clientWidth);
3688
+ update();
3689
+ const observer = new ResizeObserver(update);
3690
+ observer.observe(host);
3691
+ return () => observer.disconnect();
3692
+ }, []);
3650
3693
  const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
3651
3694
  const [fileName, setFileName] = react.useState(
3652
3695
  extension ? request.fileName.slice(0, -extension.length) : request.fileName
3653
3696
  );
3654
- const [rows, setRows] = react.useState(() => createExportDialogRows(request.columns ?? []));
3697
+ const [cached] = react.useState(() => readExportCache(storageKey));
3698
+ const [cacheEnabled, setCacheEnabled] = react.useState(Boolean(storageKey));
3699
+ const [rows, setRows] = react.useState(() => restoreExportRows(request.columns ?? [], cached));
3655
3700
  const [selectedKeys, setSelectedKeys] = react.useState(
3656
- () => (request.columns ?? []).filter((column) => column.selected !== false).map((column) => column.key)
3701
+ () => (request.columns ?? []).filter((column) => cached?.rows.some((row) => row.key === column.key) ? cached.selectedKeys.includes(column.key) : column.selected !== false).map((column) => column.key)
3702
+ );
3703
+ const [includeSummary, setIncludeSummary] = react.useState(
3704
+ () => cached?.includeSummary ?? (request.includeSummary === true || (request.columns?.some((column) => column.summary.type !== "none") ?? false))
3657
3705
  );
3658
- const [includeSummary, setIncludeSummary] = react.useState(request.includeSummary ?? false);
3659
3706
  const [error, setError] = react.useState("");
3660
3707
  const columns = react.useMemo(
3661
3708
  () => [
@@ -3733,9 +3780,16 @@ function ReactListTableExportNameDialog({
3733
3780
  ],
3734
3781
  [includeSummary, request.columns]
3735
3782
  );
3783
+ const fittedColumns = react.useMemo(
3784
+ () => fitExportDialogColumns(columns, tableWidth),
3785
+ [columns, tableWidth]
3786
+ );
3736
3787
  const confirm = () => {
3737
3788
  if (!fileName.trim()) return setError("\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0");
3738
3789
  if (request.columns && !selectedKeys.length) return setError("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u5217");
3790
+ if (request.columns && cacheEnabled) {
3791
+ writeExportCache(storageKey, { version: 1, rows, selectedKeys: selectedKeys.map(String), includeSummary });
3792
+ }
3739
3793
  request.onConfirm(
3740
3794
  `${fileName.trim()}${extension}`,
3741
3795
  request.columns ? buildExportDialogSettings(rows, selectedKeys, includeSummary) : void 0
@@ -3747,7 +3801,7 @@ function ReactListTableExportNameDialog({
3747
3801
  {
3748
3802
  open: true,
3749
3803
  title: "\u5BFC\u51FA\u6587\u4EF6",
3750
- width: request.columns ? 1180 : 420,
3804
+ width: request.columns ? includeSummary ? 1320 : 1180 : 420,
3751
3805
  fullscreenable: false,
3752
3806
  onOk: confirm,
3753
3807
  okText: "\u5BFC\u51FA",
@@ -3780,6 +3834,27 @@ function ReactListTableExportNameDialog({
3780
3834
  request.columns ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 16 }, children: [
3781
3835
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 16, marginBottom: 8 }, children: [
3782
3836
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600 }, children: "\u5BFC\u51FA\u8868\u683C\u5217" }),
3837
+ storageKey ? /* @__PURE__ */ jsxRuntime.jsxs(
3838
+ "label",
3839
+ {
3840
+ style: { display: "inline-flex", alignItems: "center", gap: 6 },
3841
+ title: "\u5BFC\u51FA\u65F6\u4FDD\u5B58\u914D\u7F6E\uFF0C\u4E0B\u6B21\u6253\u5F00\u81EA\u52A8\u6062\u590D\uFF1B\u53D6\u6D88\u52FE\u9009\u6E05\u9664\u7F13\u5B58",
3842
+ children: [
3843
+ /* @__PURE__ */ jsxRuntime.jsx(
3844
+ reactComponents.ReactCheckbox,
3845
+ {
3846
+ checked: cacheEnabled,
3847
+ "aria-label": "\u7F13\u5B58\u5BFC\u51FA\u914D\u7F6E",
3848
+ onChange: (event) => {
3849
+ setCacheEnabled(event.target.checked);
3850
+ if (!event.target.checked) writeExportCache(storageKey, null);
3851
+ }
3852
+ }
3853
+ ),
3854
+ "\u7F13\u5B58\u5BFC\u51FA\u914D\u7F6E"
3855
+ ]
3856
+ }
3857
+ ) : null,
3783
3858
  /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
3784
3859
  /* @__PURE__ */ jsxRuntime.jsx(
3785
3860
  reactComponents.ReactCheckbox,
@@ -3792,9 +3867,9 @@ function ReactListTableExportNameDialog({
3792
3867
  "\u5BFC\u51FA\u6C47\u603B\u884C"
3793
3868
  ] })
3794
3869
  ] }),
3795
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "min(45vh, 520px)", minHeight: 250, overflow: "hidden" }, children: renderTable({
3870
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: tableHostRef, style: { height: "min(45vh, 520px)", minHeight: 250, overflow: "hidden" }, children: renderTable({
3796
3871
  tableId,
3797
- columns,
3872
+ columns: fittedColumns,
3798
3873
  dataSource: rows,
3799
3874
  rowKey: "key",
3800
3875
  rowHeight: 42,
@@ -3839,6 +3914,17 @@ function ReactListTableExportNameDialog({
3839
3914
  }
3840
3915
  );
3841
3916
  }
3917
+ function fitExportDialogColumns(columns, availableWidth) {
3918
+ if (availableWidth <= 0) return columns;
3919
+ const totalWidth = (items) => items.reduce((sum, column) => sum + (column.key === listTable.ROW_SELECTION_COLUMN.key ? 0 : column.children?.length ? totalWidth(column.children) : Number(column.width) || 160), 0);
3920
+ const ratio = Math.min(1, Math.max(availableWidth - 54 - 32, 1) / totalWidth(columns));
3921
+ const fit = (items) => items.map((column) => {
3922
+ if (column.key === listTable.ROW_SELECTION_COLUMN.key) return column;
3923
+ if (column.children?.length) return { ...column, children: fit(column.children) };
3924
+ return { ...column, width: Math.max(1, Math.floor((Number(column.width) || 160) * ratio)), minWidth: 1 };
3925
+ });
3926
+ return fit(columns);
3927
+ }
3842
3928
 
3843
3929
  // src/features/editor/utils.ts
3844
3930
  function toNumberValue(value) {
@@ -5003,14 +5089,18 @@ function SortableList(props) {
5003
5089
  );
5004
5090
  react.useEffect(() => {
5005
5091
  if (!dragState) return;
5006
- const handleMove = (event) => {
5092
+ const scrollContainer = props.scrollContainerRef?.current;
5093
+ let frameId = 0;
5094
+ let lastTime = null;
5095
+ const updateTarget = () => {
5007
5096
  const current = dragRef.current;
5008
5097
  if (!current) return;
5009
5098
  const target = resolveClosestSortableItem({
5010
5099
  items,
5011
5100
  parentKey: current.source.parentKey,
5012
5101
  layouts: current.layouts,
5013
- overlayCenterY: event.clientY - current.offsetY + current.height / 2
5102
+ // 保留拖拽开始时的布局,补偿滚动位移,避免受行交换动画影响。
5103
+ overlayCenterY: current.pointerY - current.offsetY + current.height / 2 + current.rootTop - (rootRef.current?.getBoundingClientRect().top ?? current.rootTop)
5014
5104
  });
5015
5105
  if (target) {
5016
5106
  current.target = target;
@@ -5018,12 +5108,44 @@ function SortableList(props) {
5018
5108
  setDragState({
5019
5109
  sourceKey: current.source.key,
5020
5110
  targetKey: current.target.key,
5021
- pointerY: event.clientY
5111
+ pointerY: current.pointerY
5022
5112
  });
5023
5113
  };
5024
- const handleEnd = () => {
5114
+ const handleMove = (event) => {
5115
+ const current = dragRef.current;
5116
+ if (!current || event.pointerId !== current.pointerId) return;
5117
+ current.pointerY = event.clientY;
5118
+ updateTarget();
5119
+ };
5120
+ const tick = (time) => {
5121
+ const current = dragRef.current;
5122
+ if (!current) return;
5123
+ const elapsed = lastTime == null ? 0 : Math.min(time - lastTime, 50);
5124
+ lastTime = time;
5125
+ if (scrollContainer) {
5126
+ const rect = scrollContainer.getBoundingClientRect();
5127
+ const top = rect.top + scrollContainer.clientTop;
5128
+ const height = scrollContainer.clientHeight;
5129
+ const edge = Math.min(40, height / 2);
5130
+ const bottom = top + height;
5131
+ const direction = edge <= 0 ? 0 : current.pointerY < top + edge ? -Math.min(1, (top + edge - current.pointerY) / edge) : current.pointerY > bottom - edge ? Math.min(1, (current.pointerY - bottom + edge) / edge) : 0;
5132
+ if (direction) {
5133
+ scrollContainer.scrollTop = Math.max(
5134
+ 0,
5135
+ Math.min(
5136
+ scrollContainer.scrollHeight - height,
5137
+ scrollContainer.scrollTop + direction * elapsed * 0.5
5138
+ )
5139
+ );
5140
+ updateTarget();
5141
+ }
5142
+ }
5143
+ frameId = requestAnimationFrame(tick);
5144
+ };
5145
+ const finish = (commit) => {
5025
5146
  const current = dragRef.current;
5026
- if (current && current.source.key !== current.target.key) {
5147
+ cancelAnimationFrame(frameId);
5148
+ if (commit && current && current.source.key !== current.target.key) {
5027
5149
  const siblings = items.filter(
5028
5150
  (item) => item.parentKey === current.source.parentKey
5029
5151
  );
@@ -5041,15 +5163,30 @@ function SortableList(props) {
5041
5163
  document.body.classList.remove("react-list-table-sorting");
5042
5164
  document.body.style.removeProperty("user-select");
5043
5165
  };
5166
+ const handleEnd = (event) => {
5167
+ if (event.pointerId !== dragRef.current?.pointerId) return;
5168
+ handleMove(event);
5169
+ finish(true);
5170
+ };
5171
+ const handleCancel = (event) => {
5172
+ if (event.pointerId === dragRef.current?.pointerId) finish(false);
5173
+ };
5174
+ const handleBlur = () => finish(false);
5175
+ frameId = requestAnimationFrame(tick);
5176
+ scrollContainer?.addEventListener("scroll", updateTarget);
5044
5177
  window.addEventListener("pointermove", handleMove);
5045
- window.addEventListener("pointerup", handleEnd, { once: true });
5046
- window.addEventListener("pointercancel", handleEnd, { once: true });
5178
+ window.addEventListener("pointerup", handleEnd);
5179
+ window.addEventListener("pointercancel", handleCancel);
5180
+ window.addEventListener("blur", handleBlur);
5047
5181
  return () => {
5182
+ cancelAnimationFrame(frameId);
5183
+ scrollContainer?.removeEventListener("scroll", updateTarget);
5048
5184
  window.removeEventListener("pointermove", handleMove);
5049
5185
  window.removeEventListener("pointerup", handleEnd);
5050
- window.removeEventListener("pointercancel", handleEnd);
5186
+ window.removeEventListener("pointercancel", handleCancel);
5187
+ window.removeEventListener("blur", handleBlur);
5051
5188
  };
5052
- }, [dragState != null, items, onOrderChange]);
5189
+ }, [dragState != null, items, onOrderChange, props.scrollContainerRef]);
5053
5190
  const sourceIndex = dragState ? items.findIndex((item) => item.key === dragState.sourceKey) : -1;
5054
5191
  const targetIndex = dragState ? items.findIndex((item) => item.key === dragState.targetKey) : -1;
5055
5192
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, children: [
@@ -5068,7 +5205,7 @@ function SortableList(props) {
5068
5205
  style,
5069
5206
  children: props.renderItem(item, {
5070
5207
  onPointerDown: (event) => {
5071
- if (event.button !== 0) return;
5208
+ if (event.button !== 0 || dragRef.current) return;
5072
5209
  const row = event.currentTarget.closest(
5073
5210
  "[data-sortable-key]"
5074
5211
  );
@@ -5081,7 +5218,10 @@ function SortableList(props) {
5081
5218
  offsetY: event.clientY - rect.top,
5082
5219
  width: rect.width,
5083
5220
  left: rect.left,
5084
- height: rect.height
5221
+ height: rect.height,
5222
+ pointerId: event.pointerId,
5223
+ pointerY: event.clientY,
5224
+ rootTop: rootRef.current?.getBoundingClientRect().top ?? 0
5085
5225
  };
5086
5226
  setDragState({
5087
5227
  sourceKey: item.key,
@@ -5168,13 +5308,14 @@ function resolveSortableTransform(index, sourceIndex, targetIndex, height) {
5168
5308
  }
5169
5309
 
5170
5310
  // src/features/toolbar/style.css
5171
- styleInject(".react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: #374151;\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu {\n width: max-content;\n min-width: 0;\n padding: 8px;\n border-radius: 8px;\n}\n.react-list-table-tool-menu-check {\n width: 16px;\n flex: 0 0 16px;\n margin-right: 6px;\n text-align: center;\n}\n.react-list-table-tool-menu button:hover {\n background: #f3f4f6;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-sort-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n");
5311
+ styleInject(".react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: #374151;\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu {\n width: max-content;\n min-width: 0;\n padding: 8px;\n border-radius: 8px;\n}\n.react-list-table-tool-menu-check {\n width: 16px;\n flex: 0 0 16px;\n margin-right: 6px;\n text-align: center;\n}\n.react-list-table-tool-menu button:hover {\n background: #f3f4f6;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-sort-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n touch-action: none;\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n");
5172
5312
  function ReactTableToolbar(props) {
5173
5313
  const { toolbar, title } = props;
5174
5314
  const [densityOpen, setDensityOpen] = react.useState(false);
5175
5315
  const [settingOpen, setSettingOpen] = react.useState(false);
5176
5316
  const [isFullscreen, setIsFullscreen] = react.useState(false);
5177
5317
  const rootRef = react.useRef(null);
5318
+ const columnSettingsBodyRef = react.useRef(null);
5178
5319
  const hasToolbar = toolbar !== void 0 && toolbar !== false;
5179
5320
  react.useEffect(() => {
5180
5321
  const close = (event) => {
@@ -5313,116 +5454,124 @@ function ReactTableToolbar(props) {
5313
5454
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto" }, children: config.columnSettingHeaderExtra }),
5314
5455
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: props.onResetColumns, children: "\u91CD\u7F6E" })
5315
5456
  ] }),
5316
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "react-list-table-column-setting-body canvas-react-scrollbar", children: /* @__PURE__ */ jsxRuntime.jsx(
5317
- SortableList,
5457
+ /* @__PURE__ */ jsxRuntime.jsx(
5458
+ "div",
5318
5459
  {
5319
- items: flattenColumns(props.columns),
5320
- onOrderChange: props.onColumnOrderChange,
5321
- renderItem: (column, handleProps) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-column-item", children: [
5322
- /* @__PURE__ */ jsxRuntime.jsxs(
5323
- "span",
5324
- {
5325
- className: "react-list-table-column-main",
5326
- style: { paddingLeft: column.level * 16 },
5327
- children: [
5460
+ ref: columnSettingsBodyRef,
5461
+ className: "react-list-table-column-setting-body canvas-react-scrollbar",
5462
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5463
+ SortableList,
5464
+ {
5465
+ scrollContainerRef: columnSettingsBodyRef,
5466
+ items: flattenColumns(props.columns),
5467
+ onOrderChange: props.onColumnOrderChange,
5468
+ renderItem: (column, handleProps) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-column-item", children: [
5469
+ /* @__PURE__ */ jsxRuntime.jsxs(
5470
+ "span",
5471
+ {
5472
+ className: "react-list-table-column-main",
5473
+ style: { paddingLeft: column.level * 16 },
5474
+ children: [
5475
+ /* @__PURE__ */ jsxRuntime.jsx(
5476
+ "span",
5477
+ {
5478
+ className: "react-list-table-column-drag",
5479
+ ...handleProps,
5480
+ onClick: (event) => {
5481
+ event.preventDefault();
5482
+ event.stopPropagation();
5483
+ },
5484
+ children: /* @__PURE__ */ jsxRuntime.jsx(HolderOutlined, {})
5485
+ }
5486
+ ),
5487
+ /* @__PURE__ */ jsxRuntime.jsx(
5488
+ "input",
5489
+ {
5490
+ type: "checkbox",
5491
+ checked: !column.hidden,
5492
+ disabled: column.disableHide,
5493
+ onChange: (event) => props.onColumnVisibilityChange(
5494
+ column.key,
5495
+ event.target.checked
5496
+ )
5497
+ }
5498
+ ),
5499
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "react-list-table-column-label", children: column.label })
5500
+ ]
5501
+ }
5502
+ ),
5503
+ !column.isGroup ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "react-list-table-column-actions", children: [
5328
5504
  /* @__PURE__ */ jsxRuntime.jsx(
5329
- "span",
5505
+ reactComponents.ReactNumberInput,
5330
5506
  {
5331
- className: "react-list-table-column-drag",
5332
- ...handleProps,
5333
- onClick: (event) => {
5334
- event.preventDefault();
5335
- event.stopPropagation();
5336
- },
5337
- children: /* @__PURE__ */ jsxRuntime.jsx(HolderOutlined, {})
5507
+ className: "react-list-table-column-width-input",
5508
+ min: column.minWidth,
5509
+ max: column.maxWidth,
5510
+ value: column.width,
5511
+ allowClear: false,
5512
+ "aria-label": `${column.label}\u5217\u5BBD`,
5513
+ style: { width: 80, height: 24 },
5514
+ onChange: (width) => {
5515
+ if (width != null && Number.isFinite(width) && width > 0 && (column.minWidth == null || width >= column.minWidth) && (column.maxWidth == null || width <= column.maxWidth)) {
5516
+ props.onColumnWidthChange(
5517
+ column.key,
5518
+ width
5519
+ );
5520
+ }
5521
+ }
5338
5522
  }
5339
5523
  ),
5340
5524
  /* @__PURE__ */ jsxRuntime.jsx(
5341
- "input",
5525
+ reactComponents.ReactSelect,
5342
5526
  {
5343
- type: "checkbox",
5344
- checked: !column.hidden,
5345
- disabled: column.disableHide,
5346
- onChange: (event) => props.onColumnVisibilityChange(
5527
+ className: "react-list-table-column-sort-input",
5528
+ value: props.sortState.find(
5529
+ (item) => item.key === column.key
5530
+ )?.order ?? "default",
5531
+ options: [
5532
+ { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
5533
+ { label: "\u5347\u5E8F", value: "ascend" },
5534
+ { label: "\u964D\u5E8F", value: "descend" }
5535
+ ],
5536
+ disabled: !column.sortable,
5537
+ allowClear: false,
5538
+ showSearch: false,
5539
+ style: { width: "100%", height: 24 },
5540
+ "aria-label": `${column.label}\u6392\u5E8F\u65B9\u5F0F`,
5541
+ onChange: (value) => props.onColumnSortChange(
5347
5542
  column.key,
5348
- event.target.checked
5543
+ value === "ascend" || value === "descend" ? value : null
5349
5544
  )
5350
5545
  }
5351
5546
  ),
5352
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "react-list-table-column-label", children: column.label })
5353
- ]
5354
- }
5355
- ),
5356
- !column.isGroup ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "react-list-table-column-actions", children: [
5357
- /* @__PURE__ */ jsxRuntime.jsx(
5358
- reactComponents.ReactNumberInput,
5359
- {
5360
- className: "react-list-table-column-width-input",
5361
- min: column.minWidth,
5362
- max: column.maxWidth,
5363
- value: column.width,
5364
- allowClear: false,
5365
- "aria-label": `${column.label}\u5217\u5BBD`,
5366
- style: { width: 80, height: 24 },
5367
- onChange: (width) => {
5368
- if (width != null && Number.isFinite(width) && width > 0 && (column.minWidth == null || width >= column.minWidth) && (column.maxWidth == null || width <= column.maxWidth)) {
5369
- props.onColumnWidthChange(
5370
- column.key,
5371
- width
5372
- );
5547
+ /* @__PURE__ */ jsxRuntime.jsx(
5548
+ reactComponents.ReactSelect,
5549
+ {
5550
+ className: "react-list-table-column-fixed-input",
5551
+ value: column.fixed ?? "none",
5552
+ options: [
5553
+ { label: "\u4E0D\u56FA\u5B9A", value: "none" },
5554
+ { label: "\u56FA\u5B9A\u5DE6\u4FA7", value: "left" },
5555
+ { label: "\u56FA\u5B9A\u53F3\u4FA7", value: "right" }
5556
+ ],
5557
+ allowClear: false,
5558
+ showSearch: false,
5559
+ style: { width: "100%", height: 24 },
5560
+ "aria-label": `${column.label}\u56FA\u5B9A\u65B9\u5411`,
5561
+ onChange: (value) => {
5562
+ props.onColumnFixedChange(
5563
+ column.key,
5564
+ value === "left" || value === "right" ? value : void 0
5565
+ );
5566
+ }
5373
5567
  }
5374
- }
5375
- }
5376
- ),
5377
- /* @__PURE__ */ jsxRuntime.jsx(
5378
- reactComponents.ReactSelect,
5379
- {
5380
- className: "react-list-table-column-sort-input",
5381
- value: props.sortState.find(
5382
- (item) => item.key === column.key
5383
- )?.order ?? "default",
5384
- options: [
5385
- { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
5386
- { label: "\u5347\u5E8F", value: "ascend" },
5387
- { label: "\u964D\u5E8F", value: "descend" }
5388
- ],
5389
- disabled: !column.sortable,
5390
- allowClear: false,
5391
- showSearch: false,
5392
- style: { width: "100%", height: 24 },
5393
- "aria-label": `${column.label}\u6392\u5E8F\u65B9\u5F0F`,
5394
- onChange: (value) => props.onColumnSortChange(
5395
- column.key,
5396
- value === "ascend" || value === "descend" ? value : null
5397
5568
  )
5398
- }
5399
- ),
5400
- /* @__PURE__ */ jsxRuntime.jsx(
5401
- reactComponents.ReactSelect,
5402
- {
5403
- className: "react-list-table-column-fixed-input",
5404
- value: column.fixed ?? "none",
5405
- options: [
5406
- { label: "\u4E0D\u56FA\u5B9A", value: "none" },
5407
- { label: "\u56FA\u5B9A\u5DE6\u4FA7", value: "left" },
5408
- { label: "\u56FA\u5B9A\u53F3\u4FA7", value: "right" }
5409
- ],
5410
- allowClear: false,
5411
- showSearch: false,
5412
- style: { width: "100%", height: 24 },
5413
- "aria-label": `${column.label}\u56FA\u5B9A\u65B9\u5411`,
5414
- onChange: (value) => {
5415
- props.onColumnFixedChange(
5416
- column.key,
5417
- value === "left" || value === "right" ? value : void 0
5418
- );
5419
- }
5420
- }
5421
- )
5422
- ] }) : null
5423
- ] })
5569
+ ] }) : null
5570
+ ] })
5571
+ }
5572
+ )
5424
5573
  }
5425
- ) })
5574
+ )
5426
5575
  ]
5427
5576
  }
5428
5577
  ) : null
@@ -6203,6 +6352,7 @@ function ReactListTableInner(props, ref) {
6203
6352
  ReactListTableExportNameDialog,
6204
6353
  {
6205
6354
  request: exportNameRequest,
6355
+ storageKey: storageKey ? `list:${storageKey}` : void 0,
6206
6356
  onClose: closeExportNameRequest,
6207
6357
  renderTable: (tableProps) => /* @__PURE__ */ jsxRuntime.jsx(ReactListTable, { ...tableProps })
6208
6358
  }
package/dist/index.d.cts CHANGED
@@ -111,9 +111,11 @@ interface ExportDialogRow {
111
111
  preserveTrailingZeros: "yes" | "no";
112
112
  }
113
113
  /** 使用 ReactListTable 承载大量导出列的弹窗。 */
114
- declare function ReactListTableExportNameDialog({ request, onClose, renderTable, }: {
114
+ declare function ReactListTableExportNameDialog({ request, onClose, renderTable, storageKey, }: {
115
115
  request: ListTableExportNameRequest;
116
116
  onClose?: () => void;
117
+ /** 用于隔离不同表格的导出配置缓存。 */
118
+ storageKey?: string;
117
119
  renderTable: (props: ReactListTableProps<ExportDialogRow>) => ReactNode;
118
120
  }): react.JSX.Element;
119
121
 
package/dist/index.d.ts CHANGED
@@ -111,9 +111,11 @@ interface ExportDialogRow {
111
111
  preserveTrailingZeros: "yes" | "no";
112
112
  }
113
113
  /** 使用 ReactListTable 承载大量导出列的弹窗。 */
114
- declare function ReactListTableExportNameDialog({ request, onClose, renderTable, }: {
114
+ declare function ReactListTableExportNameDialog({ request, onClose, renderTable, storageKey, }: {
115
115
  request: ListTableExportNameRequest;
116
116
  onClose?: () => void;
117
+ /** 用于隔离不同表格的导出配置缓存。 */
118
+ storageKey?: string;
117
119
  renderTable: (props: ReactListTableProps<ExportDialogRow>) => ReactNode;
118
120
  }): react.JSX.Element;
119
121
 
package/dist/index.js CHANGED
@@ -3572,6 +3572,37 @@ var toolButtonStyle = {
3572
3572
  lineHeight: 1,
3573
3573
  cursor: "pointer"
3574
3574
  };
3575
+ function readExportCache(storageKey) {
3576
+ if (!storageKey) return null;
3577
+ try {
3578
+ const value = JSON.parse(localStorage.getItem(`canvas-table-export:${storageKey}`) ?? "null");
3579
+ if (value?.version !== 1 || !Array.isArray(value.rows) || !Array.isArray(value.selectedKeys) || !value.selectedKeys.every((key) => typeof key === "string") || typeof value.includeSummary !== "boolean") return null;
3580
+ if (!value.rows.every((row) => row && typeof row.key === "string" && ["default", "ascend", "descend"].includes(row.sortOrder) && summaryOptions.some((option) => option.value === row.summaryType) && roundingOptions.some((option) => option.value === row.roundingMode) && ["yes", "no"].includes(row.showTypePrefix) && ["yes", "no"].includes(row.preserveTrailingZeros) && (row.precision == null || Number.isInteger(row.precision) && row.precision >= 0 && row.precision <= 20) && (row.sortIndex == null || Number.isFinite(row.sortIndex)) && (row.sortPriority == null || Number.isFinite(row.sortPriority)))) return null;
3581
+ return value;
3582
+ } catch {
3583
+ return null;
3584
+ }
3585
+ }
3586
+ function writeExportCache(storageKey, value) {
3587
+ if (!storageKey) return;
3588
+ try {
3589
+ const key = `canvas-table-export:${storageKey}`;
3590
+ if (value) localStorage.setItem(key, JSON.stringify(value));
3591
+ else localStorage.removeItem(key);
3592
+ } catch {
3593
+ }
3594
+ }
3595
+ function restoreExportRows(columns, cache) {
3596
+ const current = new Map(createExportDialogRows(columns).map((row) => [row.key, row]));
3597
+ const rows = [];
3598
+ cache?.rows.forEach((saved) => {
3599
+ const row = current.get(saved.key);
3600
+ if (!row) return;
3601
+ rows.push({ ...saved, key: row.key, title: row.title });
3602
+ current.delete(saved.key);
3603
+ });
3604
+ return [...rows, ...current.values()];
3605
+ }
3575
3606
  var sortOptions = [
3576
3607
  { value: "default", label: "\u9ED8\u8BA4" },
3577
3608
  { value: "ascend", label: "\u5347\u5E8F" },
@@ -3643,18 +3674,34 @@ function buildExportDialogSettings(rows, selectedKeys, includeSummary) {
3643
3674
  function ReactListTableExportNameDialog({
3644
3675
  request,
3645
3676
  onClose,
3646
- renderTable
3677
+ renderTable,
3678
+ storageKey
3647
3679
  }) {
3648
3680
  const tableId = useId();
3681
+ const tableHostRef = useRef(null);
3682
+ const [tableWidth, setTableWidth] = useState(0);
3683
+ useEffect(() => {
3684
+ const host = tableHostRef.current;
3685
+ if (!host || typeof ResizeObserver === "undefined") return;
3686
+ const update = () => setTableWidth(host.clientWidth);
3687
+ update();
3688
+ const observer = new ResizeObserver(update);
3689
+ observer.observe(host);
3690
+ return () => observer.disconnect();
3691
+ }, []);
3649
3692
  const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
3650
3693
  const [fileName, setFileName] = useState(
3651
3694
  extension ? request.fileName.slice(0, -extension.length) : request.fileName
3652
3695
  );
3653
- const [rows, setRows] = useState(() => createExportDialogRows(request.columns ?? []));
3696
+ const [cached] = useState(() => readExportCache(storageKey));
3697
+ const [cacheEnabled, setCacheEnabled] = useState(Boolean(storageKey));
3698
+ const [rows, setRows] = useState(() => restoreExportRows(request.columns ?? [], cached));
3654
3699
  const [selectedKeys, setSelectedKeys] = useState(
3655
- () => (request.columns ?? []).filter((column) => column.selected !== false).map((column) => column.key)
3700
+ () => (request.columns ?? []).filter((column) => cached?.rows.some((row) => row.key === column.key) ? cached.selectedKeys.includes(column.key) : column.selected !== false).map((column) => column.key)
3701
+ );
3702
+ const [includeSummary, setIncludeSummary] = useState(
3703
+ () => cached?.includeSummary ?? (request.includeSummary === true || (request.columns?.some((column) => column.summary.type !== "none") ?? false))
3656
3704
  );
3657
- const [includeSummary, setIncludeSummary] = useState(request.includeSummary ?? false);
3658
3705
  const [error, setError] = useState("");
3659
3706
  const columns = useMemo(
3660
3707
  () => [
@@ -3732,9 +3779,16 @@ function ReactListTableExportNameDialog({
3732
3779
  ],
3733
3780
  [includeSummary, request.columns]
3734
3781
  );
3782
+ const fittedColumns = useMemo(
3783
+ () => fitExportDialogColumns(columns, tableWidth),
3784
+ [columns, tableWidth]
3785
+ );
3735
3786
  const confirm = () => {
3736
3787
  if (!fileName.trim()) return setError("\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0");
3737
3788
  if (request.columns && !selectedKeys.length) return setError("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u5217");
3789
+ if (request.columns && cacheEnabled) {
3790
+ writeExportCache(storageKey, { version: 1, rows, selectedKeys: selectedKeys.map(String), includeSummary });
3791
+ }
3738
3792
  request.onConfirm(
3739
3793
  `${fileName.trim()}${extension}`,
3740
3794
  request.columns ? buildExportDialogSettings(rows, selectedKeys, includeSummary) : void 0
@@ -3746,7 +3800,7 @@ function ReactListTableExportNameDialog({
3746
3800
  {
3747
3801
  open: true,
3748
3802
  title: "\u5BFC\u51FA\u6587\u4EF6",
3749
- width: request.columns ? 1180 : 420,
3803
+ width: request.columns ? includeSummary ? 1320 : 1180 : 420,
3750
3804
  fullscreenable: false,
3751
3805
  onOk: confirm,
3752
3806
  okText: "\u5BFC\u51FA",
@@ -3779,6 +3833,27 @@ function ReactListTableExportNameDialog({
3779
3833
  request.columns ? /* @__PURE__ */ jsxs("div", { style: { marginTop: 16 }, children: [
3780
3834
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 16, marginBottom: 8 }, children: [
3781
3835
  /* @__PURE__ */ jsx("span", { style: { fontWeight: 600 }, children: "\u5BFC\u51FA\u8868\u683C\u5217" }),
3836
+ storageKey ? /* @__PURE__ */ jsxs(
3837
+ "label",
3838
+ {
3839
+ style: { display: "inline-flex", alignItems: "center", gap: 6 },
3840
+ title: "\u5BFC\u51FA\u65F6\u4FDD\u5B58\u914D\u7F6E\uFF0C\u4E0B\u6B21\u6253\u5F00\u81EA\u52A8\u6062\u590D\uFF1B\u53D6\u6D88\u52FE\u9009\u6E05\u9664\u7F13\u5B58",
3841
+ children: [
3842
+ /* @__PURE__ */ jsx(
3843
+ ReactCheckbox,
3844
+ {
3845
+ checked: cacheEnabled,
3846
+ "aria-label": "\u7F13\u5B58\u5BFC\u51FA\u914D\u7F6E",
3847
+ onChange: (event) => {
3848
+ setCacheEnabled(event.target.checked);
3849
+ if (!event.target.checked) writeExportCache(storageKey, null);
3850
+ }
3851
+ }
3852
+ ),
3853
+ "\u7F13\u5B58\u5BFC\u51FA\u914D\u7F6E"
3854
+ ]
3855
+ }
3856
+ ) : null,
3782
3857
  /* @__PURE__ */ jsxs("label", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
3783
3858
  /* @__PURE__ */ jsx(
3784
3859
  ReactCheckbox,
@@ -3791,9 +3866,9 @@ function ReactListTableExportNameDialog({
3791
3866
  "\u5BFC\u51FA\u6C47\u603B\u884C"
3792
3867
  ] })
3793
3868
  ] }),
3794
- /* @__PURE__ */ jsx("div", { style: { height: "min(45vh, 520px)", minHeight: 250, overflow: "hidden" }, children: renderTable({
3869
+ /* @__PURE__ */ jsx("div", { ref: tableHostRef, style: { height: "min(45vh, 520px)", minHeight: 250, overflow: "hidden" }, children: renderTable({
3795
3870
  tableId,
3796
- columns,
3871
+ columns: fittedColumns,
3797
3872
  dataSource: rows,
3798
3873
  rowKey: "key",
3799
3874
  rowHeight: 42,
@@ -3838,6 +3913,17 @@ function ReactListTableExportNameDialog({
3838
3913
  }
3839
3914
  );
3840
3915
  }
3916
+ function fitExportDialogColumns(columns, availableWidth) {
3917
+ if (availableWidth <= 0) return columns;
3918
+ const totalWidth = (items) => items.reduce((sum, column) => sum + (column.key === ROW_SELECTION_COLUMN.key ? 0 : column.children?.length ? totalWidth(column.children) : Number(column.width) || 160), 0);
3919
+ const ratio = Math.min(1, Math.max(availableWidth - 54 - 32, 1) / totalWidth(columns));
3920
+ const fit = (items) => items.map((column) => {
3921
+ if (column.key === ROW_SELECTION_COLUMN.key) return column;
3922
+ if (column.children?.length) return { ...column, children: fit(column.children) };
3923
+ return { ...column, width: Math.max(1, Math.floor((Number(column.width) || 160) * ratio)), minWidth: 1 };
3924
+ });
3925
+ return fit(columns);
3926
+ }
3841
3927
 
3842
3928
  // src/features/editor/utils.ts
3843
3929
  function toNumberValue(value) {
@@ -5002,14 +5088,18 @@ function SortableList(props) {
5002
5088
  );
5003
5089
  useEffect(() => {
5004
5090
  if (!dragState) return;
5005
- const handleMove = (event) => {
5091
+ const scrollContainer = props.scrollContainerRef?.current;
5092
+ let frameId = 0;
5093
+ let lastTime = null;
5094
+ const updateTarget = () => {
5006
5095
  const current = dragRef.current;
5007
5096
  if (!current) return;
5008
5097
  const target = resolveClosestSortableItem({
5009
5098
  items,
5010
5099
  parentKey: current.source.parentKey,
5011
5100
  layouts: current.layouts,
5012
- overlayCenterY: event.clientY - current.offsetY + current.height / 2
5101
+ // 保留拖拽开始时的布局,补偿滚动位移,避免受行交换动画影响。
5102
+ overlayCenterY: current.pointerY - current.offsetY + current.height / 2 + current.rootTop - (rootRef.current?.getBoundingClientRect().top ?? current.rootTop)
5013
5103
  });
5014
5104
  if (target) {
5015
5105
  current.target = target;
@@ -5017,12 +5107,44 @@ function SortableList(props) {
5017
5107
  setDragState({
5018
5108
  sourceKey: current.source.key,
5019
5109
  targetKey: current.target.key,
5020
- pointerY: event.clientY
5110
+ pointerY: current.pointerY
5021
5111
  });
5022
5112
  };
5023
- const handleEnd = () => {
5113
+ const handleMove = (event) => {
5114
+ const current = dragRef.current;
5115
+ if (!current || event.pointerId !== current.pointerId) return;
5116
+ current.pointerY = event.clientY;
5117
+ updateTarget();
5118
+ };
5119
+ const tick = (time) => {
5120
+ const current = dragRef.current;
5121
+ if (!current) return;
5122
+ const elapsed = lastTime == null ? 0 : Math.min(time - lastTime, 50);
5123
+ lastTime = time;
5124
+ if (scrollContainer) {
5125
+ const rect = scrollContainer.getBoundingClientRect();
5126
+ const top = rect.top + scrollContainer.clientTop;
5127
+ const height = scrollContainer.clientHeight;
5128
+ const edge = Math.min(40, height / 2);
5129
+ const bottom = top + height;
5130
+ const direction = edge <= 0 ? 0 : current.pointerY < top + edge ? -Math.min(1, (top + edge - current.pointerY) / edge) : current.pointerY > bottom - edge ? Math.min(1, (current.pointerY - bottom + edge) / edge) : 0;
5131
+ if (direction) {
5132
+ scrollContainer.scrollTop = Math.max(
5133
+ 0,
5134
+ Math.min(
5135
+ scrollContainer.scrollHeight - height,
5136
+ scrollContainer.scrollTop + direction * elapsed * 0.5
5137
+ )
5138
+ );
5139
+ updateTarget();
5140
+ }
5141
+ }
5142
+ frameId = requestAnimationFrame(tick);
5143
+ };
5144
+ const finish = (commit) => {
5024
5145
  const current = dragRef.current;
5025
- if (current && current.source.key !== current.target.key) {
5146
+ cancelAnimationFrame(frameId);
5147
+ if (commit && current && current.source.key !== current.target.key) {
5026
5148
  const siblings = items.filter(
5027
5149
  (item) => item.parentKey === current.source.parentKey
5028
5150
  );
@@ -5040,15 +5162,30 @@ function SortableList(props) {
5040
5162
  document.body.classList.remove("react-list-table-sorting");
5041
5163
  document.body.style.removeProperty("user-select");
5042
5164
  };
5165
+ const handleEnd = (event) => {
5166
+ if (event.pointerId !== dragRef.current?.pointerId) return;
5167
+ handleMove(event);
5168
+ finish(true);
5169
+ };
5170
+ const handleCancel = (event) => {
5171
+ if (event.pointerId === dragRef.current?.pointerId) finish(false);
5172
+ };
5173
+ const handleBlur = () => finish(false);
5174
+ frameId = requestAnimationFrame(tick);
5175
+ scrollContainer?.addEventListener("scroll", updateTarget);
5043
5176
  window.addEventListener("pointermove", handleMove);
5044
- window.addEventListener("pointerup", handleEnd, { once: true });
5045
- window.addEventListener("pointercancel", handleEnd, { once: true });
5177
+ window.addEventListener("pointerup", handleEnd);
5178
+ window.addEventListener("pointercancel", handleCancel);
5179
+ window.addEventListener("blur", handleBlur);
5046
5180
  return () => {
5181
+ cancelAnimationFrame(frameId);
5182
+ scrollContainer?.removeEventListener("scroll", updateTarget);
5047
5183
  window.removeEventListener("pointermove", handleMove);
5048
5184
  window.removeEventListener("pointerup", handleEnd);
5049
- window.removeEventListener("pointercancel", handleEnd);
5185
+ window.removeEventListener("pointercancel", handleCancel);
5186
+ window.removeEventListener("blur", handleBlur);
5050
5187
  };
5051
- }, [dragState != null, items, onOrderChange]);
5188
+ }, [dragState != null, items, onOrderChange, props.scrollContainerRef]);
5052
5189
  const sourceIndex = dragState ? items.findIndex((item) => item.key === dragState.sourceKey) : -1;
5053
5190
  const targetIndex = dragState ? items.findIndex((item) => item.key === dragState.targetKey) : -1;
5054
5191
  return /* @__PURE__ */ jsxs("div", { ref: rootRef, children: [
@@ -5067,7 +5204,7 @@ function SortableList(props) {
5067
5204
  style,
5068
5205
  children: props.renderItem(item, {
5069
5206
  onPointerDown: (event) => {
5070
- if (event.button !== 0) return;
5207
+ if (event.button !== 0 || dragRef.current) return;
5071
5208
  const row = event.currentTarget.closest(
5072
5209
  "[data-sortable-key]"
5073
5210
  );
@@ -5080,7 +5217,10 @@ function SortableList(props) {
5080
5217
  offsetY: event.clientY - rect.top,
5081
5218
  width: rect.width,
5082
5219
  left: rect.left,
5083
- height: rect.height
5220
+ height: rect.height,
5221
+ pointerId: event.pointerId,
5222
+ pointerY: event.clientY,
5223
+ rootTop: rootRef.current?.getBoundingClientRect().top ?? 0
5084
5224
  };
5085
5225
  setDragState({
5086
5226
  sourceKey: item.key,
@@ -5167,13 +5307,14 @@ function resolveSortableTransform(index, sourceIndex, targetIndex, height) {
5167
5307
  }
5168
5308
 
5169
5309
  // src/features/toolbar/style.css
5170
- styleInject(".react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: #374151;\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu {\n width: max-content;\n min-width: 0;\n padding: 8px;\n border-radius: 8px;\n}\n.react-list-table-tool-menu-check {\n width: 16px;\n flex: 0 0 16px;\n margin-right: 6px;\n text-align: center;\n}\n.react-list-table-tool-menu button:hover {\n background: #f3f4f6;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-sort-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n");
5310
+ styleInject(".react-list-table-shell {\n background: #fff;\n font-size: 14px;\n}\n.react-list-table-titlebar {\n height: 44px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 0;\n box-sizing: border-box;\n background: #fff;\n}\n.react-list-table-shell-fullscreen {\n width: 100% !important;\n height: 100% !important;\n}\n.react-list-table-shell-fullscreen .canvas-list-table-root {\n height: 100% !important;\n}\n.react-list-table-title {\n min-width: 0;\n color: #1f2937;\n font-size: 14px;\n font-weight: 600;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-tools {\n display: flex;\n align-items: center;\n gap: 14px;\n color: #475569;\n}\n.react-list-table-tool-wrap {\n position: relative;\n display: inline-flex;\n}\n.react-list-table-tool {\n width: 20px;\n height: 24px;\n padding: 0;\n border: 0;\n color: inherit;\n background: transparent;\n font: 16px/24px sans-serif;\n cursor: pointer;\n}\n.react-list-table-tool:hover {\n color: #1677ff;\n}\n.react-list-table-tool-menu,\n.react-list-table-column-setting {\n position: absolute;\n z-index: 120;\n top: 28px;\n right: 0;\n min-width: 112px;\n padding: 6px;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.14);\n}\n.react-list-table-tool-menu button {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: #374151;\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n}\n.react-list-table-tool-menu {\n width: max-content;\n min-width: 0;\n padding: 8px;\n border-radius: 8px;\n}\n.react-list-table-tool-menu-check {\n width: 16px;\n flex: 0 0 16px;\n margin-right: 6px;\n text-align: center;\n}\n.react-list-table-tool-menu button:hover {\n background: #f3f4f6;\n}\n.react-list-table-column-setting {\n width: 328px;\n max-height: 360px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.react-list-table-column-setting-head {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px 8px;\n border-bottom: 1px solid #f0f0f0;\n flex: 0 0 auto;\n}\n.react-list-table-column-setting-head button {\n border: 0;\n color: #1677ff;\n background: transparent;\n cursor: pointer;\n}\n.react-list-table-column-setting-body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.react-list-table-column-item {\n display: flex;\n align-items: center;\n gap: 8px;\n justify-content: space-between;\n padding: 7px 6px;\n box-sizing: border-box;\n cursor: pointer;\n}\n.react-list-table-column-main,\n.react-list-table-column-actions {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n.react-list-table-column-main {\n min-width: 0;\n}\n.react-list-table-column-actions {\n flex: 0 0 auto;\n}\n.react-list-table-column-actions > .canvas-react-select-wrap {\n flex: 0 0 96px;\n width: 96px;\n height: 24px;\n}\n.react-list-table-column-label {\n min-width: 64px;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n.react-list-table-column-width-input {\n height: 22px;\n padding-inline: 5px;\n}\n.react-list-table-column-fixed-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-sort-input {\n height: 22px;\n padding-inline: 6px;\n font-size: 14px;\n}\n.react-list-table-column-setting label.dragging {\n opacity: 0.45;\n background: #e6f4ff;\n}\n.react-list-table-column-setting [data-sortable-key].dragging {\n opacity: 0.28;\n}\n.react-list-table-column-drag {\n touch-action: none;\n color: #94a3b8;\n display: inline-flex;\n font-size: 14px;\n cursor: grab;\n user-select: none;\n}\nbody.react-list-table-sorting,\nbody.react-list-table-sorting * {\n cursor: grabbing !important;\n}\n.react-list-table-sort-overlay {\n position: fixed;\n z-index: 1400;\n display: block;\n padding: 0;\n box-sizing: border-box;\n color: #334155;\n background: #fff;\n border: 1px solid #91caff;\n border-radius: 6px;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);\n pointer-events: none;\n}\n.react-list-table-sort-overlay .react-list-table-column-item {\n width: 100%;\n height: 100%;\n}\n");
5171
5311
  function ReactTableToolbar(props) {
5172
5312
  const { toolbar, title } = props;
5173
5313
  const [densityOpen, setDensityOpen] = useState(false);
5174
5314
  const [settingOpen, setSettingOpen] = useState(false);
5175
5315
  const [isFullscreen, setIsFullscreen] = useState(false);
5176
5316
  const rootRef = useRef(null);
5317
+ const columnSettingsBodyRef = useRef(null);
5177
5318
  const hasToolbar = toolbar !== void 0 && toolbar !== false;
5178
5319
  useEffect(() => {
5179
5320
  const close = (event) => {
@@ -5312,116 +5453,124 @@ function ReactTableToolbar(props) {
5312
5453
  /* @__PURE__ */ jsx("span", { style: { marginLeft: "auto" }, children: config.columnSettingHeaderExtra }),
5313
5454
  /* @__PURE__ */ jsx("button", { type: "button", onClick: props.onResetColumns, children: "\u91CD\u7F6E" })
5314
5455
  ] }),
5315
- /* @__PURE__ */ jsx("div", { className: "react-list-table-column-setting-body canvas-react-scrollbar", children: /* @__PURE__ */ jsx(
5316
- SortableList,
5456
+ /* @__PURE__ */ jsx(
5457
+ "div",
5317
5458
  {
5318
- items: flattenColumns(props.columns),
5319
- onOrderChange: props.onColumnOrderChange,
5320
- renderItem: (column, handleProps) => /* @__PURE__ */ jsxs("div", { className: "react-list-table-column-item", children: [
5321
- /* @__PURE__ */ jsxs(
5322
- "span",
5323
- {
5324
- className: "react-list-table-column-main",
5325
- style: { paddingLeft: column.level * 16 },
5326
- children: [
5459
+ ref: columnSettingsBodyRef,
5460
+ className: "react-list-table-column-setting-body canvas-react-scrollbar",
5461
+ children: /* @__PURE__ */ jsx(
5462
+ SortableList,
5463
+ {
5464
+ scrollContainerRef: columnSettingsBodyRef,
5465
+ items: flattenColumns(props.columns),
5466
+ onOrderChange: props.onColumnOrderChange,
5467
+ renderItem: (column, handleProps) => /* @__PURE__ */ jsxs("div", { className: "react-list-table-column-item", children: [
5468
+ /* @__PURE__ */ jsxs(
5469
+ "span",
5470
+ {
5471
+ className: "react-list-table-column-main",
5472
+ style: { paddingLeft: column.level * 16 },
5473
+ children: [
5474
+ /* @__PURE__ */ jsx(
5475
+ "span",
5476
+ {
5477
+ className: "react-list-table-column-drag",
5478
+ ...handleProps,
5479
+ onClick: (event) => {
5480
+ event.preventDefault();
5481
+ event.stopPropagation();
5482
+ },
5483
+ children: /* @__PURE__ */ jsx(HolderOutlined, {})
5484
+ }
5485
+ ),
5486
+ /* @__PURE__ */ jsx(
5487
+ "input",
5488
+ {
5489
+ type: "checkbox",
5490
+ checked: !column.hidden,
5491
+ disabled: column.disableHide,
5492
+ onChange: (event) => props.onColumnVisibilityChange(
5493
+ column.key,
5494
+ event.target.checked
5495
+ )
5496
+ }
5497
+ ),
5498
+ /* @__PURE__ */ jsx("span", { className: "react-list-table-column-label", children: column.label })
5499
+ ]
5500
+ }
5501
+ ),
5502
+ !column.isGroup ? /* @__PURE__ */ jsxs("span", { className: "react-list-table-column-actions", children: [
5327
5503
  /* @__PURE__ */ jsx(
5328
- "span",
5504
+ ReactNumberInput,
5329
5505
  {
5330
- className: "react-list-table-column-drag",
5331
- ...handleProps,
5332
- onClick: (event) => {
5333
- event.preventDefault();
5334
- event.stopPropagation();
5335
- },
5336
- children: /* @__PURE__ */ jsx(HolderOutlined, {})
5506
+ className: "react-list-table-column-width-input",
5507
+ min: column.minWidth,
5508
+ max: column.maxWidth,
5509
+ value: column.width,
5510
+ allowClear: false,
5511
+ "aria-label": `${column.label}\u5217\u5BBD`,
5512
+ style: { width: 80, height: 24 },
5513
+ onChange: (width) => {
5514
+ if (width != null && Number.isFinite(width) && width > 0 && (column.minWidth == null || width >= column.minWidth) && (column.maxWidth == null || width <= column.maxWidth)) {
5515
+ props.onColumnWidthChange(
5516
+ column.key,
5517
+ width
5518
+ );
5519
+ }
5520
+ }
5337
5521
  }
5338
5522
  ),
5339
5523
  /* @__PURE__ */ jsx(
5340
- "input",
5524
+ ReactSelect,
5341
5525
  {
5342
- type: "checkbox",
5343
- checked: !column.hidden,
5344
- disabled: column.disableHide,
5345
- onChange: (event) => props.onColumnVisibilityChange(
5526
+ className: "react-list-table-column-sort-input",
5527
+ value: props.sortState.find(
5528
+ (item) => item.key === column.key
5529
+ )?.order ?? "default",
5530
+ options: [
5531
+ { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
5532
+ { label: "\u5347\u5E8F", value: "ascend" },
5533
+ { label: "\u964D\u5E8F", value: "descend" }
5534
+ ],
5535
+ disabled: !column.sortable,
5536
+ allowClear: false,
5537
+ showSearch: false,
5538
+ style: { width: "100%", height: 24 },
5539
+ "aria-label": `${column.label}\u6392\u5E8F\u65B9\u5F0F`,
5540
+ onChange: (value) => props.onColumnSortChange(
5346
5541
  column.key,
5347
- event.target.checked
5542
+ value === "ascend" || value === "descend" ? value : null
5348
5543
  )
5349
5544
  }
5350
5545
  ),
5351
- /* @__PURE__ */ jsx("span", { className: "react-list-table-column-label", children: column.label })
5352
- ]
5353
- }
5354
- ),
5355
- !column.isGroup ? /* @__PURE__ */ jsxs("span", { className: "react-list-table-column-actions", children: [
5356
- /* @__PURE__ */ jsx(
5357
- ReactNumberInput,
5358
- {
5359
- className: "react-list-table-column-width-input",
5360
- min: column.minWidth,
5361
- max: column.maxWidth,
5362
- value: column.width,
5363
- allowClear: false,
5364
- "aria-label": `${column.label}\u5217\u5BBD`,
5365
- style: { width: 80, height: 24 },
5366
- onChange: (width) => {
5367
- if (width != null && Number.isFinite(width) && width > 0 && (column.minWidth == null || width >= column.minWidth) && (column.maxWidth == null || width <= column.maxWidth)) {
5368
- props.onColumnWidthChange(
5369
- column.key,
5370
- width
5371
- );
5546
+ /* @__PURE__ */ jsx(
5547
+ ReactSelect,
5548
+ {
5549
+ className: "react-list-table-column-fixed-input",
5550
+ value: column.fixed ?? "none",
5551
+ options: [
5552
+ { label: "\u4E0D\u56FA\u5B9A", value: "none" },
5553
+ { label: "\u56FA\u5B9A\u5DE6\u4FA7", value: "left" },
5554
+ { label: "\u56FA\u5B9A\u53F3\u4FA7", value: "right" }
5555
+ ],
5556
+ allowClear: false,
5557
+ showSearch: false,
5558
+ style: { width: "100%", height: 24 },
5559
+ "aria-label": `${column.label}\u56FA\u5B9A\u65B9\u5411`,
5560
+ onChange: (value) => {
5561
+ props.onColumnFixedChange(
5562
+ column.key,
5563
+ value === "left" || value === "right" ? value : void 0
5564
+ );
5565
+ }
5372
5566
  }
5373
- }
5374
- }
5375
- ),
5376
- /* @__PURE__ */ jsx(
5377
- ReactSelect,
5378
- {
5379
- className: "react-list-table-column-sort-input",
5380
- value: props.sortState.find(
5381
- (item) => item.key === column.key
5382
- )?.order ?? "default",
5383
- options: [
5384
- { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
5385
- { label: "\u5347\u5E8F", value: "ascend" },
5386
- { label: "\u964D\u5E8F", value: "descend" }
5387
- ],
5388
- disabled: !column.sortable,
5389
- allowClear: false,
5390
- showSearch: false,
5391
- style: { width: "100%", height: 24 },
5392
- "aria-label": `${column.label}\u6392\u5E8F\u65B9\u5F0F`,
5393
- onChange: (value) => props.onColumnSortChange(
5394
- column.key,
5395
- value === "ascend" || value === "descend" ? value : null
5396
5567
  )
5397
- }
5398
- ),
5399
- /* @__PURE__ */ jsx(
5400
- ReactSelect,
5401
- {
5402
- className: "react-list-table-column-fixed-input",
5403
- value: column.fixed ?? "none",
5404
- options: [
5405
- { label: "\u4E0D\u56FA\u5B9A", value: "none" },
5406
- { label: "\u56FA\u5B9A\u5DE6\u4FA7", value: "left" },
5407
- { label: "\u56FA\u5B9A\u53F3\u4FA7", value: "right" }
5408
- ],
5409
- allowClear: false,
5410
- showSearch: false,
5411
- style: { width: "100%", height: 24 },
5412
- "aria-label": `${column.label}\u56FA\u5B9A\u65B9\u5411`,
5413
- onChange: (value) => {
5414
- props.onColumnFixedChange(
5415
- column.key,
5416
- value === "left" || value === "right" ? value : void 0
5417
- );
5418
- }
5419
- }
5420
- )
5421
- ] }) : null
5422
- ] })
5568
+ ] }) : null
5569
+ ] })
5570
+ }
5571
+ )
5423
5572
  }
5424
- ) })
5573
+ )
5425
5574
  ]
5426
5575
  }
5427
5576
  ) : null
@@ -6202,6 +6351,7 @@ function ReactListTableInner(props, ref) {
6202
6351
  ReactListTableExportNameDialog,
6203
6352
  {
6204
6353
  request: exportNameRequest,
6354
+ storageKey: storageKey ? `list:${storageKey}` : void 0,
6205
6355
  onClose: closeExportNameRequest,
6206
6356
  renderTable: (tableProps) => /* @__PURE__ */ jsx(ReactListTable, { ...tableProps })
6207
6357
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canvas-components/react-list-table",
3
- "version": "0.3.36",
3
+ "version": "0.3.38",
4
4
  "description": "React adapter for the list table core engine.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@canvas-components/chart": "0.3.7",
32
- "@canvas-components/react-components": "0.3.16",
33
- "@canvas-components/list-table": "0.3.32"
32
+ "@canvas-components/list-table": "0.3.32",
33
+ "@canvas-components/react-components": "0.3.16"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=16.8.0",