@lensui/lens-table 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -111,7 +111,7 @@ export function Example() {
111
111
  | `defaultSelectedCell` | `GridSelectionTarget \| null` | `null` | 默认选中单元格。传 `columnKey`,行可使用 `rowKey` 或 `rowIndex` 定位。 |
112
112
  | `onSelectedCellChange` | `(selection) => void` | - | 单元格选中变化回调,`selection.value` 为当前单元格的原始值。 |
113
113
  | `rangeSelection` | `boolean` | `false` | 是否允许鼠标拖动选择多个单元格。开启后支持范围复制、范围右键菜单和右下角拖拽扩展范围。 |
114
- | `rowSelection` | `boolean \| RowSelectionConfig` | `false` | 开启行选择。支持 `mode`、`showCheckbox`、`indicator: 'checkbox' \| 'arrow'` 和 `columnWidth`;箭头样式未选中时为空白。默认自动生成左侧选择列。 |
114
+ | `rowSelection` | `boolean \| RowSelectionConfig` | `false` | 开启行选择。支持 `mode`、`showCheckbox`、`indicator: 'checkbox' \| 'arrow' \| 'none'` 和 `columnWidth`;`none` 保留点击区域但不绘制标记。默认自动生成左侧选择列。 |
115
115
  | `selectedRowKeys` | `GridKey[]` | 非受控 | 受控行选择 key 列表。 |
116
116
  | `defaultSelectedRowKeys` | `GridKey[]` | `[]` | 非受控模式下默认选中的行 key。 |
117
117
  | `onSelectedRowChange` | `(keys, rows, indices) => void` | - | 行选择变化回调。 |
package/dist/index.cjs CHANGED
@@ -1115,7 +1115,8 @@ function paintGrid(options) {
1115
1115
  const checked = selectedRowKeys.has(rowKey);
1116
1116
  ctx.save();
1117
1117
  ctx.lineWidth = 1;
1118
- if (column.rowSelectionIndicator === "arrow") {
1118
+ if (column.rowSelectionIndicator === "none") {
1119
+ } else if (column.rowSelectionIndicator === "arrow") {
1119
1120
  if (checked) {
1120
1121
  ctx.beginPath();
1121
1122
  ctx.moveTo(iconLeft + 3.5, iconTop + 8);
@@ -1201,9 +1202,25 @@ function paintGrid(options) {
1201
1202
  paintBodyColumns("scroll");
1202
1203
  paintBodyColumns("left");
1203
1204
  paintBodyColumns("right");
1204
- if (extendVerticalGridLines && !verticalBorderless) {
1205
+ if (extendVerticalGridLines) {
1205
1206
  const extensionTop = Math.max(bodyTop, Math.min(height, bodyTop + rows.length * rowHeight - scrollTop));
1206
1207
  const extensionHeight = Math.max(0, height - extensionTop);
1208
+ const paintExtendedColumnSelection = (layer) => {
1209
+ ctx.save();
1210
+ if (layer === "scroll") {
1211
+ ctx.beginPath();
1212
+ ctx.rect(leftFixedWidth, extensionTop, Math.max(0, rightFixedLeft - leftFixedWidth), extensionHeight);
1213
+ ctx.clip();
1214
+ }
1215
+ ctx.fillStyle = colors.axisSelectionFill;
1216
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
1217
+ if (!selectedColumnKeys.has(columns[columnIndex].key)) continue;
1218
+ if (layer === "scroll" ? columns[columnIndex].fixed !== void 0 : columns[columnIndex].fixed !== layer) continue;
1219
+ if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
1220
+ ctx.fillRect(getColumnX(columnIndex), extensionTop, metrics[columnIndex].width, extensionHeight);
1221
+ }
1222
+ ctx.restore();
1223
+ };
1207
1224
  const paintExtendedColumnLines = (layer) => {
1208
1225
  ctx.save();
1209
1226
  if (layer === "scroll") {
@@ -1221,9 +1238,14 @@ function paintGrid(options) {
1221
1238
  }
1222
1239
  ctx.restore();
1223
1240
  };
1224
- paintExtendedColumnLines("scroll");
1225
- paintExtendedColumnLines("left");
1226
- paintExtendedColumnLines("right");
1241
+ paintExtendedColumnSelection("scroll");
1242
+ paintExtendedColumnSelection("left");
1243
+ paintExtendedColumnSelection("right");
1244
+ if (!verticalBorderless) {
1245
+ paintExtendedColumnLines("scroll");
1246
+ paintExtendedColumnLines("left");
1247
+ paintExtendedColumnLines("right");
1248
+ }
1227
1249
  }
1228
1250
  const headerY = fixedHeader ? 0 : -scrollTop;
1229
1251
  ctx.fillStyle = colors.header;
@@ -1239,8 +1261,9 @@ function paintGrid(options) {
1239
1261
  ctx.fillStyle = colors.header;
1240
1262
  ctx.fillRect(x, headerY, metric.width, headerHeight);
1241
1263
  }
1242
- if (selectedColumnKeys.has(columns[columnIndex].key)) {
1243
- ctx.fillStyle = colors.selectionFill;
1264
+ const isAxisSelected = selectedColumnKeys.has(columns[columnIndex].key);
1265
+ if (isAxisSelected) {
1266
+ ctx.fillStyle = colors.axisSelectionFill;
1244
1267
  ctx.fillRect(x, headerY, metric.width, headerHeight);
1245
1268
  }
1246
1269
  if (columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex) {
@@ -1272,7 +1295,7 @@ function paintGrid(options) {
1272
1295
  ctx.beginPath();
1273
1296
  ctx.rect(x + 2, headerY + headerLeafTop + 1, Math.max(0, clipWidth - 4), headerLeafHeight - 2);
1274
1297
  ctx.clip();
1275
- ctx.fillStyle = colors.muted;
1298
+ ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : colors.muted;
1276
1299
  ctx.textAlign = titleAlign === "right" ? "right" : titleAlign === "center" ? "center" : "left";
1277
1300
  ctx.fillText(title, textX, headerY + headerLeafTop + headerLeafHeight / 2);
1278
1301
  ctx.restore();
@@ -3378,6 +3401,9 @@ function TableInner({
3378
3401
  }, [setSelection]);
3379
3402
  const selectRow = (0, import_react5.useCallback)((rowIndex, event, forceToggle = false) => {
3380
3403
  if (!rowSelection) return;
3404
+ clickedCellRef.current = null;
3405
+ setSelectionRange(null);
3406
+ setSelection(null);
3381
3407
  const mode = typeof rowSelection === "object" ? rowSelection.mode ?? "multiple" : "multiple";
3382
3408
  const key = getRowKey(rows[rowIndex], rowIndex);
3383
3409
  let next;
@@ -3392,9 +3418,12 @@ function TableInner({
3392
3418
  }
3393
3419
  rowAnchorRef.current = rowIndex;
3394
3420
  setRowKeys(next);
3395
- }, [getRowKey, rowKeys, rowSelection, rows, selectedRowKeySet, setRowKeys]);
3421
+ }, [getRowKey, rowKeys, rowSelection, rows, selectedRowKeySet, setRowKeys, setSelection]);
3396
3422
  const selectColumn = (0, import_react5.useCallback)((columnIndex, event) => {
3397
3423
  if (!columnSelection || columnIndex < 0) return;
3424
+ clickedCellRef.current = null;
3425
+ setSelectionRange(null);
3426
+ setSelection(null);
3398
3427
  const mode = typeof columnSelection === "object" ? columnSelection.mode ?? "multiple" : "multiple";
3399
3428
  const key = columns[columnIndex].key;
3400
3429
  let next;
@@ -3402,23 +3431,26 @@ function TableInner({
3402
3431
  const start = Math.min(columnAnchorRef.current, columnIndex);
3403
3432
  const end = Math.max(columnAnchorRef.current, columnIndex);
3404
3433
  next = columns.slice(start, end + 1).map((column) => column.key);
3405
- } else if (mode === "multiple") {
3434
+ } else if (mode === "multiple" && (event.ctrlKey || event.metaKey)) {
3406
3435
  next = selectedColumnKeySet.has(key) ? columnKeys.filter((item) => item !== key) : [...columnKeys, key];
3407
3436
  } else {
3408
3437
  next = columnKeys.length === 1 && selectedColumnKeySet.has(key) ? [] : [key];
3409
3438
  }
3410
3439
  columnAnchorRef.current = columnIndex;
3411
3440
  setColumnKeys(next);
3412
- }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys]);
3441
+ }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
3413
3442
  const toggleColumnFromMenu = (0, import_react5.useCallback)((columnIndex) => {
3414
3443
  if (!columnSelection || columnIndex < 0) return;
3444
+ clickedCellRef.current = null;
3445
+ setSelectionRange(null);
3446
+ setSelection(null);
3415
3447
  const key = columns[columnIndex].key;
3416
3448
  const mode = typeof columnSelection === "object" ? columnSelection.mode ?? "multiple" : "multiple";
3417
3449
  const selected = selectedColumnKeySet.has(key);
3418
3450
  const next = selected ? columnKeys.filter((value) => value !== key) : mode === "multiple" ? [...columnKeys, key] : [key];
3419
3451
  columnAnchorRef.current = columnIndex;
3420
3452
  setColumnKeys(next);
3421
- }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys]);
3453
+ }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
3422
3454
  const revealCell = (0, import_react5.useCallback)((cell) => {
3423
3455
  const scroller = scrollerRef.current;
3424
3456
  const metric = metrics[cell.columnIndex];
@@ -3770,6 +3802,8 @@ function TableInner({
3770
3802
  const renderHeaderIcons = (columnIndex, left) => {
3771
3803
  const column = columns[columnIndex];
3772
3804
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
3805
+ const isAxisSelected = selectedColumnKeySet.has(column.key);
3806
+ const selectedClassName = isAxisSelected ? " is-axis-selected" : "";
3773
3807
  const top = headerLeafTop + (headerLeafHeight - headerActionSize) / 2;
3774
3808
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
3775
3809
  let right = left + metrics[columnIndex].width - (visibleActions.drag ? headerActionSlotWidth : 2);
@@ -3777,21 +3811,21 @@ function TableInner({
3777
3811
  if (visibleActions.drag) {
3778
3812
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "drag";
3779
3813
  icons.push(
3780
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
3814
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${selectedClassName}${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
3781
3815
  );
3782
3816
  }
3783
3817
  if (visibleActions.sort) {
3784
3818
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "sort";
3785
3819
  const direction = sortState?.columnKey === column.key ? sortState.direction : null;
3786
3820
  icons.push(
3787
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
3821
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSortIcon, { className: `rvg-header-icon${selectedClassName}${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
3788
3822
  );
3789
3823
  right -= headerActionSlotWidth;
3790
3824
  }
3791
3825
  if (visibleActions.filter) {
3792
3826
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "filter";
3793
3827
  icons.push(
3794
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
3828
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${selectedClassName}${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
3795
3829
  );
3796
3830
  }
3797
3831
  return icons;
@@ -4171,6 +4205,7 @@ function TableInner({
4171
4205
  };
4172
4206
  const renderHeaderTitle = (columnIndex, left) => {
4173
4207
  const column = columns[columnIndex];
4208
+ const isAxisSelected = selectedColumnKeySet.has(column.key);
4174
4209
  const isDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
4175
4210
  const currentScrollTop = scrollRef.current.top;
4176
4211
  const headerTop = fixedHeader ? 0 : -currentScrollTop;
@@ -4187,7 +4222,7 @@ function TableInner({
4187
4222
  );
4188
4223
  }
4189
4224
  if (column.rowSelection) {
4190
- if (rowSelectionMode === "single" || column.rowSelectionIndicator === "arrow") return null;
4225
+ if (rowSelectionMode === "single" || column.rowSelectionIndicator === "arrow" || column.rowSelectionIndicator === "none") return null;
4191
4226
  const allSelected = rows.length > 0 && selectedRowKeySet.size === rows.length;
4192
4227
  const indeterminate = selectedRowKeySet.size > 0 && !allSelected;
4193
4228
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -4206,7 +4241,7 @@ function TableInner({
4206
4241
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4207
4242
  "div",
4208
4243
  {
4209
- className: `rvg-header-title is-custom${isDropTarget ? " is-drop-target" : ""}`,
4244
+ className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4210
4245
  "data-level": headerDepth - 1,
4211
4246
  "data-measure-key": column.key,
4212
4247
  style: {
@@ -4249,10 +4284,11 @@ function TableInner({
4249
4284
  const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex), headerActionSlotWidth) : null;
4250
4285
  const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable && !cell.leaf ? headerActionSlotWidth : 0;
4251
4286
  const isDropTarget = Boolean(columnDropTarget && cell.endIndex >= columnDropTarget.startIndex && cell.startIndex <= columnDropTarget.endIndex);
4287
+ const isAxisSelected = cell.leaf && selectedColumnKeySet.has(column.key);
4252
4288
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4253
4289
  "div",
4254
4290
  {
4255
- className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4291
+ className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${isAxisSelected ? " is-axis-selected" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4256
4292
  "data-level": cell.level,
4257
4293
  "data-measure-key": `group:${cell.key}:${cell.level}`,
4258
4294
  style: {
@@ -4516,12 +4552,16 @@ function TableInner({
4516
4552
  getSelectedRows: () => rows.filter((row, index) => selectedRowKeySet.has(getRowKey(row, index))),
4517
4553
  setSelectedRowKeys: (keys) => {
4518
4554
  if (!rowSelection) return;
4555
+ setSelectionRange(null);
4556
+ setSelection(null);
4519
4557
  const next = [...new Set(keys)];
4520
4558
  setRowKeys(rowSelectionMode === "single" ? next.slice(0, 1) : next);
4521
4559
  },
4522
4560
  getSelectedColumnKeys: () => [...columnKeys],
4523
4561
  setSelectedColumnKeys: (keys) => {
4524
4562
  if (!columnSelection) return;
4563
+ setSelectionRange(null);
4564
+ setSelection(null);
4525
4565
  const next = [...new Set(keys)].filter((key) => columns.some((column) => column.key === key && !column.rowNumber && !column.rowSelection && !column.rowDragHandle));
4526
4566
  setColumnKeys(typeof columnSelection === "object" && columnSelection.mode === "single" ? next.slice(0, 1) : next);
4527
4567
  },
@@ -4724,7 +4764,9 @@ function TableInner({
4724
4764
  }
4725
4765
  if (locateHeaderDragHandle(event.clientX, columnIndex)) return;
4726
4766
  if (columnIndex >= 0 && columns[columnIndex].rowSelection && rowSelection) {
4727
- if (columns[columnIndex].rowSelectionIndicator === "arrow") return;
4767
+ if (columns[columnIndex].rowSelectionIndicator === "arrow" || columns[columnIndex].rowSelectionIndicator === "none") return;
4768
+ setSelectionRange(null);
4769
+ setSelection(null);
4728
4770
  setRowKeys(rowKeys.length === rows.length ? [] : rows.map(getRowKey));
4729
4771
  } else if (columnIndex >= 0 && (columns[columnIndex].rowDragHandle || columns[columnIndex].rowNumber)) {
4730
4772
  return;
@@ -4743,7 +4785,7 @@ function TableInner({
4743
4785
  const clickedRowSelector = Boolean(columns[cell.columnIndex].rowSelection);
4744
4786
  if (clickedRowSelector) {
4745
4787
  clickedCellRef.current = null;
4746
- selectRow(cell.rowIndex, event, columns[cell.columnIndex].rowSelectionIndicator !== "arrow");
4788
+ selectRow(cell.rowIndex, event, !["arrow", "none"].includes(columns[cell.columnIndex].rowSelectionIndicator ?? "checkbox"));
4747
4789
  return;
4748
4790
  }
4749
4791
  if (event.detail > 1) return;
@@ -5042,6 +5084,8 @@ function TableInner({
5042
5084
  if (item === "select-row") {
5043
5085
  if (!rowSelection) return null;
5044
5086
  return renderContextMenuButton("cell-select-row", cellContext, selectedRowKeySet.has(cell.rowKey) ? labels.deselectRow : labels.selectRow, () => {
5087
+ setSelectionRange(null);
5088
+ setSelection(null);
5045
5089
  if (selectedRowKeySet.has(cell.rowKey)) setRowKeys(rowKeys.filter((key) => key !== cell.rowKey));
5046
5090
  else setRowKeys(rowSelectionMode === "single" ? [cell.rowKey] : [...rowKeys, cell.rowKey]);
5047
5091
  }, override, { icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContextMenuIcon, { type: "select-row" }) });
package/dist/index.css CHANGED
@@ -773,6 +773,10 @@
773
773
  .rvg-header-title.is-drop-target {
774
774
  background: var(--rvg-color-column-drop-target-fill);
775
775
  }
776
+ .rvg-header-title.is-axis-selected {
777
+ background: var(--rvg-color-axis-selection-fill);
778
+ color: var(--rvg-color-axis-selection-text);
779
+ }
776
780
  .rvg-text-fixed-shadow {
777
781
  position: absolute;
778
782
  z-index: 4;
@@ -854,6 +858,11 @@
854
858
  .rvg-header-icon.is-hovered {
855
859
  color: var(--rvg-color-muted);
856
860
  }
861
+ .rvg-header-icon.is-axis-selected,
862
+ .rvg-header-icon.is-axis-selected.is-hovered,
863
+ .rvg-header-icon.is-axis-selected.is-active {
864
+ color: var(--rvg-color-axis-selection-text);
865
+ }
857
866
  .rvg-root.is-initial-loading .rvg-header-icon {
858
867
  color: #d6dbe0;
859
868
  animation: rvg-loading-icon-pulse 1.15s ease-in-out infinite alternate;
package/dist/index.d.cts CHANGED
@@ -160,7 +160,7 @@ interface RowSelectionConfig extends AxisSelectionConfig {
160
160
  /** Show the selection column. Defaults to true; when false, click body cells to select rows. */
161
161
  showCheckbox?: boolean;
162
162
  /** Selection marker style. Arrow stays blank until selected. Defaults to checkbox. */
163
- indicator?: 'checkbox' | 'arrow';
163
+ indicator?: 'checkbox' | 'arrow' | 'none';
164
164
  /** Width of the generated selection column. Defaults to 44. */
165
165
  columnWidth?: number;
166
166
  }
package/dist/index.d.ts CHANGED
@@ -160,7 +160,7 @@ interface RowSelectionConfig extends AxisSelectionConfig {
160
160
  /** Show the selection column. Defaults to true; when false, click body cells to select rows. */
161
161
  showCheckbox?: boolean;
162
162
  /** Selection marker style. Arrow stays blank until selected. Defaults to checkbox. */
163
- indicator?: 'checkbox' | 'arrow';
163
+ indicator?: 'checkbox' | 'arrow' | 'none';
164
164
  /** Width of the generated selection column. Defaults to 44. */
165
165
  columnWidth?: number;
166
166
  }
package/dist/index.js CHANGED
@@ -1085,7 +1085,8 @@ function paintGrid(options) {
1085
1085
  const checked = selectedRowKeys.has(rowKey);
1086
1086
  ctx.save();
1087
1087
  ctx.lineWidth = 1;
1088
- if (column.rowSelectionIndicator === "arrow") {
1088
+ if (column.rowSelectionIndicator === "none") {
1089
+ } else if (column.rowSelectionIndicator === "arrow") {
1089
1090
  if (checked) {
1090
1091
  ctx.beginPath();
1091
1092
  ctx.moveTo(iconLeft + 3.5, iconTop + 8);
@@ -1171,9 +1172,25 @@ function paintGrid(options) {
1171
1172
  paintBodyColumns("scroll");
1172
1173
  paintBodyColumns("left");
1173
1174
  paintBodyColumns("right");
1174
- if (extendVerticalGridLines && !verticalBorderless) {
1175
+ if (extendVerticalGridLines) {
1175
1176
  const extensionTop = Math.max(bodyTop, Math.min(height, bodyTop + rows.length * rowHeight - scrollTop));
1176
1177
  const extensionHeight = Math.max(0, height - extensionTop);
1178
+ const paintExtendedColumnSelection = (layer) => {
1179
+ ctx.save();
1180
+ if (layer === "scroll") {
1181
+ ctx.beginPath();
1182
+ ctx.rect(leftFixedWidth, extensionTop, Math.max(0, rightFixedLeft - leftFixedWidth), extensionHeight);
1183
+ ctx.clip();
1184
+ }
1185
+ ctx.fillStyle = colors.axisSelectionFill;
1186
+ for (let columnIndex = 0; columnIndex < columns.length; columnIndex += 1) {
1187
+ if (!selectedColumnKeys.has(columns[columnIndex].key)) continue;
1188
+ if (layer === "scroll" ? columns[columnIndex].fixed !== void 0 : columns[columnIndex].fixed !== layer) continue;
1189
+ if (layer === "scroll" && (columnIndex < range.columnStart || columnIndex >= range.columnEnd)) continue;
1190
+ ctx.fillRect(getColumnX(columnIndex), extensionTop, metrics[columnIndex].width, extensionHeight);
1191
+ }
1192
+ ctx.restore();
1193
+ };
1177
1194
  const paintExtendedColumnLines = (layer) => {
1178
1195
  ctx.save();
1179
1196
  if (layer === "scroll") {
@@ -1191,9 +1208,14 @@ function paintGrid(options) {
1191
1208
  }
1192
1209
  ctx.restore();
1193
1210
  };
1194
- paintExtendedColumnLines("scroll");
1195
- paintExtendedColumnLines("left");
1196
- paintExtendedColumnLines("right");
1211
+ paintExtendedColumnSelection("scroll");
1212
+ paintExtendedColumnSelection("left");
1213
+ paintExtendedColumnSelection("right");
1214
+ if (!verticalBorderless) {
1215
+ paintExtendedColumnLines("scroll");
1216
+ paintExtendedColumnLines("left");
1217
+ paintExtendedColumnLines("right");
1218
+ }
1197
1219
  }
1198
1220
  const headerY = fixedHeader ? 0 : -scrollTop;
1199
1221
  ctx.fillStyle = colors.header;
@@ -1209,8 +1231,9 @@ function paintGrid(options) {
1209
1231
  ctx.fillStyle = colors.header;
1210
1232
  ctx.fillRect(x, headerY, metric.width, headerHeight);
1211
1233
  }
1212
- if (selectedColumnKeys.has(columns[columnIndex].key)) {
1213
- ctx.fillStyle = colors.selectionFill;
1234
+ const isAxisSelected = selectedColumnKeys.has(columns[columnIndex].key);
1235
+ if (isAxisSelected) {
1236
+ ctx.fillStyle = colors.axisSelectionFill;
1214
1237
  ctx.fillRect(x, headerY, metric.width, headerHeight);
1215
1238
  }
1216
1239
  if (columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex) {
@@ -1242,7 +1265,7 @@ function paintGrid(options) {
1242
1265
  ctx.beginPath();
1243
1266
  ctx.rect(x + 2, headerY + headerLeafTop + 1, Math.max(0, clipWidth - 4), headerLeafHeight - 2);
1244
1267
  ctx.clip();
1245
- ctx.fillStyle = colors.muted;
1268
+ ctx.fillStyle = isAxisSelected ? colors.axisSelectionText : colors.muted;
1246
1269
  ctx.textAlign = titleAlign === "right" ? "right" : titleAlign === "center" ? "center" : "left";
1247
1270
  ctx.fillText(title, textX, headerY + headerLeafTop + headerLeafHeight / 2);
1248
1271
  ctx.restore();
@@ -3348,6 +3371,9 @@ function TableInner({
3348
3371
  }, [setSelection]);
3349
3372
  const selectRow = useCallback2((rowIndex, event, forceToggle = false) => {
3350
3373
  if (!rowSelection) return;
3374
+ clickedCellRef.current = null;
3375
+ setSelectionRange(null);
3376
+ setSelection(null);
3351
3377
  const mode = typeof rowSelection === "object" ? rowSelection.mode ?? "multiple" : "multiple";
3352
3378
  const key = getRowKey(rows[rowIndex], rowIndex);
3353
3379
  let next;
@@ -3362,9 +3388,12 @@ function TableInner({
3362
3388
  }
3363
3389
  rowAnchorRef.current = rowIndex;
3364
3390
  setRowKeys(next);
3365
- }, [getRowKey, rowKeys, rowSelection, rows, selectedRowKeySet, setRowKeys]);
3391
+ }, [getRowKey, rowKeys, rowSelection, rows, selectedRowKeySet, setRowKeys, setSelection]);
3366
3392
  const selectColumn = useCallback2((columnIndex, event) => {
3367
3393
  if (!columnSelection || columnIndex < 0) return;
3394
+ clickedCellRef.current = null;
3395
+ setSelectionRange(null);
3396
+ setSelection(null);
3368
3397
  const mode = typeof columnSelection === "object" ? columnSelection.mode ?? "multiple" : "multiple";
3369
3398
  const key = columns[columnIndex].key;
3370
3399
  let next;
@@ -3372,23 +3401,26 @@ function TableInner({
3372
3401
  const start = Math.min(columnAnchorRef.current, columnIndex);
3373
3402
  const end = Math.max(columnAnchorRef.current, columnIndex);
3374
3403
  next = columns.slice(start, end + 1).map((column) => column.key);
3375
- } else if (mode === "multiple") {
3404
+ } else if (mode === "multiple" && (event.ctrlKey || event.metaKey)) {
3376
3405
  next = selectedColumnKeySet.has(key) ? columnKeys.filter((item) => item !== key) : [...columnKeys, key];
3377
3406
  } else {
3378
3407
  next = columnKeys.length === 1 && selectedColumnKeySet.has(key) ? [] : [key];
3379
3408
  }
3380
3409
  columnAnchorRef.current = columnIndex;
3381
3410
  setColumnKeys(next);
3382
- }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys]);
3411
+ }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
3383
3412
  const toggleColumnFromMenu = useCallback2((columnIndex) => {
3384
3413
  if (!columnSelection || columnIndex < 0) return;
3414
+ clickedCellRef.current = null;
3415
+ setSelectionRange(null);
3416
+ setSelection(null);
3385
3417
  const key = columns[columnIndex].key;
3386
3418
  const mode = typeof columnSelection === "object" ? columnSelection.mode ?? "multiple" : "multiple";
3387
3419
  const selected = selectedColumnKeySet.has(key);
3388
3420
  const next = selected ? columnKeys.filter((value) => value !== key) : mode === "multiple" ? [...columnKeys, key] : [key];
3389
3421
  columnAnchorRef.current = columnIndex;
3390
3422
  setColumnKeys(next);
3391
- }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys]);
3423
+ }, [columnKeys, columnSelection, columns, selectedColumnKeySet, setColumnKeys, setSelection]);
3392
3424
  const revealCell = useCallback2((cell) => {
3393
3425
  const scroller = scrollerRef.current;
3394
3426
  const metric = metrics[cell.columnIndex];
@@ -3740,6 +3772,8 @@ function TableInner({
3740
3772
  const renderHeaderIcons = (columnIndex, left) => {
3741
3773
  const column = columns[columnIndex];
3742
3774
  if (column.rowSelection || column.rowDragHandle || column.rowNumber) return null;
3775
+ const isAxisSelected = selectedColumnKeySet.has(column.key);
3776
+ const selectedClassName = isAxisSelected ? " is-axis-selected" : "";
3743
3777
  const top = headerLeafTop + (headerLeafHeight - headerActionSize) / 2;
3744
3778
  const visibleActions = getVisibleHeaderActions(column, metrics[columnIndex].width, columnDraggable, measureHeaderTitleWidth(columnIndex), headerActionSlotWidth);
3745
3779
  let right = left + metrics[columnIndex].width - (visibleActions.drag ? headerActionSlotWidth : 2);
@@ -3747,21 +3781,21 @@ function TableInner({
3747
3781
  if (visibleActions.drag) {
3748
3782
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "drag";
3749
3783
  icons.push(
3750
- /* @__PURE__ */ jsx7(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
3784
+ /* @__PURE__ */ jsx7(HeaderDragIcon, { className: `rvg-header-icon rvg-header-drag-icon${selectedClassName}${hovered ? " is-hovered" : ""}`, style: { left: left + metrics[columnIndex].width - headerActionSlotWidth, top } }, "drag")
3751
3785
  );
3752
3786
  }
3753
3787
  if (visibleActions.sort) {
3754
3788
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "sort";
3755
3789
  const direction = sortState?.columnKey === column.key ? sortState.direction : null;
3756
3790
  icons.push(
3757
- /* @__PURE__ */ jsx7(HeaderSortIcon, { className: `rvg-header-icon${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
3791
+ /* @__PURE__ */ jsx7(HeaderSortIcon, { className: `rvg-header-icon${selectedClassName}${hovered ? " is-hovered" : ""}`, style: { left: right - headerActionSlotWidth, top }, direction }, "sort")
3758
3792
  );
3759
3793
  right -= headerActionSlotWidth;
3760
3794
  }
3761
3795
  if (visibleActions.filter) {
3762
3796
  const hovered = hoveredHeaderAction?.columnIndex === columnIndex && hoveredHeaderAction.action === "filter";
3763
3797
  icons.push(
3764
- /* @__PURE__ */ jsx7(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
3798
+ /* @__PURE__ */ jsx7(HeaderSearchIcon, { className: `rvg-header-icon rvg-header-search-icon${selectedClassName}${hovered ? " is-hovered" : ""}${filterValues[column.key] ? " is-active" : ""}`, style: { left: right - headerActionSlotWidth, top: top + 1 } }, "filter")
3765
3799
  );
3766
3800
  }
3767
3801
  return icons;
@@ -4141,6 +4175,7 @@ function TableInner({
4141
4175
  };
4142
4176
  const renderHeaderTitle = (columnIndex, left) => {
4143
4177
  const column = columns[columnIndex];
4178
+ const isAxisSelected = selectedColumnKeySet.has(column.key);
4144
4179
  const isDropTarget = Boolean(columnDropTarget && columnIndex >= columnDropTarget.startIndex && columnIndex <= columnDropTarget.endIndex);
4145
4180
  const currentScrollTop = scrollRef.current.top;
4146
4181
  const headerTop = fixedHeader ? 0 : -currentScrollTop;
@@ -4157,7 +4192,7 @@ function TableInner({
4157
4192
  );
4158
4193
  }
4159
4194
  if (column.rowSelection) {
4160
- if (rowSelectionMode === "single" || column.rowSelectionIndicator === "arrow") return null;
4195
+ if (rowSelectionMode === "single" || column.rowSelectionIndicator === "arrow" || column.rowSelectionIndicator === "none") return null;
4161
4196
  const allSelected = rows.length > 0 && selectedRowKeySet.size === rows.length;
4162
4197
  const indeterminate = selectedRowKeySet.size > 0 && !allSelected;
4163
4198
  return /* @__PURE__ */ jsx7(
@@ -4176,7 +4211,7 @@ function TableInner({
4176
4211
  return /* @__PURE__ */ jsx7(
4177
4212
  "div",
4178
4213
  {
4179
- className: `rvg-header-title is-custom${isDropTarget ? " is-drop-target" : ""}`,
4214
+ className: `rvg-header-title is-custom${isAxisSelected ? " is-axis-selected" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4180
4215
  "data-level": headerDepth - 1,
4181
4216
  "data-measure-key": column.key,
4182
4217
  style: {
@@ -4219,10 +4254,11 @@ function TableInner({
4219
4254
  const visibleActions = cell.leaf ? getVisibleHeaderActions(column, startMetric.width, columnDraggable, measureHeaderTitleWidth(cell.startIndex), headerActionSlotWidth) : null;
4220
4255
  const actionWidth = visibleActions ? (Number(visibleActions.drag) + Number(visibleActions.filter) + Number(visibleActions.sort)) * headerActionSlotWidth : columnDraggable && !cell.leaf ? headerActionSlotWidth : 0;
4221
4256
  const isDropTarget = Boolean(columnDropTarget && cell.endIndex >= columnDropTarget.startIndex && cell.startIndex <= columnDropTarget.endIndex);
4257
+ const isAxisSelected = cell.leaf && selectedColumnKeySet.has(column.key);
4222
4258
  return /* @__PURE__ */ jsxs7(
4223
4259
  "div",
4224
4260
  {
4225
- className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4261
+ className: `rvg-header-title rvg-header-group${column.renderHeader ? " is-custom" : ""}${cell.leaf ? " is-leaf" : ""}${isAxisSelected ? " is-axis-selected" : ""}${cell.endIndex === columns.length - 1 ? " is-frame-right" : ""}${isDropTarget ? " is-drop-target" : ""}`,
4226
4262
  "data-level": cell.level,
4227
4263
  "data-measure-key": `group:${cell.key}:${cell.level}`,
4228
4264
  style: {
@@ -4486,12 +4522,16 @@ function TableInner({
4486
4522
  getSelectedRows: () => rows.filter((row, index) => selectedRowKeySet.has(getRowKey(row, index))),
4487
4523
  setSelectedRowKeys: (keys) => {
4488
4524
  if (!rowSelection) return;
4525
+ setSelectionRange(null);
4526
+ setSelection(null);
4489
4527
  const next = [...new Set(keys)];
4490
4528
  setRowKeys(rowSelectionMode === "single" ? next.slice(0, 1) : next);
4491
4529
  },
4492
4530
  getSelectedColumnKeys: () => [...columnKeys],
4493
4531
  setSelectedColumnKeys: (keys) => {
4494
4532
  if (!columnSelection) return;
4533
+ setSelectionRange(null);
4534
+ setSelection(null);
4495
4535
  const next = [...new Set(keys)].filter((key) => columns.some((column) => column.key === key && !column.rowNumber && !column.rowSelection && !column.rowDragHandle));
4496
4536
  setColumnKeys(typeof columnSelection === "object" && columnSelection.mode === "single" ? next.slice(0, 1) : next);
4497
4537
  },
@@ -4694,7 +4734,9 @@ function TableInner({
4694
4734
  }
4695
4735
  if (locateHeaderDragHandle(event.clientX, columnIndex)) return;
4696
4736
  if (columnIndex >= 0 && columns[columnIndex].rowSelection && rowSelection) {
4697
- if (columns[columnIndex].rowSelectionIndicator === "arrow") return;
4737
+ if (columns[columnIndex].rowSelectionIndicator === "arrow" || columns[columnIndex].rowSelectionIndicator === "none") return;
4738
+ setSelectionRange(null);
4739
+ setSelection(null);
4698
4740
  setRowKeys(rowKeys.length === rows.length ? [] : rows.map(getRowKey));
4699
4741
  } else if (columnIndex >= 0 && (columns[columnIndex].rowDragHandle || columns[columnIndex].rowNumber)) {
4700
4742
  return;
@@ -4713,7 +4755,7 @@ function TableInner({
4713
4755
  const clickedRowSelector = Boolean(columns[cell.columnIndex].rowSelection);
4714
4756
  if (clickedRowSelector) {
4715
4757
  clickedCellRef.current = null;
4716
- selectRow(cell.rowIndex, event, columns[cell.columnIndex].rowSelectionIndicator !== "arrow");
4758
+ selectRow(cell.rowIndex, event, !["arrow", "none"].includes(columns[cell.columnIndex].rowSelectionIndicator ?? "checkbox"));
4717
4759
  return;
4718
4760
  }
4719
4761
  if (event.detail > 1) return;
@@ -5012,6 +5054,8 @@ function TableInner({
5012
5054
  if (item === "select-row") {
5013
5055
  if (!rowSelection) return null;
5014
5056
  return renderContextMenuButton("cell-select-row", cellContext, selectedRowKeySet.has(cell.rowKey) ? labels.deselectRow : labels.selectRow, () => {
5057
+ setSelectionRange(null);
5058
+ setSelection(null);
5015
5059
  if (selectedRowKeySet.has(cell.rowKey)) setRowKeys(rowKeys.filter((key) => key !== cell.rowKey));
5016
5060
  else setRowKeys(rowSelectionMode === "single" ? [cell.rowKey] : [...rowKeys, cell.rowKey]);
5017
5061
  }, override, { icon: /* @__PURE__ */ jsx7(ContextMenuIcon, { type: "select-row" }) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",