66 HeaderRowSelectionChangeContext ,
77 HeaderRowSelectionContext ,
88 RowSelectionChangeContext ,
9+ useActivePosition ,
910 useCalculatedColumns ,
1011 useColumnWidths ,
1112 useGridDimensions ,
@@ -77,16 +78,6 @@ import {
7778} from './style/core' ;
7879import 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-
9081export 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 ) ;
0 commit comments