Spaces:
Running
Running
| import { useEffect } from 'react'; | |
| import { useReaderStore } from '../stores/appStore'; | |
| /** | |
| * Keyboard navigation for the Tipitaka Reader. | |
| * | |
| * β / PageUp β previous page | |
| * β / PageDown β next page | |
| * Space β next page | |
| * | |
| * Does NOT capture Up/Down β those are reserved for native scroll | |
| * so the user can scroll within a long page of text. | |
| * Does NOT fire when focus is inside <input>, <textarea>, or <select>. | |
| */ | |
| export function useKeyboardNav(): void { | |
| const { prevPage, nextPage } = useReaderStore(); | |
| useEffect(() => { | |
| const handler = (e: KeyboardEvent) => { | |
| // Skip if user is typing in a form field | |
| const tag = (e.target as HTMLElement).tagName; | |
| if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return; | |
| switch (e.key) { | |
| case 'ArrowLeft': | |
| case 'PageUp': | |
| e.preventDefault(); | |
| prevPage(); | |
| break; | |
| case 'ArrowRight': | |
| case 'PageDown': | |
| e.preventDefault(); | |
| nextPage(); | |
| break; | |
| case ' ': // Space | |
| e.preventDefault(); | |
| nextPage(); | |
| break; | |
| } | |
| }; | |
| window.addEventListener('keydown', handler); | |
| return () => window.removeEventListener('keydown', handler); | |
| }, [prevPage, nextPage]); | |
| } | |