import React from 'react' import { useGridContext } from '../context/grid-context' const SPREADSHEET_KEYS = ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft'] export function useGridNavigation() { const grid = useGridContext() const keyDownHandler = React.useCallback( (e: React.KeyboardEvent) => { const state = grid.getState() const enabled = grid.selectors.selectNavigationEnabled(state) const editing = grid.selectors.selectIsEditing(state) const headerEnabled = !grid.selectors.selectAreHeadersHidden(state) const spreadsheetMode = grid.selectors.selectIsSpreadsheet(state) if (!enabled || editing) { return } if ( e.shiftKey && spreadsheetMode && SPREADSHEET_KEYS.includes(e.key) ) { e.preventDefault() if (e.key === 'ArrowDown') { e.preventDefault() grid.api.rangeSelection.move('down') } if (e.key === 'ArrowUp') { e.preventDefault() grid.api.rangeSelection.move('up') } if (e.key === 'ArrowRight') { e.preventDefault() grid.api.rangeSelection.move('right') } if (e.key === 'ArrowLeft') { e.preventDefault() grid.api.rangeSelection.move('left') } return } if (e.key === 'Home') { e.preventDefault() if (e.ctrlKey || e.metaKey) { const rowIds = grid.selectors.selectRowIds(state) const columnIds = grid.selectors.selectColumnIds(state) grid.api.focus.set( headerEnabled ? '0' : rowIds[0], columnIds[0], headerEnabled ? 'header' : 'body' ) } else { const { rowId, area } = grid.selectors.selectCurrentFocus(state) const columnIds = grid.selectors.selectColumnIds(state) grid.api.focus.set(rowId, columnIds[0], area) } } if (e.key === 'End') { e.preventDefault() if (e.ctrlKey || e.metaKey) { const rowIds = grid.selectors.selectRowIds(state) const columnIds = grid.selectors.selectColumnIds(state) const footerEnabled = grid.selectors.selectAggregationEnabled(state) grid.api.focus.set( footerEnabled ? '0' : rowIds[rowIds.length - 1], columnIds[columnIds.length - 1], footerEnabled ? 'footer' : 'body' ) } else { const { rowId, area } = grid.selectors.selectCurrentFocus(state) const columnIds = grid.selectors.selectColumnIds(state) grid.api.focus.set( rowId, columnIds[columnIds.length - 1], area ) } } if (e.key === 'PageUp') { e.preventDefault() const { rowId, area, columnId } = grid.selectors.selectCurrentFocus(state) const rowsToJump = grid.selectors.selectNumberOfRowsInView(state) if (area === 'body') { const rowIds = grid.selectors.selectRowIds(state) const currentRowIndex = rowIds.indexOf(rowId) const nextIndex = currentRowIndex - rowsToJump if (nextIndex < 0) { //Go to header grid.api.focus.set( headerEnabled ? '0' : rowIds[0], columnId, headerEnabled ? 'header' : 'body' ) } else { grid.api.focus.set(rowIds[nextIndex], columnId, area) } } } if (e.key === 'PageDown') { e.preventDefault() const { rowId, area, columnId } = grid.selectors.selectCurrentFocus(state) const rowsToJump = grid.selectors.selectNumberOfRowsInView(state) const rowIds = grid.selectors.selectRowIds(state) const currentRowIndex = area === 'header' ? 0 : rowIds.indexOf(rowId) const nextIndex = Math.min( currentRowIndex + rowsToJump, rowIds.length - 1 ) const nextRowId = rowIds[nextIndex] grid.api.focus.set(nextRowId, columnId, 'body') } if (e.key === 'ArrowDown') { e.preventDefault() grid.api.focus.move('down') } if (e.key === 'ArrowUp') { e.preventDefault() grid.api.focus.move('up') } if (e.key === 'ArrowRight') { e.preventDefault() grid.api.focus.move('right') } if (e.key === 'ArrowLeft') { e.preventDefault() grid.api.focus.move('left') } if (e.key === ' ' && e.shiftKey) { e.preventDefault() const currentFocus = grid.selectors.selectCurrentFocus(state) if (currentFocus.area === 'body') { const currentRowId = currentFocus.rowId const isSelected = grid.selectors.selectIsRowSelected( state, currentRowId ) grid.api.selection.select(currentRowId, !isSelected) grid.events.emit('onRowClick', currentRowId) } } }, [grid] ) return keyDownHandler }