import { useId, useState } from 'react'; import { createFileRoute } from '@tanstack/react-router'; import { DataGrid } from '../../src'; import type { CellKeyboardEvent, CellKeyDownArgs, Column } from '../../src'; import { useDirection } from '../directionContext'; export const Route = createFileRoute('/CellNavigation')({ component: CellNavigation }); interface Row { id: number; task: string; complete: number; priority: string; issueType: string; startDate: string; completeDate: string; } type CellNavigationMode = 'NONE' | 'CHANGE_ROW' | 'LOOP_OVER_ROW' | 'LOOP_OVER_COLUMN' | 'NO_TAB'; const columns: Column[] = [ { key: 'id', name: 'ID', width: 80 }, { key: 'task', name: 'Title' }, { key: 'priority', name: 'Priority' }, { key: 'issueType', name: 'Issue Type' }, { key: 'complete', name: '% Complete' }, { key: 'startDate', name: 'Start Date' }, { key: 'completeDate', name: 'Expected Complete', width: 200 } ]; function getRandomDate(start: Date, end: Date) { return new Date( start.getTime() + Math.random() * (end.getTime() - start.getTime()) ).toLocaleDateString(); } function createRows(): Row[] { const rows = []; for (let i = 1; i < 500; i++) { rows.push({ id: i, task: `Task ${i}`, complete: Math.min(100, Math.round(Math.random() * 110)), priority: ['Critical', 'High', 'Medium', 'Low'][Math.floor(Math.random() * 3 + 1)], issueType: ['Bug', 'Improvement', 'Epic', 'Story'][Math.floor(Math.random() * 3 + 1)], startDate: getRandomDate(new Date(2015, 3, 1), new Date()), completeDate: getRandomDate(new Date(), new Date(2016, 0, 1)) }); } return rows; } function CellNavigation() { const groupId = useId(); const direction = useDirection(); const [rows] = useState(createRows); const [cellNavigationMode, setCellNavigationMode] = useState('CHANGE_ROW'); function handleCellKeyDown(args: CellKeyDownArgs, event: CellKeyboardEvent) { if (args.mode === 'EDIT') return; const { column, rowIdx, setActivePosition } = args; const idx = column?.idx ?? -1; const { key, shiftKey } = event; const preventDefault = () => { event.preventGridDefault(); event.preventDefault(); }; const loopOverNavigation = () => { if ((key === 'ArrowRight' || (key === 'Tab' && !shiftKey)) && idx === columns.length - 1) { setActivePosition({ rowIdx, idx: 0 }); preventDefault(); } else if ((key === 'ArrowLeft' || (key === 'Tab' && shiftKey)) && idx === 0) { setActivePosition({ rowIdx, idx: columns.length - 1 }); preventDefault(); } }; const changeRowNavigation = () => { if (key === 'ArrowRight' && idx === columns.length - 1) { if (rows.length === 0) return; if (rowIdx === -1) { setActivePosition({ rowIdx: 0, idx: 0 }); } else { if (rowIdx === rows.length - 1) return; setActivePosition({ rowIdx: rowIdx + 1, idx: 0 }); } preventDefault(); } else if (key === 'ArrowLeft' && idx === 0) { if (rowIdx === -1) return; setActivePosition({ rowIdx: rowIdx - 1, idx: columns.length - 1 }); preventDefault(); } }; const loopOverColumnNavigation = () => { let newRowIdx: number; if (rowIdx === -1) { newRowIdx = shiftKey ? rows.length - 1 : 0; } else { newRowIdx = shiftKey ? rowIdx - 1 : rowIdx === rows.length - 1 ? -1 : rowIdx + 1; } setActivePosition({ rowIdx: newRowIdx, idx }); preventDefault(); }; if (cellNavigationMode === 'LOOP_OVER_ROW') { loopOverNavigation(); } else if (cellNavigationMode === 'CHANGE_ROW') { changeRowNavigation(); } else if (cellNavigationMode === 'LOOP_OVER_COLUMN' && key === 'Tab') { loopOverColumnNavigation(); } else if (cellNavigationMode === 'NO_TAB' && key === 'Tab') { // Need to allow default event to focus the next element event.preventGridDefault(); } } return ( <>
Cell Navigation Modes:
); }