1 | import * as React from 'react';
|
2 | import { PropTypes } from 'react';
|
3 |
|
4 | import { Search, SearchResultData, SearchProps } from 'semantic-ui-react';
|
5 | import { take } from 'lodash';
|
6 | import { SearchParams } from '../context/DataStore';
|
7 |
|
8 | interface SearchBoxProps {
|
9 | placeholder: string;
|
10 | loading: boolean;
|
11 | sampleSearches?: string[];
|
12 | transition?: (params: SearchParams) => void;
|
13 | }
|
14 |
|
15 | interface SearchBoxState {
|
16 | query: string;
|
17 | shouldBeOpen: boolean;
|
18 | searchEditedByUser: boolean;
|
19 | }
|
20 |
|
21 | class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
|
22 | static contextTypes = {
|
23 | searchState: PropTypes.object,
|
24 | transition: PropTypes.func
|
25 | };
|
26 |
|
27 | state = {
|
28 | query: '',
|
29 | shouldBeOpen: false,
|
30 | searchEditedByUser: false
|
31 | };
|
32 |
|
33 | constructor() {
|
34 | super();
|
35 |
|
36 | this.onKeyUp = this.onKeyUp.bind(this);
|
37 | this.onBlur = this.onBlur.bind(this);
|
38 | this.onChangeQuery = this.onChangeQuery.bind(this);
|
39 | this.onSelectTypeahead = this.onSelectTypeahead.bind(this);
|
40 | }
|
41 |
|
42 | onKeyUp(event: React.KeyboardEvent<object>) {
|
43 | event.preventDefault();
|
44 |
|
45 | if (event.keyCode === 13) {
|
46 | this.onDoSearch(this.state.query);
|
47 | this.setState({shouldBeOpen: false});
|
48 | } else if (event.keyCode === 27) {
|
49 | this.setState({shouldBeOpen: false});
|
50 | }
|
51 | }
|
52 |
|
53 | onChangeQuery(e: React.MouseEvent<HTMLElement>, data: SearchProps) {
|
54 | this.setState(
|
55 | {
|
56 | query: data.value + '',
|
57 | shouldBeOpen: (data.value || '').length > 0,
|
58 | searchEditedByUser: true
|
59 | }
|
60 | );
|
61 | }
|
62 |
|
63 | onSelectTypeahead(e: React.MouseEvent<HTMLDivElement>, data: SearchResultData) {
|
64 | this.setState(
|
65 | {
|
66 | query: data.result.title,
|
67 | shouldBeOpen: false,
|
68 | searchEditedByUser: true
|
69 | }
|
70 | );
|
71 |
|
72 | this.onDoSearch(data.value + '');
|
73 | }
|
74 |
|
75 | onDoSearch(value: string) {
|
76 | const query: SearchParams = {
|
77 | query: value,
|
78 | start: 0
|
79 | };
|
80 |
|
81 | if (this.props.transition) {
|
82 | this.props.transition(query);
|
83 | } else {
|
84 | this.context.transition(query);
|
85 | }
|
86 | }
|
87 |
|
88 | onBlur() {
|
89 | this.setState({shouldBeOpen: false});
|
90 | }
|
91 |
|
92 | render() {
|
93 | const self = this;
|
94 |
|
95 | const query =
|
96 | (self.state.searchEditedByUser ?
|
97 | self.state.query :
|
98 | self.context.searchState ?
|
99 | (
|
100 | self.context.searchState.query
|
101 | ) : ''
|
102 | ) || '';
|
103 |
|
104 | const lc = query.toLowerCase();
|
105 | const filteredSearches = take(
|
106 | (self.props.sampleSearches || []).filter(
|
107 | (search) => search.indexOf(lc) === 0
|
108 | ),
|
109 | 5
|
110 | ).map(
|
111 | (title) => { return {title}; }
|
112 | );
|
113 |
|
114 | return (
|
115 | <Search
|
116 | className="full"
|
117 | id="searchBox"
|
118 | open={this.state.shouldBeOpen}
|
119 | loading={this.props.loading}
|
120 | onResultSelect={self.onSelectTypeahead}
|
121 | onSearchChange={self.onChangeQuery}
|
122 | results={filteredSearches}
|
123 | input={{fluid: true}}
|
124 | value={query}
|
125 | showNoResults={false}
|
126 | fluid={true}
|
127 | onKeyUp={self.onKeyUp}
|
128 | onBlur={self.onBlur}
|
129 | placeholder={this.props.placeholder}
|
130 | size="large"
|
131 | />
|
132 | );
|
133 | }
|
134 | }
|
135 |
|
136 | export {
|
137 | SearchBoxProps,
|
138 | SearchBoxState,
|
139 | SearchBox
|
140 | }; |
\ | No newline at end of file |