2018-08-25 11:15:40 +02:00
|
|
|
import React, { PureComponent, Fragment } from 'react'
|
2018-08-28 23:28:42 +02:00
|
|
|
import PropTypes from 'prop-types'
|
2018-08-25 11:15:40 +02:00
|
|
|
import Helmet from 'react-helmet'
|
2018-08-27 19:42:09 +02:00
|
|
|
import { CSSTransition } from 'react-transition-group'
|
2018-10-11 20:35:10 +02:00
|
|
|
import SearchInput from './SearchInput'
|
|
|
|
import SearchButton from './SearchButton'
|
|
|
|
import SearchResults from './SearchResults'
|
2018-08-28 23:28:42 +02:00
|
|
|
|
2018-08-25 11:15:40 +02:00
|
|
|
import styles from './Search.module.scss'
|
|
|
|
|
2018-09-06 19:23:34 +02:00
|
|
|
export default class Search extends PureComponent {
|
|
|
|
state = {
|
|
|
|
searchOpen: false,
|
|
|
|
query: '',
|
|
|
|
results: []
|
|
|
|
}
|
2018-08-25 11:15:40 +02:00
|
|
|
|
2018-09-06 19:23:34 +02:00
|
|
|
static propTypes = {
|
|
|
|
lng: PropTypes.string.isRequired
|
2018-08-25 11:15:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
toggleSearch = () => {
|
|
|
|
this.setState(prevState => ({
|
|
|
|
searchOpen: !prevState.searchOpen
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2018-08-28 23:28:42 +02:00
|
|
|
closeSearch = () => {
|
|
|
|
this.setState({
|
|
|
|
searchOpen: false,
|
|
|
|
query: '',
|
|
|
|
results: []
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-08-25 11:15:40 +02:00
|
|
|
isSearchOpen = () => this.state.searchOpen === true
|
|
|
|
|
2018-08-28 23:28:42 +02:00
|
|
|
getSearchResults(query) {
|
|
|
|
if (!query || !window.__LUNR__) return []
|
|
|
|
const lunrIndex = window.__LUNR__[this.props.lng]
|
|
|
|
const results = lunrIndex.index.search(query)
|
|
|
|
return results.map(({ ref }) => lunrIndex.store[ref])
|
|
|
|
}
|
|
|
|
|
|
|
|
search = event => {
|
|
|
|
const query = event.target.value
|
|
|
|
const results = this.getSearchResults(query)
|
|
|
|
this.setState({
|
|
|
|
results,
|
|
|
|
query
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-08-25 11:15:40 +02:00
|
|
|
render() {
|
2018-08-28 23:28:42 +02:00
|
|
|
const { searchOpen, query, results } = this.state
|
|
|
|
|
2018-08-25 11:15:40 +02:00
|
|
|
return (
|
|
|
|
<Fragment>
|
|
|
|
<Helmet>
|
|
|
|
<body className={this.isSearchOpen() ? 'has-search-open' : null} />
|
|
|
|
</Helmet>
|
|
|
|
|
2018-08-28 23:28:42 +02:00
|
|
|
<SearchButton onClick={this.toggleSearch} />
|
2018-08-25 11:15:40 +02:00
|
|
|
|
2018-08-28 23:28:42 +02:00
|
|
|
{searchOpen && (
|
2018-08-27 19:42:09 +02:00
|
|
|
<CSSTransition
|
2018-08-28 23:28:42 +02:00
|
|
|
appear={searchOpen}
|
|
|
|
in={searchOpen}
|
2018-08-27 19:42:09 +02:00
|
|
|
timeout={200}
|
|
|
|
classNames={styles}
|
|
|
|
>
|
|
|
|
<section className={styles.search}>
|
2018-08-28 23:28:42 +02:00
|
|
|
<SearchInput
|
|
|
|
value={query}
|
|
|
|
onChange={this.search}
|
|
|
|
onToggle={this.closeSearch}
|
2018-08-27 19:42:09 +02:00
|
|
|
/>
|
|
|
|
</section>
|
|
|
|
</CSSTransition>
|
2018-08-25 11:15:40 +02:00
|
|
|
)}
|
2018-08-28 23:28:42 +02:00
|
|
|
|
|
|
|
{query && (
|
|
|
|
<SearchResults results={results} onClose={this.closeSearch} />
|
|
|
|
)}
|
2018-08-25 11:15:40 +02:00
|
|
|
</Fragment>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|