feat: keyboard shortcuts, click-to-select, pulse/glow, smooth orbit resume (#4)
* feat: keyboard shortcuts, click-to-select, pulse/glow, smooth orbit resume * feat: add camera controls and enhance keyboard shortcuts help; improve flight card accessibility * feat: enhance flight layers and keyboard shortcuts; improve airline data structure
This commit is contained in:
73
src/hooks/use-keyboard-shortcuts.ts
Normal file
73
src/hooks/use-keyboard-shortcuts.ts
Normal file
@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
type ShortcutActions = {
|
||||
onNorthUp: () => void;
|
||||
onResetView: () => void;
|
||||
onToggleOrbit: () => void;
|
||||
onOpenSearch: () => void;
|
||||
onToggleHelp: () => void;
|
||||
onDeselect: () => void;
|
||||
};
|
||||
|
||||
const INPUT_TAGS = new Set(["INPUT", "TEXTAREA", "SELECT"]);
|
||||
|
||||
export function useKeyboardShortcuts(actions: ShortcutActions) {
|
||||
const ref = useRef(actions);
|
||||
|
||||
useEffect(() => {
|
||||
ref.current = actions;
|
||||
}, [actions]);
|
||||
|
||||
useEffect(() => {
|
||||
function handler(e: KeyboardEvent) {
|
||||
const target = e.target as HTMLElement;
|
||||
if (INPUT_TAGS.has(target.tagName) || target.isContentEditable) return;
|
||||
|
||||
const dialogOpen = !!document.querySelector(
|
||||
'[role="dialog"][aria-modal="true"]',
|
||||
);
|
||||
|
||||
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
||||
|
||||
const a = ref.current;
|
||||
|
||||
if (e.key === "Escape") {
|
||||
if (!dialogOpen) a.onDeselect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dialogOpen) return;
|
||||
|
||||
switch (e.key) {
|
||||
case "n":
|
||||
case "N":
|
||||
e.preventDefault();
|
||||
a.onNorthUp();
|
||||
break;
|
||||
case "r":
|
||||
case "R":
|
||||
e.preventDefault();
|
||||
a.onResetView();
|
||||
break;
|
||||
case "o":
|
||||
case "O":
|
||||
e.preventDefault();
|
||||
a.onToggleOrbit();
|
||||
break;
|
||||
case "/":
|
||||
e.preventDefault();
|
||||
a.onOpenSearch();
|
||||
break;
|
||||
case "?":
|
||||
e.preventDefault();
|
||||
a.onToggleHelp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handler);
|
||||
return () => window.removeEventListener("keydown", handler);
|
||||
}, []);
|
||||
}
|
||||
Reference in New Issue
Block a user