es-grid-template 1.9.96 → 1.9.98

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.
Files changed (44) hide show
  1. package/es/grid-component/hooks/rowFocus.d.ts +4 -3
  2. package/es/grid-component/hooks/rowFocus.js +65 -3
  3. package/es/grid-component/type.d.ts +1 -1
  4. package/es/group-component/body/TableBodyCell.d.ts +2 -0
  5. package/es/group-component/body/TableBodyCell.js +15 -30
  6. package/es/group-component/body/TableBodyCellEdit.js +21 -84
  7. package/es/group-component/body/TableBodyCellEmpty.d.ts +2 -0
  8. package/es/group-component/body/TableBodyCellEmpty.js +15 -30
  9. package/es/group-component/body/TableBodyRowGroupCell.d.ts +2 -0
  10. package/es/group-component/body/TableBodyRowGroupCell.js +15 -30
  11. package/es/group-component/hook/utils.d.ts +9 -9
  12. package/es/group-component/table/TableWrapper.js +1 -0
  13. package/es/table-component/body/TableBodyCell.js +15 -39
  14. package/es/table-component/body/TableBodyCellEdit.js +18 -69
  15. package/es/table-component/table/TableWrapper.js +1 -0
  16. package/es/table-virtuoso/body/TableBodyCell.d.ts +1 -0
  17. package/es/table-virtuoso/body/TableBodyCell.js +13 -30
  18. package/es/table-virtuoso/body/TableBodyCellRowGroup.d.ts +1 -0
  19. package/es/table-virtuoso/body/TableBodyCellRowGroup.js +13 -30
  20. package/es/table-virtuoso/body/TableBodyRow.d.ts +2 -1
  21. package/es/table-virtuoso/body/TableBodyRow.js +10 -3
  22. package/es/table-virtuoso/table/TableWrapper.js +7 -0
  23. package/lib/grid-component/hooks/rowFocus.d.ts +4 -3
  24. package/lib/grid-component/hooks/rowFocus.js +66 -3
  25. package/lib/grid-component/type.d.ts +1 -1
  26. package/lib/group-component/body/TableBodyCell.d.ts +2 -0
  27. package/lib/group-component/body/TableBodyCell.js +14 -29
  28. package/lib/group-component/body/TableBodyCellEdit.js +20 -83
  29. package/lib/group-component/body/TableBodyCellEmpty.d.ts +2 -0
  30. package/lib/group-component/body/TableBodyCellEmpty.js +14 -29
  31. package/lib/group-component/body/TableBodyRowGroupCell.d.ts +2 -0
  32. package/lib/group-component/body/TableBodyRowGroupCell.js +14 -29
  33. package/lib/group-component/table/TableWrapper.js +1 -0
  34. package/lib/table-component/body/TableBodyCell.js +14 -38
  35. package/lib/table-component/body/TableBodyCellEdit.js +17 -68
  36. package/lib/table-component/table/TableWrapper.js +1 -0
  37. package/lib/table-virtuoso/body/TableBodyCell.d.ts +1 -0
  38. package/lib/table-virtuoso/body/TableBodyCell.js +12 -29
  39. package/lib/table-virtuoso/body/TableBodyCellRowGroup.d.ts +1 -0
  40. package/lib/table-virtuoso/body/TableBodyCellRowGroup.js +12 -29
  41. package/lib/table-virtuoso/body/TableBodyRow.d.ts +2 -1
  42. package/lib/table-virtuoso/body/TableBodyRow.js +10 -3
  43. package/lib/table-virtuoso/table/TableWrapper.js +7 -0
  44. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
1
+ import { focusArrowRow, notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
2
2
  import Space from "rc-master-ui/es/space";
3
3
  import Command from "../components/command/Command";
4
4
  import { addRowsDown, addRowsDownWithCtrl, addRowsUp, addRowsUpWithCtrl, findFirst, flattenArray, flattenData, getColIdsBetween, getCommonPinningStyles, getDragRightData, getEditType, getFormat,
@@ -819,77 +819,26 @@ const TableBodyCellEdit = props => {
819
819
  }
820
820
  return;
821
821
  }
822
- if (e.key === 'ArrowDown') {
823
- // e.preventDefault()
824
- // e.stopPropagation()
825
-
826
- const nextRow = table.getRowModel().rows[rowNumber + 1];
827
- if (nextRow) {
828
- const nextRowId = nextRow.id;
829
- setFocusedCell?.({
830
- rowId: nextRowId,
831
- colId
832
- });
833
- notifyArrowRowFocus(table.getRow(nextRowId).original, 'arrowDown', selectionSettings?.useArrow, rowFocus);
834
- setStartCell?.({
835
- rowId: nextRowId,
836
- colId
837
- });
838
- setEndCell?.({
839
- rowId: nextRowId,
840
- colId
841
- });
842
- setRangeState?.(getSelectedCellMatrix(table, {
843
- rowId: nextRowId,
844
- colId
845
- }, {
846
- rowId: nextRowId,
847
- colId
848
- }));
849
-
850
- // columnVirtualizer.scrollToIndex(nextCol.getIndex(), { align: 'center' })
851
- // rowVirtualizer.scrollToIndex(nextRow.index, { align: 'center' })
852
-
853
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextRowId}"]`);
854
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
855
- if (cellFocus) {
856
- cellFocus.focus();
857
- }
858
- }
859
- return;
860
- }
861
- if (e.key === 'ArrowUp') {
862
- // e.preventDefault()
863
- // e.stopPropagation()
864
-
865
- const nextRow = table.getRowModel().rows[rowNumber - 1];
822
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
823
+ const rows = table.getRowModel().rows;
824
+ const currentIndex = rows.findIndex(row => row.id === rowId);
825
+ if (currentIndex < 0) return;
826
+ const step = e.key === 'ArrowDown' ? 1 : -1;
827
+ const nextIndex = currentIndex + step;
828
+ const nextRow = rows[nextIndex];
866
829
  if (nextRow) {
867
- const nextRowId = nextRow.id;
868
- setFocusedCell?.({
869
- rowId: nextRowId,
870
- colId
871
- });
872
- notifyArrowRowFocus(table.getRow(nextRowId).original, 'arrowUp', selectionSettings?.useArrow, rowFocus);
873
- setStartCell?.({
874
- rowId: nextRowId,
875
- colId
876
- });
877
- setEndCell?.({
878
- rowId: nextRowId,
879
- colId
880
- });
881
- setRangeState?.(getSelectedCellMatrix(table, {
882
- rowId: nextRowId,
883
- colId
884
- }, {
885
- rowId: nextRowId,
830
+ const nextCell = {
831
+ rowId: nextRow.id,
886
832
  colId
833
+ };
834
+ setFocusedCell?.(nextCell);
835
+ setStartCell?.(nextCell);
836
+ setEndCell?.(nextCell);
837
+ setRangeState?.(getSelectedCellMatrix(table, nextCell, nextCell));
838
+ focusArrowRow(e, nextRow.id, colId, () => rowVirtualizer.scrollToIndex(nextIndex, {
839
+ align: 'center'
887
840
  }));
888
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextRowId}"]`);
889
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
890
- if (cellFocus) {
891
- cellFocus.focus();
892
- }
841
+ notifyArrowRowFocus(e, nextRow.original, e.key === 'ArrowDown' ? 'arrowDown' : 'arrowUp', selectionSettings?.useArrow, rowFocus);
893
842
  }
894
843
  return;
895
844
  }
@@ -246,6 +246,7 @@ const TableWrapper = props => {
246
246
  }, /*#__PURE__*/React.createElement("div", {
247
247
  // id={id}
248
248
  ref: tableContainerRef,
249
+ "data-grid-scroll": true,
249
250
  style: {
250
251
  overflow: 'auto',
251
252
  //our scrollable table container
@@ -4,6 +4,7 @@ import type { CommandClick } from "../../grid-component/type";
4
4
  import type { VirtualItem } from "@tanstack/react-virtual";
5
5
  interface TableBodyCellProps<T> {
6
6
  table: Table<T>;
7
+ scrollToRow?: (index: number) => void;
7
8
  tableId: string;
8
9
  cell: Cell<T, unknown>;
9
10
  commandClick?: (args: CommandClick<T>) => void;
@@ -1,4 +1,4 @@
1
- import { notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
1
+ import { focusArrowRow, notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
2
2
  import Space from "rc-master-ui/es/space";
3
3
  import { getCommonPinningStyles, getFormat } from "../hook/utils";
4
4
  import Checkbox from "rc-master-ui/es/checkbox/Checkbox";
@@ -374,35 +374,18 @@ const TableBodyCell = props => {
374
374
  }
375
375
  },
376
376
  onKeyDown: e => {
377
- const flatRows = table.getRowModel().flatRows;
378
- if (e.key === 'ArrowDown' && rowNumber < flatRows.length - 1) {
379
- const nextIndex = cell.row.index + 1;
380
- // const nextIndex = rowNumber + 1
381
-
382
- const nextId = flatRows[nextIndex].id;
383
- setFocusedCell?.({
384
- colId: cell.column.id,
385
- rowId: nextId
386
- });
387
- notifyArrowRowFocus(table.getRow(nextId).original, 'arrowDown', selectionSettings?.useArrow, rowFocus);
388
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
389
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
390
- if (cellFocus) {
391
- cellFocus.focus();
392
- }
393
- }
394
- if (e.key === 'ArrowUp' && rowNumber > 0) {
395
- const prevIndex = cell.row.index - 1;
396
- const nextId = flatRows[prevIndex].id;
397
- setFocusedCell?.({
398
- colId: cell.column.id,
399
- rowId: nextId
400
- });
401
- notifyArrowRowFocus(table.getRow(nextId).original, 'arrowUp', selectionSettings?.useArrow, rowFocus);
402
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
403
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
404
- if (cellFocus) {
405
- cellFocus.focus();
377
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
378
+ const rows = table.getRowModel().rows;
379
+ const currentIndex = rows.findIndex(row => row.id === cell.row.id);
380
+ const nextIndex = currentIndex + (e.key === 'ArrowDown' ? 1 : -1);
381
+ const nextRow = currentIndex >= 0 ? rows[nextIndex] : undefined;
382
+ if (nextRow) {
383
+ setFocusedCell?.({
384
+ colId: cell.column.id,
385
+ rowId: nextRow.id
386
+ });
387
+ focusArrowRow(e, nextRow.id, cell.column.id, () => props.scrollToRow?.(nextIndex));
388
+ notifyArrowRowFocus(e, nextRow.original, e.key === 'ArrowDown' ? 'arrowDown' : 'arrowUp', selectionSettings?.useArrow, rowFocus);
406
389
  }
407
390
  }
408
391
  if (e.ctrlKey && e.code === 'Space' && cell.row.getCanSelect()) {
@@ -4,6 +4,7 @@ import type { CommandClick } from "../../grid-component/type";
4
4
  import type { VirtualItem } from "@tanstack/react-virtual";
5
5
  interface TableBodyCellProps<T> {
6
6
  table: Table<T>;
7
+ scrollToRow?: (index: number) => void;
7
8
  tableId: string;
8
9
  cell: Cell<T, unknown>;
9
10
  commandClick?: (args: CommandClick<T>) => void;
@@ -1,4 +1,4 @@
1
- import { notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
1
+ import { focusArrowRow, notifyArrowRowFocus } from "../../grid-component/hooks/rowFocus";
2
2
  import { getCommonPinningStyles } from "../hook/utils";
3
3
  import classNames from "classnames";
4
4
  import React from "react";
@@ -89,35 +89,18 @@ const TableBodyCellRowGroup = props => {
89
89
  }
90
90
  },
91
91
  onKeyDown: e => {
92
- const flatRows = table.getRowModel().flatRows;
93
- if (e.key === 'ArrowDown' && rowNumber < flatRows.length - 1) {
94
- const nextIndex = cell.row.index + 1;
95
- // const nextIndex = rowNumber + 1
96
-
97
- const nextId = flatRows[nextIndex].id;
98
- setFocusedCell?.({
99
- colId: cell.column.id,
100
- rowId: nextId
101
- });
102
- notifyArrowRowFocus(table.getRow(nextId).original, 'arrowDown', selectionSettings?.useArrow, rowFocus);
103
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
104
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
105
- if (cellFocus) {
106
- cellFocus.focus();
107
- }
108
- }
109
- if (e.key === 'ArrowUp' && rowNumber > 0) {
110
- const prevIndex = cell.row.index - 1;
111
- const nextId = flatRows[prevIndex].id;
112
- setFocusedCell?.({
113
- colId: cell.column.id,
114
- rowId: nextId
115
- });
116
- notifyArrowRowFocus(table.getRow(nextId).original, 'arrowUp', selectionSettings?.useArrow, rowFocus);
117
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
118
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
119
- if (cellFocus) {
120
- cellFocus.focus();
92
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
93
+ const rows = table.getRowModel().rows;
94
+ const currentIndex = rows.findIndex(row => row.id === cell.row.id);
95
+ const nextIndex = currentIndex + (e.key === 'ArrowDown' ? 1 : -1);
96
+ const nextRow = currentIndex >= 0 ? rows[nextIndex] : undefined;
97
+ if (nextRow) {
98
+ setFocusedCell?.({
99
+ colId: cell.column.id,
100
+ rowId: nextRow.id
101
+ });
102
+ focusArrowRow(e, nextRow.id, cell.column.id, () => props.scrollToRow?.(nextIndex));
103
+ notifyArrowRowFocus(e, nextRow.original, e.key === 'ArrowDown' ? 'arrowDown' : 'arrowUp', selectionSettings?.useArrow, rowFocus);
121
104
  }
122
105
  }
123
106
  if (e.ctrlKey && e.code === 'Space' && cell.row.getCanSelect()) {
@@ -4,10 +4,11 @@ import type { CommandClick } from "../../grid-component/type";
4
4
  interface TableBodyRowProps<T> {
5
5
  tableId: string;
6
6
  table: Table<T>;
7
+ scrollToRow?: (index: number) => void;
7
8
  row: Row<T>;
8
9
  commandClick?: (args: CommandClick<T>) => void;
9
10
  editAble?: boolean;
10
11
  [key: string]: any;
11
12
  }
12
- declare const TableBodyRow: <RecordType extends object>({ tableId, table, row, virtualRow, commandClick, contextMenuItems, onContextMenu, rowheight, editAble, isEditing, isRowEditable, ...rest }: TableBodyRowProps<RecordType>) => JSX.Element;
13
+ declare const TableBodyRow: <RecordType extends object>({ tableId, table, row, scrollToRow, virtualRow, commandClick, contextMenuItems, onContextMenu, rowheight, editAble, isEditing, isRowEditable, ...rest }: TableBodyRowProps<RecordType>) => JSX.Element;
13
14
  export default TableBodyRow;
@@ -14,6 +14,7 @@ const TableBodyRow = ({
14
14
  tableId,
15
15
  table,
16
16
  row,
17
+ scrollToRow,
17
18
  virtualRow,
18
19
  commandClick,
19
20
  contextMenuItems,
@@ -133,7 +134,9 @@ const TableBodyRow = ({
133
134
  rowData: row.original,
134
135
  value: cellValue
135
136
  }) : /*#__PURE__*/React.createElement(React.Fragment, null, headertext, headertext ? ': ' : '', " ", cellContent);
136
- return /*#__PURE__*/React.createElement(TableBodyCell, _extends({}, otherCellAttributes, {
137
+ return /*#__PURE__*/React.createElement(TableBodyCell, _extends({
138
+ scrollToRow: scrollToRow
139
+ }, otherCellAttributes, {
137
140
  table: table,
138
141
  tableId: tableId,
139
142
  key: cell.id,
@@ -166,7 +169,9 @@ const TableBodyRow = ({
166
169
  const childrenData = row.subRows.map(it => it.original);
167
170
  const sumValue = sumByField(childrenData, cell.column.id);
168
171
  const sumValueFormat = numericFormatter(sumValue.toString(), numericFormatProps);
169
- return /*#__PURE__*/React.createElement(TableBodyCellRowGroup, _extends({}, otherCellAttributes, {
172
+ return /*#__PURE__*/React.createElement(TableBodyCellRowGroup, _extends({
173
+ scrollToRow: scrollToRow
174
+ }, otherCellAttributes, {
170
175
  table: table,
171
176
  tableId: tableId,
172
177
  key: cell.id,
@@ -179,7 +184,9 @@ const TableBodyRow = ({
179
184
  sumValue: sumValueFormat
180
185
  }));
181
186
  }
182
- return /*#__PURE__*/React.createElement(TableBodyCell, _extends({}, otherCellAttributes, {
187
+ return /*#__PURE__*/React.createElement(TableBodyCell, _extends({
188
+ scrollToRow: scrollToRow
189
+ }, otherCellAttributes, {
183
190
  table: table,
184
191
  tableId: tableId,
185
192
  key: cell.id,
@@ -34,6 +34,11 @@ const TableWrapper = props => {
34
34
 
35
35
  // ref cho scroll container
36
36
  const scrollRef = useRef(null);
37
+ const virtuosoRef = useRef(null);
38
+ const scrollToRow = index => virtuosoRef.current?.scrollToIndex({
39
+ index,
40
+ align: 'center'
41
+ });
37
42
  const {
38
43
  rows
39
44
  } = table.getRowModel();
@@ -126,6 +131,7 @@ const TableWrapper = props => {
126
131
  position: "relative"
127
132
  }
128
133
  }, /*#__PURE__*/React.createElement(TableVirtuoso, _extends({
134
+ ref: virtuosoRef,
129
135
  data: table.getRowModel().rows,
130
136
  totalCount: rows.length
131
137
  }, onVisibleRowsChange ? {
@@ -190,6 +196,7 @@ const TableWrapper = props => {
190
196
  return /*#__PURE__*/React.createElement(TableBodyRow, _extends({
191
197
  tableId: id,
192
198
  row: row,
199
+ scrollToRow: scrollToRow,
193
200
  table: table,
194
201
  commandClick: commandClick,
195
202
  rowheight: editAble ? 37 : rowheight,
@@ -1,4 +1,4 @@
1
- import type { MouseEvent } from 'react';
1
+ import type { KeyboardEvent as ReactKeyboardEvent, MouseEvent } from 'react';
2
2
  import type { RowFocusEventArgs } from '../type';
3
3
  type RowFocus<T> = (args: RowFocusEventArgs<T>) => void;
4
4
  /** Capture clicks even when a cell handles the event itself. */
@@ -6,6 +6,7 @@ export declare function getRowFocusHandlers<T>(rowData: T, rowFocus?: RowFocus<T
6
6
  onClickCapture: (event: MouseEvent<HTMLElement>) => void;
7
7
  onContextMenuCapture: (event: MouseEvent<HTMLElement>) => void;
8
8
  };
9
- /** Notify arrow focus without changing the existing navigation or selection. */
10
- export declare function notifyArrowRowFocus<T>(rowData: T, method: 'arrowUp' | 'arrowDown', useArrow?: boolean, rowFocus?: RowFocus<T>): void;
9
+ /** Report the last focused row after the arrow key is released. */
10
+ export declare function notifyArrowRowFocus<T>(event: ReactKeyboardEvent, rowData: T, method: 'arrowUp' | 'arrowDown', useArrow?: boolean, rowFocus?: RowFocus<T>): void;
11
+ export declare function focusArrowRow(event: ReactKeyboardEvent, rowId: string, columnId: string, scrollToRow: () => void): void;
11
12
  export {};
@@ -3,8 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.focusArrowRow = focusArrowRow;
6
7
  exports.getRowFocusHandlers = getRowFocusHandlers;
7
8
  exports.notifyArrowRowFocus = notifyArrowRowFocus;
9
+ const gridViewportSelector = '[data-grid-scroll], [data-virtuoso-scroller]';
10
+ const pendingArrowFocus = new WeakMap();
11
+
8
12
  /** Capture clicks even when a cell handles the event itself. */
9
13
  function getRowFocusHandlers(rowData, rowFocus) {
10
14
  return {
@@ -23,10 +27,69 @@ function getRowFocusHandlers(rowData, rowFocus) {
23
27
  };
24
28
  }
25
29
 
26
- /** Notify arrow focus without changing the existing navigation or selection. */
27
- function notifyArrowRowFocus(rowData, method, useArrow, rowFocus) {
28
- if (useArrow === true) rowFocus?.({
30
+ /** Report the last focused row after the arrow key is released. */
31
+ function notifyArrowRowFocus(event, rowData, method, useArrow, rowFocus) {
32
+ if (useArrow !== true || !rowFocus) return;
33
+ const viewport = event.currentTarget.closest(gridViewportSelector);
34
+ const view = viewport?.ownerDocument.defaultView;
35
+ if (!viewport || !view) return;
36
+ const notify = () => rowFocus({
29
37
  rowData,
30
38
  method
31
39
  });
40
+ const pending = pendingArrowFocus.get(viewport);
41
+ if (pending) {
42
+ pending.key = event.key;
43
+ pending.notify = notify;
44
+ return;
45
+ }
46
+ const focus = {
47
+ key: event.key,
48
+ notify
49
+ };
50
+ pendingArrowFocus.set(viewport, focus);
51
+ const cancel = () => {
52
+ pendingArrowFocus.delete(viewport);
53
+ view.removeEventListener('keyup', release, true);
54
+ view.removeEventListener('blur', cancel);
55
+ view.removeEventListener('pointerdown', cancel, true);
56
+ };
57
+ const release = keyEvent => {
58
+ if (keyEvent.key !== focus.key) return;
59
+ cancel();
60
+ view.setTimeout(() => {
61
+ if (viewport.isConnected) focus.notify();
62
+ }, 0);
63
+ };
64
+
65
+ // A virtualized row can unmount before keyup reaches its original cell.
66
+ view.addEventListener('keyup', release, true);
67
+ view.addEventListener('blur', cancel);
68
+ view.addEventListener('pointerdown', cancel, true);
69
+ }
70
+ function focusArrowRow(event, rowId, columnId, scrollToRow) {
71
+ event.preventDefault();
72
+ const source = event.currentTarget;
73
+ const body = source.closest('.ui-rc-grid-row')?.parentElement;
74
+ const row = body && Array.from(body.children).find(child => child.getAttribute('data-row-key') === rowId);
75
+ const viewport = source.closest(gridViewportSelector);
76
+ const canScroll = viewport && viewport.scrollHeight > viewport.clientHeight;
77
+ if (!row) {
78
+ if (canScroll) scrollToRow();
79
+ return;
80
+ }
81
+ const cell = Array.from(row.querySelectorAll(':scope > [data-col-key]')).find(element => element.getAttribute('data-col-key') === columnId) ?? row.querySelector(':scope > .ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
82
+ cell?.focus({
83
+ preventScroll: true
84
+ });
85
+ if (canScroll) {
86
+ const header = body?.parentElement?.querySelector(':scope > .ui-rc-grid-thead');
87
+ const footer = body?.parentElement?.querySelector(':scope > .ui-rc-grid-tfoot');
88
+ const headerHeight = header?.getBoundingClientRect().height ?? 0;
89
+ const footerHeight = footer?.getBoundingClientRect().height ?? 0;
90
+ const viewportTop = viewport.getBoundingClientRect().top + viewport.clientTop;
91
+ const viewportCenter = viewportTop + (viewport.clientHeight + headerHeight - footerHeight) / 2;
92
+ const rowRect = row.getBoundingClientRect();
93
+ viewport.scrollTop += rowRect.top + rowRect.height / 2 - viewportCenter;
94
+ }
32
95
  }
@@ -791,7 +791,7 @@ export type IWrapSettings = {
791
791
  wrapMode?: IWrapMode;
792
792
  };
793
793
  export type SelectionSettings<T = AnyObject> = {
794
- /** Invoke rowFocus on ArrowUp/ArrowDown. Defaults to false. */
794
+ /** Invoke rowFocus for the final row after releasing ArrowUp or ArrowDown. Defaults to false. */
795
795
  useArrow?: boolean;
796
796
  mode?: 'checkbox' | 'radio';
797
797
  type?: 'single' | 'multiple';
@@ -1,8 +1,10 @@
1
1
  /// <reference types="react" />
2
+ import type { Virtualizer } from "@tanstack/react-virtual";
2
3
  import type { Cell, Table } from "@tanstack/react-table";
3
4
  import type { CommandClick } from "../../grid-component/type";
4
5
  interface TableBodyCellProps<T> {
5
6
  table: Table<T>;
7
+ rowVirtualizer?: Virtualizer<HTMLDivElement, HTMLDivElement>;
6
8
  tableId: string;
7
9
  cell: Cell<T, unknown>;
8
10
  commandClick?: (args: CommandClick<T>) => void;
@@ -454,35 +454,20 @@ const TableBodyCell = props => {
454
454
  }
455
455
  },
456
456
  onKeyDown: e => {
457
- const flatRows = table.getRowModel().flatRows;
458
- if (e.key === 'ArrowDown' && rowNumber < flatRows.length - 1) {
459
- const nextIndex = cell.row.index + 1;
460
- // const nextIndex = rowNumber + 1
461
-
462
- const nextId = flatRows[nextIndex].id;
463
- setFocusedCell?.({
464
- colId: cell.column.id,
465
- rowId: nextId
466
- });
467
- (0, _rowFocus.notifyArrowRowFocus)(table.getRow(nextId).original, 'arrowDown', selectionSettings?.useArrow, rowFocus);
468
- const rowQr = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
469
- const cellFocus = rowQr?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
470
- if (cellFocus) {
471
- cellFocus.focus();
472
- }
473
- }
474
- if (e.key === 'ArrowUp' && rowNumber > 0) {
475
- const prevIndex = cell.row.index - 1;
476
- const nextId = flatRows[prevIndex].id;
477
- setFocusedCell?.({
478
- colId: cell.column.id,
479
- rowId: nextId
480
- });
481
- (0, _rowFocus.notifyArrowRowFocus)(table.getRow(nextId).original, 'arrowUp', selectionSettings?.useArrow, rowFocus);
482
- const rowQr = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextId}"]`);
483
- const cellFocus = rowQr?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
484
- if (cellFocus) {
485
- cellFocus.focus();
457
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
458
+ const rows = table.getRowModel().rows;
459
+ const currentIndex = rows.findIndex(row => row.id === cell.row.id);
460
+ const nextIndex = currentIndex + (e.key === 'ArrowDown' ? 1 : -1);
461
+ const nextRow = currentIndex >= 0 ? rows[nextIndex] : undefined;
462
+ if (nextRow) {
463
+ setFocusedCell?.({
464
+ colId: cell.column.id,
465
+ rowId: nextRow.id
466
+ });
467
+ (0, _rowFocus.focusArrowRow)(e, nextRow.id, cell.column.id, () => props.rowVirtualizer?.scrollToIndex(nextIndex, {
468
+ align: 'center'
469
+ }));
470
+ (0, _rowFocus.notifyArrowRowFocus)(e, nextRow.original, e.key === 'ArrowDown' ? 'arrowDown' : 'arrowUp', selectionSettings?.useArrow, rowFocus);
486
471
  }
487
472
  }
488
473
  if (e.ctrlKey && e.code === 'Space' && cell.row.getCanSelect()) {
@@ -794,93 +794,30 @@ const TableBodyCellEdit = props => {
794
794
  }
795
795
  return;
796
796
  }
797
- if (e.key === 'ArrowDown') {
798
- // e.preventDefault()
799
- // e.stopPropagation()
800
-
801
- let nextRowIndex = rowNumber + 1;
802
- let nextRow = table.getRowModel().rows[nextRowIndex];
803
-
804
- // Nếu nextRow có children và chưa được expand, thì tìm tiếp dòng tiếp theo
805
- while (nextRow && nextRow.subRows && nextRow.subRows.length > 0) {
806
- nextRowIndex++;
807
- nextRow = table.getRowModel().rows[nextRowIndex];
797
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
798
+ const rows = table.getRowModel().rows;
799
+ const currentIndex = rows.findIndex(row => row.id === rowId);
800
+ if (currentIndex < 0) return;
801
+ const step = e.key === 'ArrowDown' ? 1 : -1;
802
+ let nextIndex = currentIndex + step;
803
+ let nextRow = rows[nextIndex];
804
+ while (nextRow?.subRows.length) {
805
+ nextIndex += step;
806
+ nextRow = rows[nextIndex];
808
807
  }
809
808
  if (nextRow) {
810
- const nextRowId = nextRow.id;
811
- setFocusedCell?.({
812
- rowId: nextRowId,
813
- colId
814
- });
815
- (0, _rowFocus.notifyArrowRowFocus)(table.getRow(nextRowId).original, 'arrowDown', selectionSettings?.useArrow, rowFocus);
816
- setStartCell?.({
817
- rowId: nextRowId,
818
- colId
819
- });
820
- setEndCell?.({
821
- rowId: nextRowId,
822
- colId
823
- });
824
- setRangeState?.((0, _utils.getSelectedCellMatrix)(table, {
825
- rowId: nextRowId,
826
- colId
827
- }, {
828
- rowId: nextRowId,
829
- colId
830
- }));
831
-
832
- // columnVirtualizer.scrollToIndex(nextCol.getIndex(), { align: 'center' })
833
- // rowVirtualizer.scrollToIndex(nextRow.index, { align: 'center' })
834
-
835
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextRowId}"]`);
836
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
837
- if (cellFocus) {
838
- cellFocus.focus();
839
- }
840
- }
841
- return;
842
- }
843
- if (e.key === 'ArrowUp') {
844
- // e.preventDefault()
845
- // e.stopPropagation()
846
-
847
- // const nextRow = table.getRowModel().rows[rowNumber - 1]
848
-
849
- let prevRowIndex = rowNumber - 1;
850
- let prevRow = table.getRowModel().rows[prevRowIndex];
851
-
852
- // Nếu nextRow có children và chưa được expand, thì tìm tiếp dòng tiếp theo
853
- while (prevRow && prevRow.subRows && prevRow.subRows.length > 0) {
854
- prevRowIndex--;
855
- prevRow = table.getRowModel().rows[prevRowIndex];
856
- }
857
- if (prevRow) {
858
- const nextRowId = prevRow.id;
859
- setFocusedCell?.({
860
- rowId: nextRowId,
861
- colId
862
- });
863
- (0, _rowFocus.notifyArrowRowFocus)(table.getRow(nextRowId).original, 'arrowUp', selectionSettings?.useArrow, rowFocus);
864
- setStartCell?.({
865
- rowId: nextRowId,
866
- colId
867
- });
868
- setEndCell?.({
869
- rowId: nextRowId,
870
- colId
871
- });
872
- setRangeState?.((0, _utils.getSelectedCellMatrix)(table, {
873
- rowId: nextRowId,
874
- colId
875
- }, {
876
- rowId: nextRowId,
809
+ const nextCell = {
810
+ rowId: nextRow.id,
877
811
  colId
812
+ };
813
+ setFocusedCell?.(nextCell);
814
+ setStartCell?.(nextCell);
815
+ setEndCell?.(nextCell);
816
+ setRangeState?.((0, _utils.getSelectedCellMatrix)(table, nextCell, nextCell));
817
+ (0, _rowFocus.focusArrowRow)(e, nextRow.id, colId, () => rowVirtualizer.scrollToIndex(nextIndex, {
818
+ align: 'center'
878
819
  }));
879
- const row = document.querySelector(`.ui-rc-grid-row[data-row-key="${nextRowId}"]`);
880
- const cellFocus = row?.querySelector('.ui-rc-grid-cell:not(.ui-rc-grid-cell-selection)');
881
- if (cellFocus) {
882
- cellFocus.focus();
883
- }
820
+ (0, _rowFocus.notifyArrowRowFocus)(e, nextRow.original, e.key === 'ArrowDown' ? 'arrowDown' : 'arrowUp', selectionSettings?.useArrow, rowFocus);
884
821
  }
885
822
  return;
886
823
  }
@@ -1,8 +1,10 @@
1
1
  /// <reference types="react" />
2
+ import type { Virtualizer } from "@tanstack/react-virtual";
2
3
  import type { Cell, Table } from "@tanstack/react-table";
3
4
  import type { CommandClick } from "../../grid-component/type";
4
5
  interface TableBodyCellProps<T> {
5
6
  table: Table<T>;
7
+ rowVirtualizer?: Virtualizer<HTMLDivElement, HTMLDivElement>;
6
8
  tableId: string;
7
9
  cell: Cell<T, unknown>;
8
10
  commandClick?: (args: CommandClick<T>) => void;