@canvas-components/react-list-table 0.3.28 → 0.3.30

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
@@ -328,7 +328,8 @@ function buildCacheMenuItems(request) {
328
328
  ["alignment", "\u5BF9\u9F50"],
329
329
  ["dataFormat", "\u683C\u5F0F"],
330
330
  ["density", "\u8868\u683C\u5BC6\u5EA6"],
331
- ["zoom", "\u7F29\u653E"]
331
+ ["zoom", "\u7F29\u653E"],
332
+ ["scrollbar", "\u6EDA\u52A8\u6761"]
332
333
  ];
333
334
  for (const [category, label] of categories)
334
335
  items.push({
@@ -376,6 +377,24 @@ var SELECTION_CHART_TYPES = [
376
377
  { value: "gauge", label: "\u4EEA\u8868\u76D8" }
377
378
  ];
378
379
  var COLORS = ["#1677ff", "#13c2c2", "#fa8c16", "#722ed1", "#eb2f96"];
380
+ function isSameSelectionChartData(left, right) {
381
+ if (left === right) return true;
382
+ if (!left || !right) return false;
383
+ if (left.labels.length !== right.labels.length || left.keys?.length !== right.keys?.length || left.series.length !== right.series.length) {
384
+ return false;
385
+ }
386
+ if (left.labels.some((label, index) => label !== right.labels[index])) {
387
+ return false;
388
+ }
389
+ if (left.keys?.some((key, index) => key !== right.keys?.[index])) {
390
+ return false;
391
+ }
392
+ return left.series.every(
393
+ (series, index) => series.name === right.series[index]?.name && series.data.length === right.series[index]?.data.length && series.data.every(
394
+ (value, valueIndex) => value === right.series[index]?.data[valueIndex]
395
+ )
396
+ );
397
+ }
379
398
  function createSelectionChartOption(data, chartType, seriesIndex = 0) {
380
399
  const activeSeries = data.series[Math.min(seriesIndex, data.series.length - 1)];
381
400
  if (["pie", "donut", "rose", "half-donut"].includes(chartType)) {
@@ -388,6 +407,7 @@ function createSelectionChartOption(data, chartType, seriesIndex = 0) {
388
407
  name: activeSeries.name,
389
408
  data: data.labels.map((name, index) => ({
390
409
  name,
410
+ key: data.keys?.[index],
391
411
  value: Math.max(activeSeries.data[index] ?? 0, 0)
392
412
  })),
393
413
  radius: chartType === "pie" || chartType === "rose" ? "62%" : ["28%", "62%"],
@@ -409,6 +429,7 @@ function createSelectionChartOption(data, chartType, seriesIndex = 0) {
409
429
  ...series.flatMap((item) => item.data.slice(0, labels.length))
410
430
  );
411
431
  const option2 = {
432
+ categoryKeys: data.keys?.slice(0, labels.length),
412
433
  color: COLORS,
413
434
  radar: {
414
435
  indicator: labels.map((name) => ({
@@ -456,6 +477,7 @@ function createSelectionChartOption(data, chartType, seriesIndex = 0) {
456
477
  const area = chartType.includes("area");
457
478
  const bumpData = chartType === "bump" ? resolveBumpRanks(data) : null;
458
479
  const option = {
480
+ categoryKeys: data.keys,
459
481
  grid: {
460
482
  show: true,
461
483
  left: 20,
@@ -517,29 +539,48 @@ function resolveBumpRanks(data) {
517
539
  return ranks;
518
540
  }
519
541
  function ChartDialog(props) {
542
+ const [data, setData] = react.useState(props.data);
520
543
  const [chartType, setChartType] = react.useState("line");
521
544
  const [seriesIndex, setSeriesIndex] = react.useState(0);
522
545
  const [ready, setReady] = react.useState(false);
523
546
  const chartHostRef = react.useRef(null);
524
547
  const chartRef = react.useRef(null);
525
548
  const chartConfig = react.useMemo(() => {
526
- if (!props.data) return null;
527
- return createSelectionChartOption(props.data, chartType, seriesIndex);
528
- }, [chartType, props.data, seriesIndex]);
549
+ if (!data) return null;
550
+ return createSelectionChartOption(data, chartType, seriesIndex);
551
+ }, [chartType, data, seriesIndex]);
552
+ react.useEffect(() => {
553
+ if (!props.getData) return;
554
+ const timer = globalThis.setInterval(() => {
555
+ const next = props.getData?.() ?? null;
556
+ setData(
557
+ (current) => isSameSelectionChartData(current, next) ? current : next
558
+ );
559
+ }, 500);
560
+ return () => globalThis.clearInterval(timer);
561
+ }, [props.getData]);
562
+ react.useEffect(() => {
563
+ if (!data && chartRef.current) {
564
+ chartRef.current.destroy();
565
+ chartRef.current = null;
566
+ }
567
+ }, [data]);
529
568
  react.useEffect(() => {
530
569
  if (!ready || !chartConfig || !chartHostRef.current) return;
531
570
  let chart$1 = chartRef.current;
532
571
  if (!chart$1) {
533
572
  chart$1 = new chart.CanvasChart(chartHostRef.current, {
534
573
  type: chartConfig.type,
535
- option: chartConfig.option
574
+ option: chartConfig.option,
575
+ animation: { duration: 720, easing: "linear" }
536
576
  });
537
577
  chart$1.mount();
538
578
  chartRef.current = chart$1;
539
579
  } else {
540
580
  chart$1.updateOptions({
541
581
  type: chartConfig.type,
542
- option: chartConfig.option
582
+ option: chartConfig.option,
583
+ animation: { duration: 720, easing: "linear" }
543
584
  });
544
585
  }
545
586
  }, [chartConfig, ready]);
@@ -564,7 +605,7 @@ function ChartDialog(props) {
564
605
  onCancel: props.onClose,
565
606
  afterOpenChange: setReady,
566
607
  bodyStyle: { padding: "12px 20px 20px", display: "flex" },
567
- children: props.data ? /* @__PURE__ */ jsxRuntime.jsxs(
608
+ children: data ? /* @__PURE__ */ jsxRuntime.jsxs(
568
609
  "div",
569
610
  {
570
611
  style: {
@@ -599,7 +640,7 @@ function ChartDialog(props) {
599
640
  ]
600
641
  }
601
642
  ),
602
- props.data.series.length > 1 && [
643
+ data.series.length > 1 && [
603
644
  "pie",
604
645
  "donut",
605
646
  "rose",
@@ -621,7 +662,7 @@ function ChartDialog(props) {
621
662
  {
622
663
  value: seriesIndex,
623
664
  allowClear: false,
624
- options: props.data.series.map((series, index) => ({
665
+ options: data.series.map((series, index) => ({
625
666
  value: index,
626
667
  label: series.name
627
668
  })),
@@ -675,9 +716,90 @@ var CONTEXT_MENU_SURFACE_STYLE = {
675
716
  boxShadow: "0 8px 24px rgba(15, 23, 42, 0.16)",
676
717
  fontSize: 14
677
718
  };
719
+ function ScrollbarModeMenu(props) {
720
+ const { request, onOpenSettings } = props;
721
+ return /* @__PURE__ */ jsxRuntime.jsx(
722
+ MenuSubmenu,
723
+ {
724
+ label: "\u6EDA\u52A8\u6761\u6A21\u5F0F",
725
+ items: [
726
+ ["scrollbar", "\u6EDA\u52A8\u6761"],
727
+ ["button", "\u6309\u94AE"]
728
+ ].map(([mode, label]) => ({
729
+ key: `scrollbar-mode-${mode}`,
730
+ label,
731
+ selected: (request.scrollbar?.mode ?? "scrollbar") === mode,
732
+ onClick: () => {
733
+ request.onChangeScrollbar?.({
734
+ ...request.scrollbar,
735
+ mode,
736
+ horizontal: request.scrollbar?.horizontal === false ? false : { ...request.scrollbar?.horizontal, mode },
737
+ vertical: request.scrollbar?.vertical === false ? false : { ...request.scrollbar?.vertical, mode }
738
+ });
739
+ request.onClose();
740
+ }
741
+ })),
742
+ footer: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactButton, { onClick: onOpenSettings, style: { width: "100%" }, children: "\u914D\u7F6E\u6EDA\u52A8\u6761\u5C5E\u6027" })
743
+ }
744
+ );
745
+ }
746
+ function ResetMenu(props) {
747
+ const { request } = props;
748
+ return /* @__PURE__ */ jsxRuntime.jsx(
749
+ MenuSubmenu,
750
+ {
751
+ label: "\u91CD\u7F6E",
752
+ items: [
753
+ {
754
+ key: "reset-filter",
755
+ label: "\u91CD\u7F6E\u7B5B\u9009",
756
+ onClick: request.onResetFilter
757
+ },
758
+ { key: "reset-sort", label: "\u91CD\u7F6E\u6392\u5E8F", onClick: request.onResetSort },
759
+ {
760
+ key: "reset-header",
761
+ label: "\u91CD\u7F6E\u8868\u5934\u914D\u7F6E",
762
+ onClick: request.onResetHeader
763
+ },
764
+ {
765
+ key: "reset-grouping",
766
+ label: "\u91CD\u7F6E\u5206\u7EC4",
767
+ onClick: request.onResetGrouping
768
+ },
769
+ {
770
+ key: "reset-summary",
771
+ label: "\u91CD\u7F6E\u6C47\u603B",
772
+ onClick: request.onResetSummary
773
+ },
774
+ {
775
+ key: "reset-alignment",
776
+ label: "\u91CD\u7F6E\u5BF9\u9F50",
777
+ onClick: request.onResetAlignment
778
+ },
779
+ {
780
+ key: "reset-data-format",
781
+ label: "\u91CD\u7F6E\u683C\u5F0F",
782
+ onClick: request.onResetDataFormat
783
+ },
784
+ {
785
+ key: "reset-scrollbar",
786
+ label: "\u91CD\u7F6E\u6EDA\u52A8\u914D\u7F6E",
787
+ onClick: () => {
788
+ request.onResetScrollbar?.();
789
+ request.onClose();
790
+ }
791
+ }
792
+ ]
793
+ }
794
+ );
795
+ }
678
796
  function ReactTableContextMenuView(props) {
679
797
  const { request } = props;
680
- const [menuOpen, setMenuOpen] = react.useState(true);
798
+ const [closedRequest, setClosedRequest] = react.useState(null);
799
+ const menuOpen = request !== null && closedRequest !== request;
800
+ const setMenuOpen = (open) => {
801
+ setClosedRequest(open ? null : request);
802
+ };
681
803
  const [conditionalEditor, setConditionalEditor] = react.useState(null);
682
804
  const conditionalDialog = conditionalEditor ? /* @__PURE__ */ jsxRuntime.jsx(
683
805
  ConditionalFormatDialog,
@@ -690,6 +812,31 @@ function ReactTableContextMenuView(props) {
690
812
  }
691
813
  ) : null;
692
814
  const [moreFormatRequest, setMoreFormatRequest] = react.useState(null);
815
+ const [scrollbarSettingsRequest, setScrollbarSettingsRequest] = react.useState(null);
816
+ const [scrollbarPositionRequest, setScrollbarPositionRequest] = react.useState(null);
817
+ const scrollbarDialog = scrollbarSettingsRequest ? /* @__PURE__ */ jsxRuntime.jsx(
818
+ reactComponents.ReactScrollbarSettingsDialog,
819
+ {
820
+ value: scrollbarSettingsRequest.scrollbar,
821
+ onConfirm: (value) => {
822
+ scrollbarSettingsRequest.onChangeScrollbar?.({
823
+ ...scrollbarSettingsRequest.scrollbar,
824
+ ...value
825
+ });
826
+ setScrollbarSettingsRequest(null);
827
+ },
828
+ onClose: () => setScrollbarSettingsRequest(null)
829
+ }
830
+ ) : null;
831
+ const scrollbarPositionDialog = scrollbarPositionRequest ? /* @__PURE__ */ jsxRuntime.jsx(
832
+ reactComponents.ReactScrollbarPositionDialog,
833
+ {
834
+ rowCount: scrollbarPositionRequest.scrollbarRowCount ?? 0,
835
+ columnCount: scrollbarPositionRequest.scrollbarColumnCount ?? 0,
836
+ onConfirm: (row, column) => scrollbarPositionRequest.onScrollToPosition?.(row, column),
837
+ onClose: () => setScrollbarPositionRequest(null)
838
+ }
839
+ ) : null;
693
840
  const [customSelectionRequest, setCustomSelectionRequest] = react.useState(null);
694
841
  const [chartRequest, setChartRequest] = react.useState(null);
695
842
  const [columnEditor, setColumnEditor] = react.useState(null);
@@ -708,6 +855,8 @@ function ReactTableContextMenuView(props) {
708
855
  ) : null });
709
856
  if (!request) {
710
857
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
858
+ scrollbarDialog,
859
+ scrollbarPositionDialog,
711
860
  conditionalDialog,
712
861
  columnDialogs,
713
862
  moreFormatRequest ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -731,6 +880,7 @@ function ReactTableContextMenuView(props) {
731
880
  ChartDialog,
732
881
  {
733
882
  data: chartRequest.data,
883
+ getData: chartRequest.request.onCreateChart,
734
884
  onClose: () => {
735
885
  chartRequest.request.onClose();
736
886
  setChartRequest(null);
@@ -739,11 +889,64 @@ function ReactTableContextMenuView(props) {
739
889
  ) : null
740
890
  ] });
741
891
  }
892
+ const openScrollbarSettings = () => {
893
+ setScrollbarSettingsRequest(request);
894
+ request.onClose();
895
+ };
896
+ if (request.scrollbarArea) {
897
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
898
+ scrollbarDialog,
899
+ scrollbarPositionDialog,
900
+ /* @__PURE__ */ jsxRuntime.jsxs(
901
+ reactComponents.ReactPopup,
902
+ {
903
+ constrainHeight: true,
904
+ open: menuOpen,
905
+ anchorRect: { x: request.x, y: request.y, width: 0, height: 0 },
906
+ minWidth: 260,
907
+ onOpenChange: (open) => {
908
+ setMenuOpen(open);
909
+ if (!open) request.onClose();
910
+ },
911
+ surfaceStyle: { ...CONTEXT_MENU_SURFACE_STYLE, width: 260 },
912
+ children: [
913
+ /* @__PURE__ */ jsxRuntime.jsx(
914
+ ScrollbarModeMenu,
915
+ {
916
+ request,
917
+ onOpenSettings: openScrollbarSettings
918
+ }
919
+ ),
920
+ /* @__PURE__ */ jsxRuntime.jsx(
921
+ MenuAction,
922
+ {
923
+ label: "\u6EDA\u52A8\u5230\u6307\u5B9A\u884C / \u5217",
924
+ onClick: () => {
925
+ setScrollbarPositionRequest(request);
926
+ request.onClose();
927
+ }
928
+ }
929
+ ),
930
+ /* @__PURE__ */ jsxRuntime.jsx(ResetMenu, { request }),
931
+ buildCacheMenuItems(request).length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
932
+ MenuSubmenu,
933
+ {
934
+ label: "\u7F13\u5B58\u5230\u672C\u5730",
935
+ items: buildCacheMenuItems(request)
936
+ }
937
+ ) : null
938
+ ]
939
+ }
940
+ )
941
+ ] });
942
+ }
742
943
  const surfaceStyle = {
743
944
  ...CONTEXT_MENU_SURFACE_STYLE,
744
945
  width: 260
745
946
  };
746
947
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
948
+ scrollbarDialog,
949
+ scrollbarPositionDialog,
747
950
  conditionalDialog,
748
951
  columnDialogs,
749
952
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -831,7 +1034,10 @@ function ReactTableContextMenuView(props) {
831
1034
  {
832
1035
  label: "\u521B\u5EFA\u56FE\u8868",
833
1036
  onClick: request.onCreateChart ? () => {
834
- setChartRequest({ request, data: request.onCreateChart?.() ?? null });
1037
+ setChartRequest({
1038
+ request,
1039
+ data: request.onCreateChart?.() ?? null
1040
+ });
835
1041
  setMenuOpen(false);
836
1042
  } : void 0
837
1043
  }
@@ -1071,47 +1277,22 @@ function ReactTableContextMenuView(props) {
1071
1277
  ]
1072
1278
  }
1073
1279
  ),
1280
+ /* @__PURE__ */ jsxRuntime.jsx(ResetMenu, { request }),
1074
1281
  /* @__PURE__ */ jsxRuntime.jsx(
1075
- MenuSubmenu,
1282
+ ScrollbarModeMenu,
1076
1283
  {
1077
- label: "\u91CD\u7F6E",
1078
- items: [
1079
- {
1080
- key: "reset-filter",
1081
- label: "\u91CD\u7F6E\u7B5B\u9009",
1082
- onClick: request.onResetFilter
1083
- },
1084
- {
1085
- key: "reset-sort",
1086
- label: "\u91CD\u7F6E\u6392\u5E8F",
1087
- onClick: request.onResetSort
1088
- },
1089
- {
1090
- key: "reset-header",
1091
- label: "\u91CD\u7F6E\u8868\u5934\u914D\u7F6E",
1092
- onClick: request.onResetHeader
1093
- },
1094
- {
1095
- key: "reset-grouping",
1096
- label: "\u91CD\u7F6E\u5206\u7EC4",
1097
- onClick: request.onResetGrouping
1098
- },
1099
- {
1100
- key: "reset-summary",
1101
- label: "\u91CD\u7F6E\u6C47\u603B",
1102
- onClick: request.onResetSummary
1103
- },
1104
- {
1105
- key: "reset-alignment",
1106
- label: "\u91CD\u7F6E\u5BF9\u9F50",
1107
- onClick: request.onResetAlignment
1108
- },
1109
- {
1110
- key: "reset-data-format",
1111
- label: "\u91CD\u7F6E\u683C\u5F0F",
1112
- onClick: request.onResetDataFormat
1113
- }
1114
- ]
1284
+ request,
1285
+ onOpenSettings: openScrollbarSettings
1286
+ }
1287
+ ),
1288
+ /* @__PURE__ */ jsxRuntime.jsx(
1289
+ MenuAction,
1290
+ {
1291
+ label: "\u6EDA\u52A8\u5230\u6307\u5B9A\u884C / \u5217",
1292
+ onClick: () => {
1293
+ setScrollbarPositionRequest(request);
1294
+ request.onClose();
1295
+ }
1115
1296
  }
1116
1297
  ),
1117
1298
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1182,6 +1363,7 @@ function ReactTableContextMenuView(props) {
1182
1363
  ChartDialog,
1183
1364
  {
1184
1365
  data: chartRequest.data,
1366
+ getData: chartRequest.request.onCreateChart,
1185
1367
  onClose: () => {
1186
1368
  chartRequest.request.onClose();
1187
1369
  setChartRequest(null);
@@ -1610,6 +1792,7 @@ function ColumnEditorDialog(props) {
1610
1792
  minWidth: item?.minWidth ?? Math.min(40, item?.width ?? 160),
1611
1793
  maxWidth: item?.maxWidth ?? Math.max(2e3, item?.width ?? 160),
1612
1794
  fixed: item?.fixed,
1795
+ sortOrder: item && (item.sortable === false || item.children?.length) ? void 0 : item ? request.sortState?.find((entry) => entry.key === item.key)?.order ?? null : null,
1613
1796
  order: item?.order ?? (parentItem?.children?.length ?? request.columns?.length ?? 0) + 1
1614
1797
  }));
1615
1798
  const [error, setError] = react.useState(null);
@@ -1716,6 +1899,25 @@ function ColumnEditorDialog(props) {
1716
1899
  }
1717
1900
  )
1718
1901
  ] }),
1902
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
1903
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u6392\u5E8F\u65B9\u5F0F" }),
1904
+ /* @__PURE__ */ jsxRuntime.jsx(
1905
+ reactComponents.ReactSelect,
1906
+ {
1907
+ value: draft.sortOrder ?? "default",
1908
+ allowClear: false,
1909
+ disabled: item?.sortable === false || Boolean(item?.children?.length),
1910
+ options: [
1911
+ { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
1912
+ { label: "\u5347\u5E8F", value: "ascend" },
1913
+ { label: "\u964D\u5E8F", value: "descend" }
1914
+ ],
1915
+ onChange: (value) => update({
1916
+ sortOrder: value === "ascend" || value === "descend" ? value : null
1917
+ })
1918
+ }
1919
+ )
1920
+ ] }),
1719
1921
  isUserColumn ? /* @__PURE__ */ jsxRuntime.jsxs("label", { style: fieldStyle, children: [
1720
1922
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u56FA\u5B9A\u4F4D\u7F6E" }),
1721
1923
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1745,6 +1947,7 @@ function ColumnVisibilityMenu(props) {
1745
1947
  const [open, setOpen] = react.useState(false);
1746
1948
  const [deleteConfirmKey, setDeleteConfirmKey] = react.useState(null);
1747
1949
  const closeTimerRef = react.useRef(null);
1950
+ const keepOpenAfterToggleRef = react.useRef(false);
1748
1951
  const clearCloseTimer = () => {
1749
1952
  if (closeTimerRef.current != null) {
1750
1953
  window.clearTimeout(closeTimerRef.current);
@@ -1752,13 +1955,19 @@ function ColumnVisibilityMenu(props) {
1752
1955
  }
1753
1956
  };
1754
1957
  const scheduleClose = () => {
1755
- if (deleteConfirmKey) return;
1958
+ if (deleteConfirmKey || keepOpenAfterToggleRef.current) return;
1756
1959
  clearCloseTimer();
1757
1960
  closeTimerRef.current = window.setTimeout(() => {
1758
1961
  setOpen(false);
1759
1962
  closeTimerRef.current = null;
1760
1963
  }, 120);
1761
1964
  };
1965
+ const handleToggle = (columnKey, visible) => {
1966
+ clearCloseTimer();
1967
+ keepOpenAfterToggleRef.current = true;
1968
+ setOpen(true);
1969
+ onToggle(columnKey, visible);
1970
+ };
1762
1971
  return /* @__PURE__ */ jsxRuntime.jsxs(
1763
1972
  "div",
1764
1973
  {
@@ -1811,7 +2020,10 @@ function ColumnVisibilityMenu(props) {
1811
2020
  placement: "rightTop",
1812
2021
  offset: 2,
1813
2022
  minWidth: 300,
1814
- onOpenChange: setOpen,
2023
+ onOpenChange: (nextOpen) => {
2024
+ if (!nextOpen) keepOpenAfterToggleRef.current = false;
2025
+ setOpen(nextOpen);
2026
+ },
1815
2027
  surfaceClassName: "canvas-react-scrollbar",
1816
2028
  surfaceStyle: {
1817
2029
  ...CONTEXT_MENU_SURFACE_STYLE,
@@ -1843,7 +2055,7 @@ function ColumnVisibilityMenu(props) {
1843
2055
  ColumnVisibilityItem,
1844
2056
  {
1845
2057
  item: column,
1846
- onToggle,
2058
+ onToggle: handleToggle,
1847
2059
  onAddChild,
1848
2060
  onEdit,
1849
2061
  onDelete,
@@ -1877,6 +2089,7 @@ function ColumnVisibilityItem(props) {
1877
2089
  const triggerRef = react.useRef(null);
1878
2090
  const [open, setOpen] = react.useState(false);
1879
2091
  const closeTimerRef = react.useRef(null);
2092
+ const keepOpenAfterToggleRef = react.useRef(false);
1880
2093
  const hasChildren = !!item.children?.length;
1881
2094
  const clearCloseTimer = () => {
1882
2095
  if (closeTimerRef.current != null) {
@@ -1885,13 +2098,18 @@ function ColumnVisibilityItem(props) {
1885
2098
  }
1886
2099
  };
1887
2100
  const scheduleClose = () => {
1888
- if (deleteConfirmKey) return;
2101
+ if (deleteConfirmKey || keepOpenAfterToggleRef.current) return;
1889
2102
  clearCloseTimer();
1890
2103
  closeTimerRef.current = window.setTimeout(() => {
1891
2104
  setOpen(false);
1892
2105
  closeTimerRef.current = null;
1893
2106
  }, 120);
1894
2107
  };
2108
+ const handleToggle = (columnKey, visible) => {
2109
+ clearCloseTimer();
2110
+ keepOpenAfterToggleRef.current = true;
2111
+ onToggle(columnKey, visible);
2112
+ };
1895
2113
  return /* @__PURE__ */ jsxRuntime.jsxs(
1896
2114
  "div",
1897
2115
  {
@@ -1927,7 +2145,7 @@ function ColumnVisibilityItem(props) {
1927
2145
  disabled: item.disabled,
1928
2146
  indeterminate: !!item.indeterminate,
1929
2147
  onChange: (event) => {
1930
- onToggle(item.key, !!event.target.checked);
2148
+ handleToggle(item.key, !!event.target.checked);
1931
2149
  },
1932
2150
  children: [
1933
2151
  item.title,
@@ -1999,7 +2217,10 @@ function ColumnVisibilityItem(props) {
1999
2217
  placement: "rightTop",
2000
2218
  offset: 2,
2001
2219
  minWidth: 300,
2002
- onOpenChange: setOpen,
2220
+ onOpenChange: (nextOpen) => {
2221
+ if (!nextOpen) keepOpenAfterToggleRef.current = false;
2222
+ setOpen(nextOpen);
2223
+ },
2003
2224
  surfaceClassName: "canvas-react-scrollbar",
2004
2225
  surfaceStyle: {
2005
2226
  ...CONTEXT_MENU_SURFACE_STYLE,
@@ -2031,7 +2252,7 @@ function ColumnVisibilityItem(props) {
2031
2252
  ColumnVisibilityItem,
2032
2253
  {
2033
2254
  item: child,
2034
- onToggle,
2255
+ onToggle: handleToggle,
2035
2256
  onAddChild,
2036
2257
  onEdit,
2037
2258
  onDelete,
@@ -3329,36 +3550,193 @@ var toolButtonStyle = {
3329
3550
  lineHeight: 1,
3330
3551
  cursor: "pointer"
3331
3552
  };
3553
+ var sortOptions = [
3554
+ { value: "default", label: "\u9ED8\u8BA4" },
3555
+ { value: "ascend", label: "\u5347\u5E8F" },
3556
+ { value: "descend", label: "\u964D\u5E8F" }
3557
+ ];
3558
+ var summaryOptions = [
3559
+ { value: "original", label: "\u539F\u6C47\u603B" },
3560
+ { value: "none", label: "\u65E0\u6C47\u603B" },
3561
+ { value: "title", label: "\u6807\u9898" },
3562
+ { value: "sum", label: "\u6C42\u548C" },
3563
+ { value: "avg", label: "\u5E73\u5747\u503C" },
3564
+ { value: "count", label: "\u8BA1\u6570" },
3565
+ { value: "unionCount", label: "\u53BB\u91CD\u8BA1\u6570" },
3566
+ { value: "rowCount", label: "\u884C\u6570" },
3567
+ { value: "mergedRowCount", label: "\u5408\u5E76\u884C\u6570" },
3568
+ { value: "min", label: "\u6700\u5C0F\u503C" },
3569
+ { value: "max", label: "\u6700\u5927\u503C" }
3570
+ ];
3571
+ var roundingOptions = [
3572
+ { value: "round", label: "\u56DB\u820D\u4E94\u5165" },
3573
+ { value: "floor", label: "\u5411\u4E0B\u53D6\u6574" },
3574
+ { value: "ceil", label: "\u5411\u4E0A\u53D6\u6574" },
3575
+ { value: "truncate", label: "\u622A\u65AD" }
3576
+ ];
3577
+ var booleanOptions = [
3578
+ { value: "yes", label: "\u662F" },
3579
+ { value: "no", label: "\u5426" }
3580
+ ];
3581
+ function createExportDialogRows(columns) {
3582
+ return columns.map((column) => ({
3583
+ key: column.key,
3584
+ title: column.title,
3585
+ sortOrder: column.sortOrder,
3586
+ sortIndex: column.sortIndex,
3587
+ sortPriority: column.sortPriority,
3588
+ summaryType: column.summary.type,
3589
+ showTypePrefix: column.summary.showTypePrefix ? "yes" : "no",
3590
+ precision: column.summary.precision,
3591
+ roundingMode: column.summary.roundingMode,
3592
+ preserveTrailingZeros: column.summary.preserveTrailingZeros ? "yes" : "no"
3593
+ }));
3594
+ }
3595
+ function buildExportDialogSettings(rows, selectedKeys, includeSummary) {
3596
+ const selected = new Set(selectedKeys.map(String));
3597
+ return {
3598
+ columnKeys: rows.filter((row) => selected.has(row.key)).map((row) => row.key),
3599
+ sortState: rows.filter((row) => selected.has(row.key) && row.sortOrder !== "default").sort(
3600
+ (a, b) => (a.sortIndex ?? Number.MAX_SAFE_INTEGER) - (b.sortIndex ?? Number.MAX_SAFE_INTEGER)
3601
+ ).map((row) => ({
3602
+ key: row.key,
3603
+ order: row.sortOrder,
3604
+ ...row.sortPriority != null ? { priority: row.sortPriority } : {}
3605
+ })),
3606
+ summaries: Object.fromEntries(
3607
+ rows.map((row) => [
3608
+ row.key,
3609
+ {
3610
+ type: row.summaryType,
3611
+ showTypePrefix: row.showTypePrefix === "yes",
3612
+ precision: row.precision,
3613
+ roundingMode: row.roundingMode,
3614
+ preserveTrailingZeros: row.preserveTrailingZeros === "yes"
3615
+ }
3616
+ ])
3617
+ ),
3618
+ includeSummary
3619
+ };
3620
+ }
3332
3621
  function ReactListTableExportNameDialog({
3333
- request
3622
+ request,
3623
+ onClose,
3624
+ renderTable
3334
3625
  }) {
3626
+ const tableId = react.useId();
3335
3627
  const extension = request.fileName.match(/\.(xlsx|csv|txt|json)$/i)?.[0] ?? "";
3336
3628
  const [fileName, setFileName] = react.useState(
3337
3629
  extension ? request.fileName.slice(0, -extension.length) : request.fileName
3338
3630
  );
3339
- const [invalid, setInvalid] = react.useState(false);
3631
+ const [rows, setRows] = react.useState(() => createExportDialogRows(request.columns ?? []));
3632
+ const [selectedKeys, setSelectedKeys] = react.useState(
3633
+ () => (request.columns ?? []).filter((column) => column.selected !== false).map((column) => column.key)
3634
+ );
3635
+ const [includeSummary, setIncludeSummary] = react.useState(request.includeSummary ?? false);
3636
+ const [error, setError] = react.useState("");
3637
+ const columns = react.useMemo(
3638
+ () => [
3639
+ {
3640
+ key: "position",
3641
+ dataIndex: "key",
3642
+ title: "\u5217\u987A\u5E8F\uFF08\u62D6\u52A8\u884C\u6392\u5E8F\uFF09",
3643
+ width: 160,
3644
+ render: (_value, _row, index) => String(index + 1),
3645
+ headerAlign: "center",
3646
+ align: "center"
3647
+ },
3648
+ listTable.ROW_SELECTION_COLUMN,
3649
+ { key: "title", dataIndex: "title", title: "\u5217\u540D\u79F0", width: 190 },
3650
+ {
3651
+ key: "sortOrder",
3652
+ dataIndex: "sortOrder",
3653
+ title: "\u6570\u636E\u6392\u5E8F",
3654
+ width: 120,
3655
+ editable: true,
3656
+ formItemProps: { valueType: "select", clickCount: 1, options: sortOptions },
3657
+ render: (value) => sortOptions.find((option) => option.value === value)?.label ?? "\u9ED8\u8BA4"
3658
+ },
3659
+ ...includeSummary ? [{
3660
+ key: "summary-group",
3661
+ dataIndex: "summaryType",
3662
+ title: "\u6C47\u603B",
3663
+ children: [
3664
+ {
3665
+ key: "summaryType",
3666
+ dataIndex: "summaryType",
3667
+ title: "\u6C47\u603B\u65B9\u5F0F",
3668
+ width: 135,
3669
+ editable: true,
3670
+ formItemProps: { valueType: "select", clickCount: 1, options: summaryOptions.filter((option) => option.value !== "original" || request.columns?.some((column) => column.summary.type === "original")) },
3671
+ render: (value) => summaryOptions.find((option) => option.value === value)?.label ?? "\u65E0\u6C47\u603B"
3672
+ },
3673
+ {
3674
+ key: "showTypePrefix",
3675
+ dataIndex: "showTypePrefix",
3676
+ title: "\u6C47\u603B\u524D\u7F00",
3677
+ width: 115,
3678
+ editable: true,
3679
+ formItemProps: { valueType: "select", clickCount: 1, options: booleanOptions },
3680
+ render: (value) => value === "yes" ? "\u662F" : "\u5426"
3681
+ },
3682
+ {
3683
+ key: "precision",
3684
+ dataIndex: "precision",
3685
+ title: "\u6C47\u603B\u5C0F\u6570\u4F4D\u6570",
3686
+ width: 135,
3687
+ editable: true,
3688
+ formItemProps: { valueType: "number", clickCount: 1, min: 0, max: 20 }
3689
+ },
3690
+ {
3691
+ key: "roundingMode",
3692
+ dataIndex: "roundingMode",
3693
+ title: "\u53D6\u6574\u65B9\u5F0F",
3694
+ width: 130,
3695
+ editable: true,
3696
+ formItemProps: { valueType: "select", clickCount: 1, options: roundingOptions },
3697
+ render: (value) => roundingOptions.find((option) => option.value === value)?.label ?? "\u56DB\u820D\u4E94\u5165"
3698
+ },
3699
+ {
3700
+ key: "preserveTrailingZeros",
3701
+ dataIndex: "preserveTrailingZeros",
3702
+ title: "\u4FDD\u7559\u65E0\u6548\u96F6",
3703
+ width: 125,
3704
+ editable: true,
3705
+ formItemProps: { valueType: "select", clickCount: 1, options: booleanOptions },
3706
+ render: (value) => value === "yes" ? "\u662F" : "\u5426"
3707
+ }
3708
+ ]
3709
+ }] : []
3710
+ ],
3711
+ [includeSummary, request.columns]
3712
+ );
3340
3713
  const confirm = () => {
3341
- if (!fileName.trim()) {
3342
- setInvalid(true);
3343
- return;
3344
- }
3345
- request.onConfirm(`${fileName.trim()}${extension}`);
3714
+ if (!fileName.trim()) return setError("\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0");
3715
+ if (request.columns && !selectedKeys.length) return setError("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u5217");
3716
+ request.onConfirm(
3717
+ `${fileName.trim()}${extension}`,
3718
+ request.columns ? buildExportDialogSettings(rows, selectedKeys, includeSummary) : void 0
3719
+ );
3720
+ onClose?.();
3346
3721
  };
3347
3722
  return /* @__PURE__ */ jsxRuntime.jsxs(
3348
3723
  reactComponents.ReactModal,
3349
3724
  {
3350
3725
  open: true,
3351
3726
  title: "\u5BFC\u51FA\u6587\u4EF6",
3352
- width: 420,
3727
+ width: request.columns ? 1180 : 420,
3353
3728
  fullscreenable: false,
3354
- onCancel: request.onCancel,
3355
3729
  onOk: confirm,
3356
3730
  okText: "\u5BFC\u51FA",
3357
3731
  cancelText: "\u53D6\u6D88",
3732
+ onCancel: () => {
3733
+ onClose?.();
3734
+ request.onCancel();
3735
+ },
3358
3736
  children: [
3359
3737
  /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
3360
3738
  "\u6587\u4EF6\u540D\u79F0",
3361
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3739
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
3362
3740
  /* @__PURE__ */ jsxRuntime.jsx(
3363
3741
  reactComponents.ReactInput,
3364
3742
  {
@@ -3368,15 +3746,72 @@ function ReactListTableExportNameDialog({
3368
3746
  onFocus: (event) => event.target.select(),
3369
3747
  onChange: (event) => {
3370
3748
  setFileName(event.target.value);
3371
- setInvalid(false);
3749
+ setError("");
3372
3750
  },
3373
3751
  onPressEnter: confirm
3374
3752
  }
3375
3753
  ),
3376
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", style: { flexShrink: 0 }, children: extension })
3754
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": "\u6587\u4EF6\u540E\u7F00", children: extension })
3377
3755
  ] })
3378
3756
  ] }),
3379
- invalid ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: "\u8BF7\u8F93\u5165\u6587\u4EF6\u540D\u79F0" }) : null
3757
+ request.columns ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginTop: 16 }, children: [
3758
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 16, marginBottom: 8 }, children: [
3759
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600 }, children: "\u5BFC\u51FA\u8868\u683C\u5217" }),
3760
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
3761
+ /* @__PURE__ */ jsxRuntime.jsx(
3762
+ reactComponents.ReactCheckbox,
3763
+ {
3764
+ checked: includeSummary,
3765
+ "aria-label": "\u5BFC\u51FA\u6C47\u603B\u884C",
3766
+ onChange: (event) => setIncludeSummary(event.target.checked)
3767
+ }
3768
+ ),
3769
+ "\u5BFC\u51FA\u6C47\u603B\u884C"
3770
+ ] })
3771
+ ] }),
3772
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "min(45vh, 520px)", minHeight: 250, overflow: "hidden" }, children: renderTable({
3773
+ tableId,
3774
+ columns,
3775
+ dataSource: rows,
3776
+ rowKey: "key",
3777
+ rowHeight: 42,
3778
+ headerRowHeight: 38,
3779
+ toolbar: false,
3780
+ contextMenu: false,
3781
+ pagination: false,
3782
+ resizable: true,
3783
+ draggable: true,
3784
+ rowSelection: {
3785
+ type: "checkbox",
3786
+ selectedRowKeys: selectedKeys,
3787
+ selectRowByClick: false,
3788
+ columnWidth: 54,
3789
+ onChange: (keys) => {
3790
+ setSelectedKeys(keys);
3791
+ setError("");
3792
+ }
3793
+ },
3794
+ rowDrag: {
3795
+ enabled: true,
3796
+ droppable: true,
3797
+ allowSelfDrop: true,
3798
+ mode: "move",
3799
+ onDrop: ({ rows: dragged, insertIndex, source }) => {
3800
+ if (source.tableId !== tableId || insertIndex == null) return;
3801
+ const draggedKeys = new Set(dragged.map((row) => row.key));
3802
+ setRows((current) => {
3803
+ const moved = current.filter((row) => draggedKeys.has(row.key));
3804
+ const preceding = current.slice(0, insertIndex).filter((row) => !draggedKeys.has(row.key)).length;
3805
+ const remaining = current.filter((row) => !draggedKeys.has(row.key));
3806
+ remaining.splice(preceding, 0, ...moved);
3807
+ return remaining;
3808
+ });
3809
+ }
3810
+ },
3811
+ style: { width: "100%", height: "100%" }
3812
+ }) })
3813
+ ] }) : null,
3814
+ error ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#ff4d4f", marginTop: 8 }, children: error }) : null
3380
3815
  ]
3381
3816
  }
3382
3817
  );
@@ -4710,7 +5145,7 @@ function resolveSortableTransform(index, sourceIndex, targetIndex, height) {
4710
5145
  }
4711
5146
 
4712
5147
  // src/features/toolbar/style.css
4713
- 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-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");
5148
+ 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");
4714
5149
  function ReactTableToolbar(props) {
4715
5150
  const { toolbar, title } = props;
4716
5151
  const [densityOpen, setDensityOpen] = react.useState(false);
@@ -4825,7 +5260,10 @@ function ReactTableToolbar(props) {
4825
5260
  ToolButton,
4826
5261
  {
4827
5262
  label: "\u5217\u8BBE\u7F6E",
4828
- onClick: () => setSettingOpen((v) => !v),
5263
+ onClick: () => {
5264
+ if (!settingOpen) props.onColumnSettingsOpen();
5265
+ setSettingOpen((v) => !v);
5266
+ },
4829
5267
  children: /* @__PURE__ */ jsxRuntime.jsx(SettingOutlined, {})
4830
5268
  }
4831
5269
  ),
@@ -4833,7 +5271,7 @@ function ReactTableToolbar(props) {
4833
5271
  "div",
4834
5272
  {
4835
5273
  className: "react-list-table-column-setting",
4836
- style: { width: config.columnSettingWidth },
5274
+ style: { width: config.columnSettingWidth ?? 430 },
4837
5275
  children: [
4838
5276
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-column-setting-head", children: [
4839
5277
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "\u5217\u8BBE\u7F6E" }),
@@ -4913,6 +5351,29 @@ function ReactTableToolbar(props) {
4913
5351
  }
4914
5352
  }
4915
5353
  ),
5354
+ /* @__PURE__ */ jsxRuntime.jsx(
5355
+ reactComponents.ReactSelect,
5356
+ {
5357
+ className: "react-list-table-column-sort-input",
5358
+ value: props.sortState.find(
5359
+ (item) => item.key === column.key
5360
+ )?.order ?? "default",
5361
+ options: [
5362
+ { label: "\u9ED8\u8BA4\u6392\u5E8F", value: "default" },
5363
+ { label: "\u5347\u5E8F", value: "ascend" },
5364
+ { label: "\u964D\u5E8F", value: "descend" }
5365
+ ],
5366
+ disabled: !column.sortable,
5367
+ allowClear: false,
5368
+ showSearch: false,
5369
+ style: { width: "100%", height: 24 },
5370
+ "aria-label": `${column.label}\u6392\u5E8F\u65B9\u5F0F`,
5371
+ onChange: (value) => props.onColumnSortChange(
5372
+ column.key,
5373
+ value === "ascend" || value === "descend" ? value : null
5374
+ )
5375
+ }
5376
+ ),
4916
5377
  /* @__PURE__ */ jsxRuntime.jsx(
4917
5378
  reactComponents.ReactSelect,
4918
5379
  {
@@ -4978,7 +5439,8 @@ function flattenColumns(columns, parentKey = "root", level = 0) {
4978
5439
  fixed: column.fixed,
4979
5440
  level,
4980
5441
  isGroup: Boolean(column.children?.length),
4981
- disableHide: column.disableHide === true
5442
+ disableHide: column.disableHide === true,
5443
+ sortable: column.allowSort !== false && column.sorter !== false
4982
5444
  };
4983
5445
  return column.children?.length ? [current, ...flattenColumns(column.children, key, level + 1)] : [current];
4984
5446
  });
@@ -5047,6 +5509,7 @@ function useReactListTableState(options) {
5047
5509
  }),
5048
5510
  [options.ui]
5049
5511
  );
5512
+ const appliedOptionsRef = react.useRef(null);
5050
5513
  react.useEffect(() => {
5051
5514
  const container = containerRef.current;
5052
5515
  if (!container) {
@@ -5056,11 +5519,13 @@ function useReactListTableState(options) {
5056
5519
  ...options,
5057
5520
  ui: uiOptions
5058
5521
  });
5522
+ appliedOptionsRef.current = { options, uiOptions };
5059
5523
  table.mount();
5060
5524
  tableRef.current = table;
5061
5525
  return () => {
5062
5526
  table.destroy();
5063
5527
  tableRef.current = null;
5528
+ appliedOptionsRef.current = null;
5064
5529
  setEditorRequest(null);
5065
5530
  setPaginationConfig(null);
5066
5531
  setTooltipRequest(null);
@@ -5075,6 +5540,10 @@ function useReactListTableState(options) {
5075
5540
  };
5076
5541
  }, []);
5077
5542
  react.useEffect(() => {
5543
+ if (appliedOptionsRef.current?.options === options && appliedOptionsRef.current.uiOptions === uiOptions) {
5544
+ return;
5545
+ }
5546
+ appliedOptionsRef.current = { options, uiOptions };
5078
5547
  tableRef.current?.updateOptions({
5079
5548
  ...options,
5080
5549
  ui: uiOptions
@@ -5094,6 +5563,9 @@ function useReactListTableState(options) {
5094
5563
  imagePreviewRequest,
5095
5564
  dangerConfirmRequest,
5096
5565
  exportNameRequest,
5566
+ closeExportNameRequest: () => {
5567
+ setExportNameRequest(null);
5568
+ },
5097
5569
  closeDangerConfirmRequest: () => {
5098
5570
  setDangerConfirmRequest(null);
5099
5571
  options.ui?.onDangerConfirmRequest?.(null);
@@ -5155,6 +5627,70 @@ function resolveReactListTableDebugOptions(debug, inheritedEnabled) {
5155
5627
  enabled: true
5156
5628
  };
5157
5629
  }
5630
+
5631
+ // src/components/column-manager-state.ts
5632
+ function applyColumnManagerState(columns, visibility, orders, config, parentKey = "root") {
5633
+ const order = orders.get(parentKey);
5634
+ const sortedColumns = order ? applyManagedColumnOrder(columns, order) : columns;
5635
+ return sortedColumns.map((column) => {
5636
+ const key = resolveColumnKey(column);
5637
+ const managedConfig = config.get(key);
5638
+ return {
5639
+ ...column,
5640
+ hidden: visibility.has(key) ? visibility.get(key) === false : column.hidden ?? column.initialHide,
5641
+ width: managedConfig?.width ?? column.width,
5642
+ minWidth: column.minWidth,
5643
+ maxWidth: column.maxWidth,
5644
+ fixed: managedConfig?.fixed === null ? void 0 : managedConfig?.fixed ?? column.fixed,
5645
+ children: column.children ? applyColumnManagerState(
5646
+ column.children,
5647
+ visibility,
5648
+ orders,
5649
+ config,
5650
+ key
5651
+ ) : void 0
5652
+ };
5653
+ });
5654
+ }
5655
+ function applyManagedColumnOrder(columns, orderedKeys) {
5656
+ const managedKeySet = new Set(orderedKeys);
5657
+ const managedSlots = columns.map(
5658
+ (column, index) => managedKeySet.has(resolveColumnKey(column)) ? index : -1
5659
+ ).filter((index) => index >= 0);
5660
+ const columnByKey = new Map(
5661
+ columns.map((column) => [resolveColumnKey(column), column])
5662
+ );
5663
+ const next = [...columns];
5664
+ orderedKeys.forEach((key, index) => {
5665
+ const slot = managedSlots[index];
5666
+ const column = columnByKey.get(key);
5667
+ if (slot != null && column) {
5668
+ next[slot] = column;
5669
+ }
5670
+ });
5671
+ return next;
5672
+ }
5673
+ function resolveColumnKey(column) {
5674
+ return String(column.key ?? column.dataIndex);
5675
+ }
5676
+ function getColumnSettingsSignature(columns) {
5677
+ return JSON.stringify(
5678
+ columns.map((column) => ({
5679
+ key: resolveColumnKey(column),
5680
+ title: String(
5681
+ column.settingTitle ?? (typeof column.title === "string" ? column.title : "")
5682
+ ),
5683
+ dataIndex: column.dataIndex,
5684
+ userDefined: column.userDefined,
5685
+ hidden: column.hidden,
5686
+ width: column.width,
5687
+ minWidth: column.minWidth,
5688
+ maxWidth: column.maxWidth,
5689
+ fixed: column.fixed,
5690
+ children: column.children ? getColumnSettingsSignature(column.children) : void 0
5691
+ }))
5692
+ );
5693
+ }
5158
5694
  function ReactListTableInner(props, ref) {
5159
5695
  const {
5160
5696
  className,
@@ -5167,6 +5703,7 @@ function ReactListTableInner(props, ref) {
5167
5703
  onChange,
5168
5704
  rowKey,
5169
5705
  columns,
5706
+ showCollapsedColumnIcon,
5170
5707
  dataSource,
5171
5708
  loading,
5172
5709
  onRow,
@@ -5174,6 +5711,7 @@ function ReactListTableInner(props, ref) {
5174
5711
  styles,
5175
5712
  striped,
5176
5713
  highlightMode,
5714
+ keyboardNavigation,
5177
5715
  contextMenu,
5178
5716
  grouping,
5179
5717
  rowHeight,
@@ -5208,13 +5746,31 @@ function ReactListTableInner(props, ref) {
5208
5746
  );
5209
5747
  const shellRef = react.useRef(null);
5210
5748
  const [isFullscreen, setIsFullscreen] = react.useState(false);
5749
+ const [scrollbarOverride, setScrollbarOverride] = react.useState(null);
5750
+ const [sharedScrollbar, setSharedScrollbar] = react.useState(
5751
+ reactComponents.getSharedScrollbarSettings
5752
+ );
5753
+ react.useEffect(
5754
+ () => reactComponents.subscribeSharedScrollbarSettings(
5755
+ () => setSharedScrollbar(reactComponents.getSharedScrollbarSettings())
5756
+ ),
5757
+ []
5758
+ );
5759
+ const effectiveScrollbar = sharedScrollbar.shared ? sharedScrollbar.value : scrollbarOverride ?? scrollbar;
5211
5760
  const [densityOverride, setDensityOverride] = react.useState(null);
5212
5761
  const [columnVisibility, setColumnVisibility] = react.useState(() => /* @__PURE__ */ new Map());
5213
5762
  const [columnOrders, setColumnOrders] = react.useState(
5214
5763
  () => /* @__PURE__ */ new Map()
5215
5764
  );
5216
5765
  const [columnConfig, setColumnConfig] = react.useState(() => /* @__PURE__ */ new Map());
5766
+ const restoredColumnTreeRef = react.useRef(null);
5767
+ const [restoredColumnTree, setRestoredColumnTree] = react.useState(
5768
+ restoredColumnTreeRef.current
5769
+ );
5217
5770
  const [columnConfigRevision, setColumnConfigRevision] = react.useState(0);
5771
+ const [toolbarSortState, setToolbarSortState] = react.useState(
5772
+ []
5773
+ );
5218
5774
  const [columnSettingsCacheOverride, setColumnSettingsCacheOverride] = react.useState(null);
5219
5775
  const resolvedColumnSettingsCache = (columnSettingsCacheOverride?.storageKey === storageKey ? columnSettingsCacheOverride?.value : void 0) ?? cacheColumnSettings ?? true;
5220
5776
  const [cachePreferencesOverride, setCachePreferencesOverride] = react.useState();
@@ -5222,12 +5778,19 @@ function ReactListTableInner(props, ref) {
5222
5778
  const [columnConfigResetRevision, setColumnConfigResetRevision] = react.useState(0);
5223
5779
  const resolvedColumns = react.useMemo(
5224
5780
  () => applyColumnManagerState(
5225
- columns,
5781
+ restoredColumnTree?.sourceColumns === columns && restoredColumnTree.storageKey === storageKey ? restoredColumnTree.columns : columns,
5226
5782
  columnVisibility,
5227
5783
  columnOrders,
5228
5784
  columnConfig
5229
5785
  ),
5230
- [columns, columnVisibility, columnOrders, columnConfig]
5786
+ [
5787
+ columns,
5788
+ storageKey,
5789
+ restoredColumnTree,
5790
+ columnVisibility,
5791
+ columnOrders,
5792
+ columnConfig
5793
+ ]
5231
5794
  );
5232
5795
  const resolvedRowHeight = densityOverride ?? rowHeight;
5233
5796
  const resolvedHeaderRowHeight = resolveDensityLinkedHeight(
@@ -5249,6 +5812,7 @@ function ReactListTableInner(props, ref) {
5249
5812
  onChange,
5250
5813
  rowKey,
5251
5814
  columns: resolvedColumns,
5815
+ showCollapsedColumnIcon,
5252
5816
  dataSource,
5253
5817
  loading,
5254
5818
  onRow,
@@ -5256,6 +5820,7 @@ function ReactListTableInner(props, ref) {
5256
5820
  styles,
5257
5821
  striped,
5258
5822
  highlightMode,
5823
+ keyboardNavigation,
5259
5824
  contextMenu,
5260
5825
  grouping,
5261
5826
  rowHeight: resolvedRowHeight,
@@ -5268,7 +5833,7 @@ function ReactListTableInner(props, ref) {
5268
5833
  rowSelection,
5269
5834
  expandable,
5270
5835
  pagination,
5271
- scrollbar,
5836
+ scrollbar: effectiveScrollbar,
5272
5837
  carouselScroll,
5273
5838
  stretchColumns,
5274
5839
  resizable,
@@ -5293,6 +5858,24 @@ function ReactListTableInner(props, ref) {
5293
5858
  ui: {
5294
5859
  ...nextOptions.ui,
5295
5860
  onDensityChange: setDensityOverride,
5861
+ onScrollbarChange: setScrollbarOverride,
5862
+ onColumnSettingsChange: (restoredColumns) => {
5863
+ const signature = getColumnSettingsSignature(restoredColumns);
5864
+ const current = restoredColumnTreeRef.current;
5865
+ if (current?.sourceColumns === columns && current.storageKey === storageKey && current.signature === signature)
5866
+ return;
5867
+ const next = {
5868
+ sourceColumns: columns,
5869
+ storageKey,
5870
+ columns: restoredColumns,
5871
+ signature
5872
+ };
5873
+ restoredColumnTreeRef.current = next;
5874
+ setRestoredColumnTree(next);
5875
+ setColumnVisibility(/* @__PURE__ */ new Map());
5876
+ setColumnOrders(/* @__PURE__ */ new Map());
5877
+ setColumnConfig(/* @__PURE__ */ new Map());
5878
+ },
5296
5879
  onColumnSettingsCacheChange: (value) => setColumnSettingsCacheOverride(
5297
5880
  (current) => current?.storageKey === storageKey && current?.value === value ? current : { storageKey, value }
5298
5881
  ),
@@ -5311,6 +5894,7 @@ function ReactListTableInner(props, ref) {
5311
5894
  onChange,
5312
5895
  rowKey,
5313
5896
  resolvedColumns,
5897
+ showCollapsedColumnIcon,
5314
5898
  dataSource,
5315
5899
  loading,
5316
5900
  onRow,
@@ -5318,6 +5902,7 @@ function ReactListTableInner(props, ref) {
5318
5902
  styles,
5319
5903
  striped,
5320
5904
  highlightMode,
5905
+ keyboardNavigation,
5321
5906
  contextMenu,
5322
5907
  grouping,
5323
5908
  resolvedRowHeight,
@@ -5330,7 +5915,7 @@ function ReactListTableInner(props, ref) {
5330
5915
  rowSelection,
5331
5916
  expandable,
5332
5917
  pagination,
5333
- scrollbar,
5918
+ effectiveScrollbar,
5334
5919
  carouselScroll,
5335
5920
  stretchColumns,
5336
5921
  resizable,
@@ -5359,6 +5944,7 @@ function ReactListTableInner(props, ref) {
5359
5944
  imagePreviewRequest,
5360
5945
  dangerConfirmRequest,
5361
5946
  exportNameRequest,
5947
+ closeExportNameRequest,
5362
5948
  closeDangerConfirmRequest
5363
5949
  } = useReactListTableState(options);
5364
5950
  const hasPagination = paginationConfig != null;
@@ -5411,6 +5997,12 @@ function ReactListTableInner(props, ref) {
5411
5997
  columnSettingsCacheAvailable: Boolean(storageKey),
5412
5998
  onColumnSettingsCacheChange: (enabled) => tableRef.current?.setColumnSettingsCache(enabled),
5413
5999
  columns: resolvedColumns,
6000
+ sortState: toolbarSortState,
6001
+ onColumnSettingsOpen: () => setToolbarSortState(tableRef.current?.getSortState() ?? []),
6002
+ onColumnSortChange: (columnKey, order) => {
6003
+ tableRef.current?.setSortOrder(columnKey, order);
6004
+ setToolbarSortState(tableRef.current?.getSortState() ?? []);
6005
+ },
5414
6006
  density: resolvedRowHeight ?? 32,
5415
6007
  hostRef: shellRef,
5416
6008
  onFullscreenChange: setIsFullscreen,
@@ -5474,6 +6066,8 @@ function ReactListTableInner(props, ref) {
5474
6066
  setColumnVisibility(/* @__PURE__ */ new Map());
5475
6067
  setColumnOrders(/* @__PURE__ */ new Map());
5476
6068
  setColumnConfig(/* @__PURE__ */ new Map());
6069
+ restoredColumnTreeRef.current = null;
6070
+ setRestoredColumnTree(null);
5477
6071
  setColumnConfigResetRevision((current) => current + 1);
5478
6072
  setColumnConfigRevision((current) => current + 1);
5479
6073
  });
@@ -5531,16 +6125,43 @@ function ReactListTableInner(props, ref) {
5531
6125
  /* @__PURE__ */ jsxRuntime.jsx(ReactTableFixedPopupView, { request: fixedPopupRequest }),
5532
6126
  portalContainer
5533
6127
  ) : null,
5534
- headerContextMenuRequest ? reactDom.createPortal(
5535
- /* @__PURE__ */ jsxRuntime.jsx(ReactTableContextMenuView, { request: headerContextMenuRequest }),
6128
+ reactDom.createPortal(
6129
+ /* @__PURE__ */ jsxRuntime.jsx(
6130
+ ReactTableContextMenuView,
6131
+ {
6132
+ request: headerContextMenuRequest ? {
6133
+ ...headerContextMenuRequest,
6134
+ scrollbar: effectiveScrollbar,
6135
+ onChangeScrollbar: (value) => {
6136
+ headerContextMenuRequest.onChangeScrollbar?.(value);
6137
+ setScrollbarOverride(value);
6138
+ if (reactComponents.getSharedScrollbarSettings().shared)
6139
+ reactComponents.setSharedScrollbarSettings({ shared: true, value });
6140
+ },
6141
+ onResetScrollbar: () => {
6142
+ headerContextMenuRequest.onResetScrollbar?.();
6143
+ setScrollbarOverride(null);
6144
+ if (reactComponents.getSharedScrollbarSettings().shared)
6145
+ reactComponents.setSharedScrollbarSettings({ shared: true, value: {} });
6146
+ }
6147
+ } : null
6148
+ }
6149
+ ),
5536
6150
  portalContainer
5537
- ) : null,
6151
+ ),
5538
6152
  searchRequest ? reactDom.createPortal(
5539
6153
  /* @__PURE__ */ jsxRuntime.jsx(ReactListTableSearchDialog, { request: searchRequest }),
5540
6154
  portalContainer
5541
6155
  ) : null,
5542
6156
  exportNameRequest ? reactDom.createPortal(
5543
- /* @__PURE__ */ jsxRuntime.jsx(ReactListTableExportNameDialog, { request: exportNameRequest }),
6157
+ /* @__PURE__ */ jsxRuntime.jsx(
6158
+ ReactListTableExportNameDialog,
6159
+ {
6160
+ request: exportNameRequest,
6161
+ onClose: closeExportNameRequest,
6162
+ renderTable: (tableProps) => /* @__PURE__ */ jsxRuntime.jsx(ReactListTable, { ...tableProps })
6163
+ }
6164
+ ),
5544
6165
  portalContainer
5545
6166
  ) : null,
5546
6167
  dangerConfirmRequest ? reactDom.createPortal(
@@ -5571,50 +6192,6 @@ function ReactListTableInner(props, ref) {
5571
6192
  ) : null
5572
6193
  ] });
5573
6194
  }
5574
- function applyColumnManagerState(columns, visibility, orders, config, parentKey = "root") {
5575
- const order = orders.get(parentKey);
5576
- const sortedColumns = order ? applyManagedColumnOrder(columns, order) : columns;
5577
- return sortedColumns.map((column) => {
5578
- const key = resolveColumnKey(column);
5579
- const managedConfig = config.get(key);
5580
- return {
5581
- ...column,
5582
- hidden: visibility.has(key) ? visibility.get(key) === false : column.hidden ?? column.initialHide,
5583
- width: managedConfig?.width ?? column.width,
5584
- minWidth: column.minWidth,
5585
- maxWidth: column.maxWidth,
5586
- fixed: managedConfig?.fixed === null ? void 0 : managedConfig?.fixed ?? column.fixed,
5587
- children: column.children ? applyColumnManagerState(
5588
- column.children,
5589
- visibility,
5590
- orders,
5591
- config,
5592
- key
5593
- ) : void 0
5594
- };
5595
- });
5596
- }
5597
- function applyManagedColumnOrder(columns, orderedKeys) {
5598
- const managedKeySet = new Set(orderedKeys);
5599
- const managedSlots = columns.map(
5600
- (column, index) => managedKeySet.has(resolveColumnKey(column)) ? index : -1
5601
- ).filter((index) => index >= 0);
5602
- const columnByKey = new Map(
5603
- columns.map((column) => [resolveColumnKey(column), column])
5604
- );
5605
- const next = [...columns];
5606
- orderedKeys.forEach((key, index) => {
5607
- const slot = managedSlots[index];
5608
- const column = columnByKey.get(key);
5609
- if (slot != null && column) {
5610
- next[slot] = column;
5611
- }
5612
- });
5613
- return next;
5614
- }
5615
- function resolveColumnKey(column) {
5616
- return String(column.key ?? column.dataIndex);
5617
- }
5618
6195
  var ReactListTable = react.forwardRef(
5619
6196
  ReactListTableInner
5620
6197
  );
@@ -5640,5 +6217,6 @@ Object.defineProperty(exports, "getListTableStoredPageSize", {
5640
6217
  });
5641
6218
  exports.ReactListTable = ReactListTable;
5642
6219
  exports.ReactListTableDebugProvider = ReactListTableDebugProvider;
6220
+ exports.ReactListTableExportNameDialog = ReactListTableExportNameDialog;
5643
6221
  //# sourceMappingURL=index.cjs.map
5644
6222
  //# sourceMappingURL=index.cjs.map