Skip to content

Commit 0bd6803

Browse files
committed
feat: move key events to become global.
1 parent bf92ee2 commit 0bd6803

1 file changed

Lines changed: 48 additions & 31 deletions

File tree

Website/components/datamodelview/TimeSlicedSearch.tsx

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useSidebar } from '@/contexts/SidebarContext';
66
import { useSettings } from '@/contexts/SettingsContext';
77
import { useIsMobile } from '@/hooks/use-mobile';
88
import { Box, CircularProgress, Divider, IconButton, InputAdornment, InputBase, ListItemIcon, ListItemText, Menu, MenuItem, MenuList, Paper, TextField, Typography } from '@mui/material';
9-
import { ClearRounded, CloseRounded, InfoRounded, NavigateBeforeRounded, NavigateNextRounded, SearchRounded } from '@mui/icons-material';
9+
import { ClearRounded, CloseRounded, InfoRounded, KeyboardArrowDownRounded, KeyboardArrowUpRounded, NavigateBeforeRounded, NavigateNextRounded, SearchRounded } from '@mui/icons-material';
1010

1111
interface TimeSlicedSearchProps {
1212
onSearch: (value: string) => void;
@@ -45,6 +45,39 @@ export const TimeSlicedSearch = ({
4545
// Hide search on mobile when sidebar is open, or when settings are open
4646
const shouldHideSearch = (isMobile && isOpen) || isSettingsOpen;
4747

48+
useEffect(() => {
49+
const handleGlobalKeyDown = (e: KeyboardEvent) => {
50+
if (localValue.length === 0) return;
51+
if (e.key === 'Escape') {
52+
e.preventDefault();
53+
setLocalValue('');
54+
onSearch(''); // Only clear when explicitly using ESC
55+
setIsTyping(false);
56+
onLoadingChange(false);
57+
} else if (e.key === 'Enter' && !e.shiftKey) {
58+
e.preventDefault();
59+
onNavigateNext?.();
60+
if ('vibrate' in navigator) {
61+
navigator.vibrate(50);
62+
}
63+
} else if (e.key === 'Enter' && e.shiftKey) {
64+
e.preventDefault();
65+
onNavigatePrevious?.();
66+
if ('vibrate' in navigator) {
67+
navigator.vibrate(50);
68+
}
69+
} else if (e.key === 'ArrowDown' && e.ctrlKey) {
70+
e.preventDefault();
71+
onNavigateNext?.();
72+
} else if (e.key === 'ArrowUp' && e.ctrlKey) {
73+
e.preventDefault();
74+
onNavigatePrevious?.();
75+
}
76+
};
77+
window.addEventListener('keydown', handleGlobalKeyDown);
78+
return () => window.removeEventListener('keydown', handleGlobalKeyDown);
79+
}, [localValue, onSearch, onLoadingChange, onNavigateNext, onNavigatePrevious]);
80+
4881
// Time-sliced debouncing using requestAnimationFrame
4982
const scheduleSearch = useCallback((value: string) => {
5083
if (searchTimeoutRef.current) {
@@ -139,35 +172,6 @@ export const TimeSlicedSearch = ({
139172
}
140173
}, [onSearch, onLoadingChange]);
141174

142-
// Handle keyboard navigation
143-
const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
144-
if (e.key === 'Escape') {
145-
e.preventDefault();
146-
setLocalValue('');
147-
onSearch(''); // Only clear when explicitly using ESC
148-
setIsTyping(false);
149-
onLoadingChange(false);
150-
} else if (e.key === 'Enter' && !e.shiftKey) {
151-
e.preventDefault();
152-
onNavigateNext?.();
153-
if ('vibrate' in navigator) {
154-
navigator.vibrate(50);
155-
}
156-
} else if (e.key === 'Enter' && e.shiftKey) {
157-
e.preventDefault();
158-
onNavigatePrevious?.();
159-
if ('vibrate' in navigator) {
160-
navigator.vibrate(50);
161-
}
162-
} else if (e.key === 'ArrowDown' && e.ctrlKey) {
163-
e.preventDefault();
164-
onNavigateNext?.();
165-
} else if (e.key === 'ArrowUp' && e.ctrlKey) {
166-
e.preventDefault();
167-
onNavigatePrevious?.();
168-
}
169-
}, [onNavigateNext, onNavigatePrevious, onSearch, onLoadingChange]);
170-
171175
// Cleanup
172176
useEffect(() => {
173177
return () => {
@@ -240,7 +244,6 @@ export const TimeSlicedSearch = ({
240244
aria-label="Search attributes in tables"
241245
value={localValue}
242246
onChange={handleChange}
243-
onKeyDown={handleKeyDown}
244247
spellCheck={false}
245248
autoComplete="off"
246249
autoCapitalize="off"
@@ -286,6 +289,20 @@ export const TimeSlicedSearch = ({
286289
<ListItemText>Previous</ListItemText>
287290
<Typography variant='body2' color="text.secondary">Shift + Enter</Typography>
288291
</MenuItem>
292+
<MenuItem onClick={onNavigateNext}>
293+
<ListItemIcon>
294+
<NavigateNextRounded />
295+
</ListItemIcon>
296+
<ListItemText>Next</ListItemText>
297+
<Typography variant='body2' color="text.secondary">Ctrl + <KeyboardArrowDownRounded /></Typography>
298+
</MenuItem>
299+
<MenuItem onClick={onNavigatePrevious}>
300+
<ListItemIcon>
301+
<NavigateBeforeRounded />
302+
</ListItemIcon>
303+
<ListItemText>Previous</ListItemText>
304+
<Typography variant='body2' color="text.secondary">Ctrl + <KeyboardArrowUpRounded /></Typography>
305+
</MenuItem>
289306
<Divider />
290307
<MenuItem onClick={handleClear}>
291308
<ListItemIcon>

0 commit comments

Comments
 (0)