MCPcopy Create free account
hub / github.com/primer/react / useTypeahead

Function useTypeahead

packages/react/src/TreeView/useTypeahead.ts:10–87  ·  view source on GitHub ↗
({containerRef, onFocusChange}: TypeaheadOptions)

Source from the content-addressed store, hash-verified

8}
9
10export function useTypeahead({containerRef, onFocusChange}: TypeaheadOptions) {
11 const searchValue = React.useRef('')
12 const timeoutRef = React.useRef(0)
13 const onFocusChangeRef = React.useRef(onFocusChange)
14 const {safeSetTimeout, safeClearTimeout} = useSafeTimeout()
15
16 // Update the ref when the callback changes
17 React.useEffect(() => {
18 onFocusChangeRef.current = onFocusChange
19 }, [onFocusChange])
20
21 // Focus the closest element that matches the search value
22 const focusSearchValue = React.useCallback(
23 (searchValue: string) => {
24 // Don't change focus if the search value is empty
25 if (!searchValue) return
26
27 if (!containerRef.current) return
28 const container = containerRef.current
29
30 // Get focusable elements
31 const elements = Array.from(container.querySelectorAll('[role="treeitem"]'))
32
33 // Get the index of active element
34 const activeIndex = elements.findIndex(element => element === document.activeElement)
35
36 // Wrap the array elements such that the active descendant is at the beginning
37 let sortedElements = wrapArray(elements, activeIndex)
38
39 // Remove the active descendant from the beginning of the array
40 // when the user initiates a new search
41 if (searchValue.length === 1) {
42 sortedElements = sortedElements.slice(1)
43 }
44
45 // Find the first element that matches the search value
46 const nextElement = sortedElements.find(element => {
47 const name = getAccessibleName(element).toLowerCase()
48 return name.startsWith(searchValue.toLowerCase())
49 })
50
51 // If a match is found, focus it
52 if (nextElement) {
53 onFocusChangeRef.current(nextElement)
54 }
55 },
56 [containerRef],
57 )
58
59 // Update the search value when the user types
60 React.useEffect(() => {
61 if (!containerRef.current) return
62 const container = containerRef.current
63
64 function onKeyDown(event: KeyboardEvent) {
65 // Ignore key presses that don't produce a character value
66 if (!event.key || event.key.length > 1) return
67

Callers 1

RootFunction · 0.90

Calls 3

getAccessibleNameFunction · 0.90
useSafeTimeoutFunction · 0.85
wrapArrayFunction · 0.85

Tested by

no test coverage detected