D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
search
/
hooks
/
Filename :
useSearchKeyboardSelection.ts
back
Copy
import { useEffect, useRef, useState } from 'react'; import { Observable, Subject } from 'rxjs'; import { Field, locationUtil } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { QueryResponse } from '../service'; export function useKeyNavigationListener() { const eventsRef = useRef(new Subject<React.KeyboardEvent>()); return { keyboardEvents: eventsRef.current, onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => { switch (e.code) { case 'ArrowDown': case 'ArrowUp': case 'ArrowLeft': case 'ArrowRight': case 'Enter': eventsRef.current.next(e); default: // ignore } }, }; } interface ItemSelection { x: number; y: number; } export function useSearchKeyboardNavigation( keyboardEvents: Observable<React.KeyboardEvent>, numColumns: number, response: QueryResponse ): ItemSelection { const highlightIndexRef = useRef<ItemSelection>({ x: 0, y: -1 }); const [highlightIndex, setHighlightIndex] = useState<ItemSelection>({ x: 0, y: -1 }); const urlsRef = useRef<Field>(); // Clear selection when the search results change useEffect(() => { urlsRef.current = response.view.fields.url; highlightIndexRef.current.x = 0; highlightIndexRef.current.y = -1; setHighlightIndex({ ...highlightIndexRef.current }); }, [response]); useEffect(() => { const sub = keyboardEvents.subscribe({ next: (keyEvent) => { switch (keyEvent?.code) { case 'ArrowDown': { highlightIndexRef.current.y++; setHighlightIndex({ ...highlightIndexRef.current }); break; } case 'ArrowUp': highlightIndexRef.current.y = Math.max(0, highlightIndexRef.current.y - 1); setHighlightIndex({ ...highlightIndexRef.current }); break; case 'ArrowRight': { if (numColumns > 0) { highlightIndexRef.current.x = Math.min(numColumns, highlightIndexRef.current.x + 1); setHighlightIndex({ ...highlightIndexRef.current }); } break; } case 'ArrowLeft': { if (numColumns > 0) { highlightIndexRef.current.x = Math.max(0, highlightIndexRef.current.x - 1); setHighlightIndex({ ...highlightIndexRef.current }); } break; } case 'Enter': if (!urlsRef.current) { break; } const idx = highlightIndexRef.current.x * numColumns + highlightIndexRef.current.y; if (idx < 0) { highlightIndexRef.current.x = 0; highlightIndexRef.current.y = 0; setHighlightIndex({ ...highlightIndexRef.current }); break; } const url = urlsRef.current.values?.[idx] as string; if (url) { locationService.push(locationUtil.stripBaseFromUrl(url)); } } }, }); return () => sub.unsubscribe(); }, [keyboardEvents, numColumns]); return highlightIndex; }