Skip to content

Commit 61cb9e7

Browse files
committed
Use common SearchBox
1 parent faf0f9a commit 61cb9e7

File tree

6 files changed

+219
-393
lines changed

6 files changed

+219
-393
lines changed

components/SearchBox.js

+112
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/SearchBox.res

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* This SearchBox is used for fuzzy-find search scenarios, such as the syntax widget tool or
3+
* the package index
4+
*/
5+
6+
@bs.send external focus: Dom.element => unit = "focus"
7+
8+
type state =
9+
| Active
10+
| Inactive
11+
12+
@react.component
13+
let make = (
14+
~completionValues: array<string>=[], // set of possible values
15+
~value: string,
16+
~onClear: unit => unit,
17+
~placeholder: string="",
18+
~onValueChange: string => unit,
19+
) => {
20+
let (state, setState) = React.useState(_ => Inactive)
21+
let textInput = React.useRef(Js.Nullable.null)
22+
23+
let onMouseDownClear = evt => {
24+
ReactEvent.Mouse.preventDefault(evt)
25+
onClear()
26+
}
27+
28+
let focusInput = () =>
29+
textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus)
30+
31+
let onAreaFocus = evt => {
32+
let el = ReactEvent.Focus.target(evt)
33+
let isDiv = Js.Null_undefined.isNullable(el["type"])
34+
35+
if isDiv && state === Inactive {
36+
focusInput()
37+
}
38+
}
39+
40+
let onFocus = _ => {
41+
setState(_ => Active)
42+
}
43+
44+
let onBlur = _ => {
45+
setState(_ => Inactive)
46+
}
47+
48+
let onKeyDown = evt => {
49+
let key = ReactEvent.Keyboard.key(evt)
50+
let ctrlKey = ReactEvent.Keyboard.ctrlKey(evt)
51+
52+
let full = (ctrlKey ? "CTRL+" : "") ++ key
53+
54+
switch full {
55+
| "Escape" => onClear()
56+
| "Tab" =>
57+
if Js.Array.length(completionValues) === 1 {
58+
let targetValue = Belt.Array.getExn(completionValues, 0)
59+
60+
if targetValue !== value {
61+
ReactEvent.Keyboard.preventDefault(evt)
62+
onValueChange(targetValue)
63+
} else {
64+
()
65+
}
66+
}
67+
| _ => ()
68+
}
69+
}
70+
71+
let onChange = evt => {
72+
ReactEvent.Form.preventDefault(evt)
73+
let value = ReactEvent.Form.target(evt)["value"]
74+
onValueChange(value)
75+
}
76+
77+
<div
78+
tabIndex={-1}
79+
onFocus=onAreaFocus
80+
onBlur
81+
className={(
82+
state === Active ? "border-fire" : "border-fire-40"
83+
) ++ " flex items-center border rounded-lg py-4 px-5"}>
84+
<Icon.MagnifierGlass
85+
className={(state === Active ? "text-fire" : "text-fire-80") ++ " w-4 h-4"}
86+
/>
87+
<input
88+
value
89+
ref={ReactDOM.Ref.domRef(textInput)}
90+
onFocus
91+
onKeyDown
92+
onChange={onChange}
93+
placeholder
94+
className="text-16 outline-none ml-4 w-full"
95+
type_="text"
96+
/>
97+
<button onFocus className={value === "" ? "hidden" : "block"} onMouseDown=onMouseDownClear>
98+
<Icon.Close className="w-4 h-4 text-fire" />
99+
</button>
100+
</div>
101+
}

components/SyntaxLookupWidget.js

+3-96
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)