Skip to content

Commit 772dafc

Browse files
authored
Merge branch 'main' into externaldimensions
2 parents b78a048 + 5e1ac44 commit 772dafc

8 files changed

Lines changed: 280 additions & 162 deletions

File tree

src/DataGrid.tsx

Lines changed: 57 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
HeaderRowSelectionChangeContext,
77
HeaderRowSelectionContext,
88
RowSelectionChangeContext,
9+
useActivePosition,
910
useCalculatedColumns,
1011
useColumnWidths,
1112
useGridDimensions,
@@ -77,16 +78,6 @@ import {
7778
} from './style/core';
7879
import SummaryRow from './SummaryRow';
7980

80-
interface ActiveCellState extends Position {
81-
readonly mode: 'ACTIVE';
82-
}
83-
84-
interface EditCellState<R> extends Position {
85-
readonly mode: 'EDIT';
86-
readonly row: R;
87-
readonly originalRow: R;
88-
}
89-
9081
export type DefaultColumnOptions<R, SR> = Pick<
9182
Column<R, SR>,
9283
| 'renderCell'
@@ -365,33 +356,50 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
365356
enableVirtualization
366357
});
367358

359+
/**
360+
* computed values
361+
*/
362+
const isTreeGrid = role === 'treegrid';
368363
const topSummaryRowsCount = topSummaryRows?.length ?? 0;
369364
const bottomSummaryRowsCount = bottomSummaryRows?.length ?? 0;
370365
const summaryRowsCount = topSummaryRowsCount + bottomSummaryRowsCount;
371366
const headerAndTopSummaryRowsCount = headerRowsCount + topSummaryRowsCount;
372367
const groupedColumnHeaderRowsCount = headerRowsCount - 1;
373368
const minRowIdx = -headerAndTopSummaryRowsCount;
374-
const mainHeaderRowIdx = minRowIdx + groupedColumnHeaderRowsCount;
375369
const maxRowIdx = rows.length + bottomSummaryRowsCount - 1;
376-
const frozenShadowStyles: React.CSSProperties = {
377-
gridColumnStart: lastFrozenColumnIndex + 2,
378-
insetInlineStart: totalFrozenColumnWidth
379-
};
380-
381-
const [activePosition, setActivePosition] = useState<ActiveCellState | EditCellState<R>>(
382-
getInitialActivePosition
383-
);
384-
385-
/**
386-
* computed values
387-
*/
388-
const isTreeGrid = role === 'treegrid';
370+
const mainHeaderRowIdx = minRowIdx + groupedColumnHeaderRowsCount;
371+
const maxColIdx = columns.length - 1;
389372
const headerRowsHeight = headerRowsCount * headerRowHeight;
390373
const summaryRowsHeight = summaryRowsCount * summaryRowHeight;
391374
const clientHeight = gridHeight - headerRowsHeight - summaryRowsHeight;
392375
const isSelectable = selectedRows != null && onSelectedRowsChange != null;
393376
const { leftKey, rightKey } = getLeftRightKey(direction);
394377
const ariaRowCount = rawAriaRowCount ?? headerRowsCount + rows.length + summaryRowsCount;
378+
const frozenShadowStyles: React.CSSProperties = {
379+
gridColumnStart: lastFrozenColumnIndex + 2,
380+
insetInlineStart: totalFrozenColumnWidth
381+
};
382+
383+
const {
384+
activePosition,
385+
setActivePosition,
386+
activePositionIsInActiveBounds,
387+
activePositionIsInViewport,
388+
activePositionIsRow,
389+
activePositionIsCellInViewport,
390+
validatePosition,
391+
getActiveColumn,
392+
getActiveRow
393+
} = useActivePosition<R, SR>({
394+
columns,
395+
rows,
396+
isTreeGrid,
397+
maxColIdx,
398+
minRowIdx,
399+
maxRowIdx,
400+
setDraggedOverRowIdx,
401+
setShouldFocusPosition
402+
});
395403

396404
const defaultGridComponents = useMemo(
397405
() => ({
@@ -441,14 +449,6 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
441449
enableVirtualization
442450
});
443451

444-
const maxColIdx = columns.length - 1;
445-
const {
446-
isPositionInActiveBounds: activePositionIsInActiveBounds,
447-
isPositionInViewport: activePositionIsInViewport,
448-
isRowInActiveBounds: activePositionIsRow,
449-
isCellInViewport: activePositionIsCellInViewport
450-
} = validatePosition(activePosition);
451-
452452
const {
453453
viewportColumns,
454454
iterateOverViewportColumnsForRow,
@@ -656,29 +656,32 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
656656

657657
function commitEditorChanges() {
658658
if (activePosition.mode !== 'EDIT') return;
659-
updateRow(columns[activePosition.idx], activePosition.rowIdx, activePosition.row);
659+
updateRow(getActiveColumn(), activePosition.rowIdx, activePosition.row);
660660
}
661661

662662
function handleCellCopy(event: CellClipboardEvent) {
663663
if (!activePositionIsCellInViewport) return;
664-
const { idx, rowIdx } = activePosition;
665-
onCellCopy?.({ row: rows[rowIdx], column: columns[idx] }, event);
664+
onCellCopy?.({ row: getActiveRow(), column: getActiveColumn() }, event);
666665
}
667666

668667
function handleCellPaste(event: CellClipboardEvent) {
669-
if (!onCellPaste || !onRowsChange || !isCellEditable(activePosition)) {
668+
if (
669+
typeof onCellPaste !== 'function' ||
670+
typeof onRowsChange !== 'function' ||
671+
!isCellEditable(activePosition)
672+
) {
670673
return;
671674
}
672675

673-
const { idx, rowIdx } = activePosition;
674-
const column = columns[idx];
675-
const updatedRow = onCellPaste({ row: rows[rowIdx], column }, event);
676-
updateRow(column, rowIdx, updatedRow);
676+
const column = getActiveColumn();
677+
const row = getActiveRow();
678+
const updatedRow = onCellPaste({ row, column }, event);
679+
updateRow(column, activePosition.rowIdx, updatedRow);
677680
}
678681

679682
function handleCellInput(event: KeyboardEvent<HTMLDivElement>) {
680683
if (!activePositionIsCellInViewport) return;
681-
const row = rows[activePosition.rowIdx];
684+
const row = getActiveRow();
682685
const { key, shiftKey } = event;
683686

684687
// Select the row on Shift + Space
@@ -764,9 +767,9 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
764767
function updateRows(startRowIdx: number, endRowIdx: number) {
765768
if (onRowsChange == null) return;
766769

767-
const { rowIdx, idx } = activePosition;
768-
const column = columns[idx];
769-
const sourceRow = rows[rowIdx];
770+
const { idx } = activePosition;
771+
const column = getActiveColumn();
772+
const sourceRow = getActiveRow();
770773
const updatedRows = [...rows];
771774
const indexes: number[] = [];
772775
for (let i = startRowIdx; i < endRowIdx; i++) {
@@ -784,50 +787,6 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
784787
}
785788
}
786789

787-
/**
788-
* utils
789-
*/
790-
function getInitialActivePosition(): ActiveCellState {
791-
return { idx: -1, rowIdx: minRowIdx - 1, mode: 'ACTIVE' };
792-
}
793-
794-
/**
795-
* Returns whether the given position represents a valid cell or row position in the grid.
796-
* Active bounds: any valid position in the grid
797-
* Viewport: any valid position in the grid outside of header rows and summary rows
798-
* Row selection is only allowed in TreeDataGrid
799-
*/
800-
function validatePosition({ idx, rowIdx }: Position) {
801-
// check column position
802-
const isColumnPositionAllColumns = isTreeGrid && idx === -1;
803-
const isColumnPositionInActiveBounds = idx >= 0 && idx <= maxColIdx;
804-
805-
// check row position
806-
const isRowPositionInActiveBounds = rowIdx >= minRowIdx && rowIdx <= maxRowIdx;
807-
const isRowPositionInViewport = rowIdx >= 0 && rowIdx < rows.length;
808-
809-
// row status
810-
const isRowInActiveBounds = isColumnPositionAllColumns && isRowPositionInActiveBounds;
811-
const isRowInViewport = isColumnPositionAllColumns && isRowPositionInViewport;
812-
813-
// cell status
814-
const isCellInActiveBounds = isColumnPositionInActiveBounds && isRowPositionInActiveBounds;
815-
const isCellInViewport = isColumnPositionInActiveBounds && isRowPositionInViewport;
816-
817-
// position status
818-
const isPositionInActiveBounds = isRowInActiveBounds || isCellInActiveBounds;
819-
const isPositionInViewport = isRowInViewport || isCellInViewport;
820-
821-
return {
822-
isPositionInActiveBounds,
823-
isPositionInViewport,
824-
isRowInActiveBounds,
825-
isRowInViewport,
826-
isCellInActiveBounds,
827-
isCellInViewport
828-
};
829-
}
830-
831790
function isCellEditable(position: Position): boolean {
832791
return (
833792
validatePosition(position).isCellInViewport &&
@@ -977,19 +936,19 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
977936
}
978937

979938
function getDragHandle() {
980-
if (onFill == null || activePosition.mode === 'EDIT' || !activePositionIsCellInViewport) {
939+
if (onFill == null || activePosition.mode !== 'ACTIVE' || !activePositionIsCellInViewport) {
981940
return;
982941
}
983942

984-
const { idx, rowIdx } = activePosition;
985-
const column = columns[idx];
943+
const { rowIdx } = activePosition;
944+
const column = getActiveColumn();
986945
if (column.renderEditCell == null || column.editable === false) {
987946
return;
988947
}
989948

990949
const isLastRow = rowIdx === maxRowIdx;
991950
const columnWidth = getColumnWidth(column);
992-
const colSpan = column.colSpan?.({ type: 'ROW', row: rows[rowIdx] }) ?? 1;
951+
const colSpan = column.colSpan?.({ type: 'ROW', row: getActiveRow() }) ?? 1;
993952
const { insetInlineStart, ...style } = getCellStyle(column, colSpan);
994953
const marginEnd = 'calc(var(--rdg-drag-handle-size) * -0.5 + 1px)';
995954
const isLastColumn = column.idx + colSpan - 1 === maxColIdx;
@@ -1023,22 +982,21 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
1023982
if (
1024983
!activePositionIsCellInViewport ||
1025984
activePosition.rowIdx !== rowIdx ||
1026-
activePosition.mode === 'ACTIVE'
985+
activePosition.mode !== 'EDIT'
1027986
) {
1028987
return;
1029988
}
1030989

1031-
const { idx, row } = activePosition;
1032-
const column = columns[idx];
990+
const { row } = activePosition;
991+
const column = getActiveColumn();
1033992
const colSpan = getColSpan(column, lastFrozenColumnIndex, { type: 'ROW', row });
1034-
const closeOnExternalRowChange = column.editorOptions?.closeOnExternalRowChange ?? true;
1035993

1036-
const closeEditor = (shouldFocus: boolean) => {
994+
function closeEditor(shouldFocus: boolean) {
1037995
setShouldFocusPosition(shouldFocus);
1038996
setActivePosition(({ idx, rowIdx }) => ({ idx, rowIdx, mode: 'ACTIVE' }));
1039-
};
997+
}
1040998

1041-
const onRowChange = (row: R, commitChanges: boolean, shouldFocus: boolean) => {
999+
function onRowChange(row: R, commitChanges: boolean, shouldFocus: boolean) {
10421000
if (commitChanges) {
10431001
// Prevents two issues when editor is closed by clicking on a different cell
10441002
//
@@ -1051,11 +1009,6 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
10511009
} else {
10521010
setActivePosition((position) => ({ ...position, row }));
10531011
}
1054-
};
1055-
1056-
if (closeOnExternalRowChange && rows[activePosition.rowIdx] !== activePosition.originalRow) {
1057-
// Discard changes if rows are updated from outside
1058-
closeEditor(false);
10591012
}
10601013

10611014
return (
@@ -1135,12 +1088,6 @@ export function DataGrid<R, SR = unknown, K extends Key = Key>(props: DataGridPr
11351088
.toArray();
11361089
}
11371090

1138-
// Reset the positions if the current values are no longer valid. This can happen if a column or row is removed
1139-
if (activePosition.idx > maxColIdx || activePosition.rowIdx > maxRowIdx) {
1140-
setActivePosition(getInitialActivePosition());
1141-
setDraggedOverRowIdx(undefined);
1142-
}
1143-
11441091
// Keep the state and prop in sync
11451092
if (isColumnWidthsControlled && columnWidthsInternal !== columnWidthsRaw) {
11461093
setColumnWidthsInternal(columnWidthsRaw);

src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './useActivePosition';
12
export * from './useCalculatedColumns';
23
export * from './useColumnWidths';
34
export * from './useGridDimensions';

0 commit comments

Comments
 (0)