@canvas-components/react-list-table 0.2.1 → 0.2.3

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
@@ -164,6 +164,8 @@ function ReactTableContextMenuView(props) {
164
164
  }
165
165
  ),
166
166
  /* @__PURE__ */ jsxRuntime.jsx(SummaryMenu, { request }),
167
+ /* @__PURE__ */ jsxRuntime.jsx(AlignmentMenu, { request }),
168
+ /* @__PURE__ */ jsxRuntime.jsx(DataFormatMenu, { request }),
167
169
  /* @__PURE__ */ jsxRuntime.jsx(
168
170
  MenuSubmenu,
169
171
  {
@@ -217,13 +219,7 @@ function ReactTableContextMenuView(props) {
217
219
  onChange: request.onChangeDensity
218
220
  }
219
221
  ),
220
- /* @__PURE__ */ jsxRuntime.jsx(
221
- ZoomMenu,
222
- {
223
- value: request.zoom ?? 1,
224
- onChange: request.onChangeZoom
225
- }
226
- ),
222
+ /* @__PURE__ */ jsxRuntime.jsx(ZoomMenu, { value: request.zoom ?? 1, onChange: request.onChangeZoom }),
227
223
  request.columns?.length && request.onToggleColumn ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
228
224
  /* @__PURE__ */ jsxRuntime.jsx(MenuDivider, {}),
229
225
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -524,11 +520,11 @@ function ZoomMenu(props) {
524
520
  anchorRef: triggerRef,
525
521
  placement: "rightTop",
526
522
  offset: 2,
527
- minWidth: 220,
523
+ minWidth: 280,
528
524
  onOpenChange: setOpen,
529
525
  surfaceStyle: {
530
526
  ...CONTEXT_MENU_SURFACE_STYLE,
531
- width: 220
527
+ width: 280
532
528
  },
533
529
  children: /* @__PURE__ */ jsxRuntime.jsxs(
534
530
  "div",
@@ -557,45 +553,58 @@ function ZoomMenu(props) {
557
553
  children: "\u8868\u683C\u7F29\u653E\uFF0850% - 200%\uFF09"
558
554
  }
559
555
  ),
560
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0 8px 4px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
561
- reactComponents.ReactInputNumber,
562
- {
563
- value: percent,
564
- min: CONTEXT_MENU_ZOOM_MIN,
565
- max: CONTEXT_MENU_ZOOM_MAX,
566
- step: CONTEXT_MENU_ZOOM_STEP,
567
- precision: 0,
568
- addonAfter: "%",
569
- onChange: (next) => {
570
- if (next == null || !Number.isFinite(next)) {
571
- return;
572
- }
573
- onChange(Math.round(next) / 100);
574
- }
575
- }
576
- ) }),
577
- /* @__PURE__ */ jsxRuntime.jsx(
578
- "button",
556
+ /* @__PURE__ */ jsxRuntime.jsxs(
557
+ "div",
579
558
  {
580
- type: "button",
581
- disabled: percent === 100,
582
- onClick: () => {
583
- onChange(1);
584
- },
585
- className: "react-list-table-menu-action",
586
559
  style: {
587
- display: "block",
588
- width: "100%",
589
- height: 32,
590
- padding: "0 8px",
591
- border: "none",
592
- borderRadius: 8,
593
- background: "transparent",
594
- color: percent === 100 ? "#9ca3af" : "#374151",
595
- textAlign: "left",
596
- cursor: percent === 100 ? "not-allowed" : "pointer"
560
+ display: "flex",
561
+ alignItems: "stretch",
562
+ gap: 6,
563
+ padding: "0 8px 4px"
597
564
  },
598
- children: "\u91CD\u7F6E\u7F29\u653E"
565
+ children: [
566
+ /* @__PURE__ */ jsxRuntime.jsx(
567
+ reactComponents.ReactInputNumber,
568
+ {
569
+ value: percent,
570
+ min: CONTEXT_MENU_ZOOM_MIN,
571
+ max: CONTEXT_MENU_ZOOM_MAX,
572
+ step: CONTEXT_MENU_ZOOM_STEP,
573
+ precision: 0,
574
+ addonAfter: "%",
575
+ style: { flex: "1 1 auto", minWidth: 0 },
576
+ onChange: (next) => {
577
+ if (next == null || !Number.isFinite(next)) {
578
+ return;
579
+ }
580
+ onChange(Math.round(next) / 100);
581
+ }
582
+ }
583
+ ),
584
+ /* @__PURE__ */ jsxRuntime.jsx(
585
+ "button",
586
+ {
587
+ type: "button",
588
+ disabled: percent === 100,
589
+ onClick: () => {
590
+ onChange(1);
591
+ },
592
+ className: "react-list-table-menu-action",
593
+ style: {
594
+ flex: "0 0 52px",
595
+ height: 32,
596
+ padding: 0,
597
+ border: "1px solid #d1d5db",
598
+ borderRadius: 6,
599
+ background: "#ffffff",
600
+ color: percent === 100 ? "#9ca3af" : "#374151",
601
+ textAlign: "center",
602
+ cursor: percent === 100 ? "not-allowed" : "pointer"
603
+ },
604
+ children: "\u91CD\u7F6E"
605
+ }
606
+ )
607
+ ]
599
608
  }
600
609
  )
601
610
  ]
@@ -1061,6 +1070,129 @@ function SummaryMenu(props) {
1061
1070
  }
1062
1071
  );
1063
1072
  }
1073
+ function AlignmentMenu(props) {
1074
+ const { request } = props;
1075
+ if (!request.alignment || !request.onChangeAlignment) {
1076
+ return null;
1077
+ }
1078
+ return /* @__PURE__ */ jsxRuntime.jsx(
1079
+ MenuSubmenu,
1080
+ {
1081
+ label: "\u5BF9\u9F50\u65B9\u5F0F",
1082
+ items: [],
1083
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 10, padding: "4px 8px" }, children: [
1084
+ /* @__PURE__ */ jsxRuntime.jsx(
1085
+ AlignmentGroup,
1086
+ {
1087
+ label: "\u8868\u5934",
1088
+ horizontal: request.alignment.headerHorizontal,
1089
+ vertical: request.alignment.headerVertical,
1090
+ onHorizontalChange: (value) => request.onChangeAlignment?.("header", "horizontal", value),
1091
+ onVerticalChange: (value) => request.onChangeAlignment?.("header", "vertical", value)
1092
+ }
1093
+ ),
1094
+ /* @__PURE__ */ jsxRuntime.jsx(
1095
+ AlignmentGroup,
1096
+ {
1097
+ label: "\u8868\u4F53",
1098
+ horizontal: request.alignment.bodyHorizontal,
1099
+ vertical: request.alignment.bodyVertical,
1100
+ onHorizontalChange: (value) => request.onChangeAlignment?.("body", "horizontal", value),
1101
+ onVerticalChange: (value) => request.onChangeAlignment?.("body", "vertical", value)
1102
+ }
1103
+ )
1104
+ ] })
1105
+ }
1106
+ );
1107
+ }
1108
+ function AlignmentGroup(props) {
1109
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 6 }, children: [
1110
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: "#374151", fontSize: 13 }, children: props.label }),
1111
+ /* @__PURE__ */ jsxRuntime.jsx(
1112
+ AlignmentSegment,
1113
+ {
1114
+ label: "\u6C34\u5E73",
1115
+ value: props.horizontal,
1116
+ options: [
1117
+ { label: "\u5DE6", value: "left" },
1118
+ { label: "\u4E2D", value: "center" },
1119
+ { label: "\u53F3", value: "right" }
1120
+ ],
1121
+ onChange: props.onHorizontalChange
1122
+ }
1123
+ ),
1124
+ /* @__PURE__ */ jsxRuntime.jsx(
1125
+ AlignmentSegment,
1126
+ {
1127
+ label: "\u5782\u76F4",
1128
+ value: props.vertical,
1129
+ options: [
1130
+ { label: "\u4E0A", value: "top" },
1131
+ { label: "\u4E2D", value: "middle" },
1132
+ { label: "\u4E0B", value: "bottom" }
1133
+ ],
1134
+ onChange: props.onVerticalChange
1135
+ }
1136
+ )
1137
+ ] });
1138
+ }
1139
+ function AlignmentSegment(props) {
1140
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1141
+ "div",
1142
+ {
1143
+ style: {
1144
+ display: "grid",
1145
+ gridTemplateColumns: "40px repeat(3, 1fr)",
1146
+ gap: 4,
1147
+ alignItems: "center"
1148
+ },
1149
+ children: [
1150
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#6b7280", fontSize: 12 }, children: props.label }),
1151
+ props.options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
1152
+ "button",
1153
+ {
1154
+ type: "button",
1155
+ className: "react-list-table-menu-action",
1156
+ style: {
1157
+ height: 28,
1158
+ border: "1px solid #d1d5db",
1159
+ borderRadius: 4,
1160
+ background: props.value === option.value ? "#e8f3ff" : "#ffffff",
1161
+ color: props.value === option.value ? "#1677ff" : "#374151",
1162
+ cursor: "pointer"
1163
+ },
1164
+ onClick: () => props.onChange(option.value),
1165
+ children: option.label
1166
+ },
1167
+ option.value
1168
+ ))
1169
+ ]
1170
+ }
1171
+ );
1172
+ }
1173
+ function DataFormatMenu(props) {
1174
+ const { request } = props;
1175
+ if (!request.onChangeDataFormat) {
1176
+ return null;
1177
+ }
1178
+ return /* @__PURE__ */ jsxRuntime.jsx(
1179
+ MenuSubmenu,
1180
+ {
1181
+ label: "\u6570\u636E\u683C\u5F0F",
1182
+ items: [
1183
+ { key: "default", label: "\u9ED8\u8BA4", value: "default" },
1184
+ { key: "number", label: "\u666E\u901A\u6570\u5B57", value: "number" },
1185
+ { key: "thousands", label: "\u5343\u4F4D\u5206\u9694", value: "thousands" },
1186
+ { key: "money", label: "\u91D1\u989D\uFF08\u4E24\u4F4D\u5C0F\u6570\uFF09", value: "money" }
1187
+ ].map((item) => ({
1188
+ key: `data-format-${item.key}`,
1189
+ label: item.label,
1190
+ selected: request.dataFormat === item.value,
1191
+ onClick: () => request.onChangeDataFormat?.(item.value)
1192
+ }))
1193
+ }
1194
+ );
1195
+ }
1064
1196
 
1065
1197
  // src/features/editor/utils.ts
1066
1198
  function toNumberValue(value) {
@@ -2301,7 +2433,15 @@ function ReactTableToolbar(props) {
2301
2433
  children: isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(FullscreenExitOutlined, {}) : /* @__PURE__ */ jsxRuntime.jsx(FullscreenOutlined, {})
2302
2434
  }
2303
2435
  ) : null,
2304
- config.showRefresh !== false ? /* @__PURE__ */ jsxRuntime.jsx(ToolButton, { label: "\u5237\u65B0", iconSize: 14, onClick: () => config.onRefresh?.(), children: /* @__PURE__ */ jsxRuntime.jsx(ReloadOutlined, {}) }) : null,
2436
+ config.showRefresh !== false ? /* @__PURE__ */ jsxRuntime.jsx(
2437
+ ToolButton,
2438
+ {
2439
+ label: "\u5237\u65B0",
2440
+ iconSize: 14,
2441
+ onClick: () => config.onRefresh?.(),
2442
+ children: /* @__PURE__ */ jsxRuntime.jsx(ReloadOutlined, {})
2443
+ }
2444
+ ) : null,
2305
2445
  config.showExport ? /* @__PURE__ */ jsxRuntime.jsx(
2306
2446
  ToolButton,
2307
2447
  {
@@ -2311,14 +2451,21 @@ function ReactTableToolbar(props) {
2311
2451
  if (config.onExport) {
2312
2452
  config.onExport();
2313
2453
  } else {
2314
- props.onExport();
2454
+ props.onExport(config.exportOptions);
2315
2455
  }
2316
2456
  },
2317
2457
  children: /* @__PURE__ */ jsxRuntime.jsx(ExportOutlined, {})
2318
2458
  }
2319
2459
  ) : null,
2320
2460
  config.showDensity !== false ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-tool-wrap", children: [
2321
- /* @__PURE__ */ jsxRuntime.jsx(ToolButton, { label: "\u8868\u683C\u5BC6\u5EA6", onClick: () => setDensityOpen((v) => !v), children: /* @__PURE__ */ jsxRuntime.jsx(ColumnHeightOutlined, {}) }),
2461
+ /* @__PURE__ */ jsxRuntime.jsx(
2462
+ ToolButton,
2463
+ {
2464
+ label: "\u8868\u683C\u5BC6\u5EA6",
2465
+ onClick: () => setDensityOpen((v) => !v),
2466
+ children: /* @__PURE__ */ jsxRuntime.jsx(ColumnHeightOutlined, {})
2467
+ }
2468
+ ),
2322
2469
  densityOpen ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "react-list-table-tool-menu", children: [48, 40, 32].map((height) => /* @__PURE__ */ jsxRuntime.jsx(
2323
2470
  "button",
2324
2471
  {
@@ -2334,7 +2481,14 @@ function ReactTableToolbar(props) {
2334
2481
  )) }) : null
2335
2482
  ] }) : null,
2336
2483
  config.showColumnSetting !== false ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-tool-wrap", children: [
2337
- /* @__PURE__ */ jsxRuntime.jsx(ToolButton, { label: "\u5217\u8BBE\u7F6E", onClick: () => setSettingOpen((v) => !v), children: /* @__PURE__ */ jsxRuntime.jsx(SettingOutlined, {}) }),
2484
+ /* @__PURE__ */ jsxRuntime.jsx(
2485
+ ToolButton,
2486
+ {
2487
+ label: "\u5217\u8BBE\u7F6E",
2488
+ onClick: () => setSettingOpen((v) => !v),
2489
+ children: /* @__PURE__ */ jsxRuntime.jsx(SettingOutlined, {})
2490
+ }
2491
+ ),
2338
2492
  settingOpen ? /* @__PURE__ */ jsxRuntime.jsxs(
2339
2493
  "div",
2340
2494
  {
@@ -2343,6 +2497,7 @@ function ReactTableToolbar(props) {
2343
2497
  children: [
2344
2498
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "react-list-table-column-setting-head", children: [
2345
2499
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "\u5217\u8BBE\u7F6E" }),
2500
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: "auto" }, children: config.columnSettingHeaderExtra }),
2346
2501
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: props.onResetColumns, children: "\u91CD\u7F6E" })
2347
2502
  ] }),
2348
2503
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "react-list-table-column-setting-body", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -2374,6 +2529,7 @@ function ReactTableToolbar(props) {
2374
2529
  {
2375
2530
  type: "checkbox",
2376
2531
  checked: !column.hidden,
2532
+ disabled: column.disableHide,
2377
2533
  onChange: (event) => props.onColumnVisibilityChange(
2378
2534
  column.key,
2379
2535
  event.target.checked
@@ -2397,7 +2553,10 @@ function ReactTableToolbar(props) {
2397
2553
  style: { width: 80, height: 24 },
2398
2554
  onChange: (width) => {
2399
2555
  if (width != null && Number.isFinite(width) && width > 0 && (column.minWidth == null || width >= column.minWidth) && (column.maxWidth == null || width <= column.maxWidth)) {
2400
- props.onColumnWidthChange(column.key, width);
2556
+ props.onColumnWidthChange(
2557
+ column.key,
2558
+ width
2559
+ );
2401
2560
  }
2402
2561
  }
2403
2562
  }
@@ -2436,12 +2595,26 @@ function ReactTableToolbar(props) {
2436
2595
  ] });
2437
2596
  }
2438
2597
  function ToolButton(props) {
2439
- return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "react-list-table-tool", style: { fontSize: props.iconSize ?? 16 }, title: props.label, "aria-label": props.label, onClick: props.onClick, children: props.children });
2598
+ return /* @__PURE__ */ jsxRuntime.jsx(
2599
+ "button",
2600
+ {
2601
+ type: "button",
2602
+ className: "react-list-table-tool",
2603
+ style: { fontSize: props.iconSize ?? 16 },
2604
+ title: props.label,
2605
+ "aria-label": props.label,
2606
+ onClick: props.onClick,
2607
+ children: props.children
2608
+ }
2609
+ );
2440
2610
  }
2441
2611
  function flattenColumns(columns, parentKey = "root", level = 0) {
2442
2612
  return columns.flatMap((column) => {
2613
+ if (column.hideInSetting) {
2614
+ return [];
2615
+ }
2443
2616
  const key = String(column.key ?? column.dataIndex);
2444
- const label = typeof column.title === "string" ? column.title : key;
2617
+ const label = column.settingTitle ?? (typeof column.title === "string" ? column.title : key);
2445
2618
  const current = {
2446
2619
  key,
2447
2620
  label,
@@ -2452,7 +2625,8 @@ function flattenColumns(columns, parentKey = "root", level = 0) {
2452
2625
  maxWidth: typeof column.maxWidth === "number" ? column.maxWidth : void 0,
2453
2626
  fixed: column.fixed,
2454
2627
  level,
2455
- isGroup: Boolean(column.children?.length)
2628
+ isGroup: Boolean(column.children?.length),
2629
+ disableHide: column.disableHide === true
2456
2630
  };
2457
2631
  return column.children?.length ? [current, ...flattenColumns(column.children, key, level + 1)] : [current];
2458
2632
  });
@@ -2598,6 +2772,7 @@ function ReactListTableInner(props, ref) {
2598
2772
  rowKey,
2599
2773
  columns,
2600
2774
  dataSource,
2775
+ onRow,
2601
2776
  theme,
2602
2777
  striped,
2603
2778
  highlightMode,
@@ -2652,6 +2827,7 @@ function ReactListTableInner(props, ref) {
2652
2827
  rowKey,
2653
2828
  columns: resolvedColumns,
2654
2829
  dataSource,
2830
+ onRow,
2655
2831
  theme,
2656
2832
  striped,
2657
2833
  highlightMode,
@@ -2684,6 +2860,7 @@ function ReactListTableInner(props, ref) {
2684
2860
  rowKey,
2685
2861
  resolvedColumns,
2686
2862
  dataSource,
2863
+ onRow,
2687
2864
  theme,
2688
2865
  striped,
2689
2866
  highlightMode,
@@ -2726,8 +2903,8 @@ function ReactListTableInner(props, ref) {
2726
2903
  ref,
2727
2904
  () => ({
2728
2905
  validate: () => tableRef.current?.validate() ?? Promise.resolve([]),
2729
- exportXlsx: () => {
2730
- tableRef.current?.exportXlsx();
2906
+ exportXlsx: (options2) => {
2907
+ tableRef.current?.exportXlsx(options2);
2731
2908
  },
2732
2909
  scrollTo: (options2) => {
2733
2910
  tableRef.current?.scrollTo(options2);
@@ -2764,8 +2941,13 @@ function ReactListTableInner(props, ref) {
2764
2941
  columns: resolvedColumns,
2765
2942
  density: resolvedRowHeight === "auto" ? 40 : resolvedRowHeight ?? 40,
2766
2943
  hostRef: shellRef,
2767
- onExport: () => tableRef.current?.exportXlsx(),
2768
- onDensityChange: setDensityOverride,
2944
+ onExport: (options2) => tableRef.current?.exportXlsx(options2),
2945
+ onDensityChange: (density) => {
2946
+ setDensityOverride(density);
2947
+ if (toolbar) {
2948
+ toolbar.onDensityChange?.(density);
2949
+ }
2950
+ },
2769
2951
  onColumnVisibilityChange: (columnKey, visible) => {
2770
2952
  setColumnVisibility((current) => {
2771
2953
  const next = new Map(current);
@@ -2882,15 +3064,13 @@ function ReactListTableInner(props, ref) {
2882
3064
  }
2883
3065
  function applyColumnManagerState(columns, visibility, orders, config, parentKey = "root") {
2884
3066
  const order = orders.get(parentKey);
2885
- const sortedColumns = order ? [...columns].sort(
2886
- (left, right) => order.indexOf(resolveColumnKey(left)) - order.indexOf(resolveColumnKey(right))
2887
- ) : columns;
3067
+ const sortedColumns = order ? applyManagedColumnOrder(columns, order) : columns;
2888
3068
  return sortedColumns.map((column) => {
2889
3069
  const key = resolveColumnKey(column);
2890
3070
  const managedConfig = config.get(key);
2891
3071
  return {
2892
3072
  ...column,
2893
- hidden: visibility.has(key) ? visibility.get(key) === false : column.hidden,
3073
+ hidden: visibility.has(key) ? visibility.get(key) === false : column.hidden ?? column.initialHide,
2894
3074
  width: managedConfig?.width ?? column.width,
2895
3075
  minWidth: column.minWidth,
2896
3076
  maxWidth: column.maxWidth,
@@ -2905,6 +3085,24 @@ function applyColumnManagerState(columns, visibility, orders, config, parentKey
2905
3085
  };
2906
3086
  });
2907
3087
  }
3088
+ function applyManagedColumnOrder(columns, orderedKeys) {
3089
+ const managedKeySet = new Set(orderedKeys);
3090
+ const managedSlots = columns.map(
3091
+ (column, index) => managedKeySet.has(resolveColumnKey(column)) ? index : -1
3092
+ ).filter((index) => index >= 0);
3093
+ const columnByKey = new Map(
3094
+ columns.map((column) => [resolveColumnKey(column), column])
3095
+ );
3096
+ const next = [...columns];
3097
+ orderedKeys.forEach((key, index) => {
3098
+ const slot = managedSlots[index];
3099
+ const column = columnByKey.get(key);
3100
+ if (slot != null && column) {
3101
+ next[slot] = column;
3102
+ }
3103
+ });
3104
+ return next;
3105
+ }
2908
3106
  function resolveColumnKey(column) {
2909
3107
  return String(column.key ?? column.dataIndex);
2910
3108
  }