Skip to content

Commit 0aebcf3

Browse files
committed
refactor(AutoComplete): Extract useFocus hook
1 parent f614a00 commit 0aebcf3

2 files changed

Lines changed: 33 additions & 32 deletions

File tree

src/components/ui/auto-complete/auto-complete.tsx

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
PropsWithChildren,
55
ReactNode,
66
RefObject,
7-
useEffect,
87
useMemo,
98
useRef,
109
useState,
@@ -14,43 +13,13 @@ import { Slot } from "@radix-ui/react-slot"
1413

1514
import { Button } from "components/ui/button"
1615
import { Portal } from "components/utility/portal"
16+
import { useFocus } from "hooks/use-focus"
1717
import { ClassNameProp } from "types/base-props"
1818
import { cn } from "utils/cn"
1919
import { fuzzyFilter } from "utils/fuzzy-filter"
2020
import { surface } from "utils/styles"
2121
import { zIndex } from "utils/z-index"
2222

23-
const useFocus = (refs: RefObject<Element | null>[]) => {
24-
const [focus, setFocus] = useState(false)
25-
26-
useEffect(() => {
27-
const handler = () => {
28-
const elements = refs
29-
.map(({ current }) => current)
30-
.filter(Boolean) as Element[]
31-
32-
const target = document.activeElement
33-
const focus = elements.some(
34-
element => element === target || element.contains(target)
35-
)
36-
37-
setFocus(!!focus)
38-
}
39-
40-
window.addEventListener("focusin", handler)
41-
window.addEventListener("click", handler)
42-
43-
return () => {
44-
window.removeEventListener("focusin", handler)
45-
window.removeEventListener("click", handler)
46-
}
47-
// eslint-disable-next-line react-compiler/react-compiler
48-
// eslint-disable-next-line react-hooks/exhaustive-deps
49-
}, refs)
50-
51-
return focus
52-
}
53-
5423
const useBoundingRect = () => {
5524
const [boundingRect, setBoundingRect] =
5625
useState<ReturnType<Element["getBoundingClientRect"]>>()

src/hooks/use-focus.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { RefObject, useEffect, useState } from "react"
2+
3+
export const useFocus = (refs: RefObject<Element | null>[]) => {
4+
const [focus, setFocus] = useState(false)
5+
6+
useEffect(() => {
7+
const handler = () => {
8+
const elements = refs
9+
.map(({ current }) => current)
10+
.filter(Boolean) as Element[]
11+
12+
const target = document.activeElement
13+
const focus = elements.some(
14+
element => element === target || element.contains(target)
15+
)
16+
17+
setFocus(!!focus)
18+
}
19+
20+
window.addEventListener("focusin", handler)
21+
window.addEventListener("click", handler)
22+
23+
return () => {
24+
window.removeEventListener("focusin", handler)
25+
window.removeEventListener("click", handler)
26+
}
27+
// eslint-disable-next-line react-compiler/react-compiler
28+
// eslint-disable-next-line react-hooks/exhaustive-deps
29+
}, refs)
30+
31+
return focus
32+
}

0 commit comments

Comments
 (0)