forked from elastic/search-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SearchBox.js
163 lines (156 loc) · 4.99 KB
/
SearchBox.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import PropTypes from "prop-types";
import React from "react";
import Downshift from "downshift";
import { Result } from "./types";
import { Suggestion } from "./types";
import { appendClassName } from "./view-helpers";
import Autocomplete from "./Autocomplete";
import SearchInput from "./SearchInput";
function SearchBox(props) {
const {
className,
allAutocompletedItemsCount,
autocompleteView,
isFocused,
inputProps = {},
inputView,
onChange,
onSelectAutocomplete,
onSubmit,
useAutocomplete,
value,
// NOTE: These are explicitly de-structured but not used so that they are
// not passed through to the input with the 'rest' parameter
// eslint-disable-next-line no-unused-vars
autocompletedResults,
// eslint-disable-next-line no-unused-vars
autocompletedSuggestions,
// eslint-disable-next-line no-unused-vars
autocompletedSuggestionsCount,
// eslint-disable-next-line no-unused-vars
completeSuggestion,
// eslint-disable-next-line no-unused-vars
notifyAutocompleteSelected,
...rest
} = props;
const focusedClass = isFocused ? "focus" : "";
const AutocompleteView = autocompleteView || Autocomplete;
const InputView = inputView || SearchInput;
return (
<Downshift
inputValue={value}
onChange={onSelectAutocomplete}
onInputValueChange={newValue => {
// To avoid over dispatching
if (value === newValue) return;
onChange(newValue);
}}
// Because when a selection is made, we don't really want to change
// the inputValue. This is supposed to be a "controlled" value, and when
// this happens we lose control of it.
itemToString={() => value}
{...rest}
>
{downshiftProps => {
const { closeMenu, getInputProps, isOpen } = downshiftProps;
let autocompleteClass = isOpen === true ? " autocomplete" : "";
return (
<form
onSubmit={e => {
closeMenu();
onSubmit(e);
}}
>
<div
className={
appendClassName("sui-search-box", className) + autocompleteClass
}
>
<InputView
{...downshiftProps}
getInputProps={additionalProps => {
const { className, ...rest } = additionalProps || {};
return getInputProps({
placeholder: "Search",
...inputProps,
className: appendClassName("sui-search-box__text-input", [
inputProps.className,
className,
focusedClass
]),
...rest
});
}}
getButtonProps={additionalProps => {
const { className, ...rest } = additionalProps || {};
return {
type: "submit",
value: "Search",
className: appendClassName(
"button sui-search-box__submit",
className
),
...rest
};
}}
getAutocomplete={() => {
if (
useAutocomplete &&
isOpen &&
allAutocompletedItemsCount > 0
) {
return <AutocompleteView {...props} {...downshiftProps} />;
} else {
return null;
}
}}
/>
</div>
</form>
);
}}
</Downshift>
);
}
SearchBox.propTypes = {
// Provided by container
allAutocompletedItemsCount: PropTypes.number.isRequired,
autocompletedResults: PropTypes.arrayOf(Result).isRequired,
autocompletedSuggestions: PropTypes.objectOf(PropTypes.arrayOf(Suggestion))
.isRequired,
autocompletedSuggestionsCount: PropTypes.number.isRequired,
completeSuggestion: PropTypes.func.isRequired,
notifyAutocompleteSelected: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
value: PropTypes.string.isRequired,
autocompleteResults: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.shape({
titleField: PropTypes.string.isRequired,
urlField: PropTypes.string.isRequired,
linkTarget: PropTypes.string,
sectionTitle: PropTypes.string
})
]),
autocompleteView: PropTypes.func,
autocompleteSuggestions: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.exact({
sectionTitle: PropTypes.string
}),
PropTypes.objectOf(
PropTypes.exact({
sectionTitle: PropTypes.string
})
)
]),
className: PropTypes.string,
inputProps: PropTypes.object,
inputView: PropTypes.func,
isFocused: PropTypes.bool,
useAutocomplete: PropTypes.bool,
// Specific configuration for this view only
onSelectAutocomplete: PropTypes.func
};
export default SearchBox;