UNPKG

instantjob-recruiter-client

Version:

a set of tools for creating an instantjob recruiter react client

145 lines (130 loc) 3.62 kB
import React, {Component} from 'react' import classNames from 'classnames/bind' import {MdSearch} from 'react-icons/lib/md' import styled from 'styled-components' import {tolerant_equal} from 'selectors/base' import {cancelable_timeout} from 'common/cancelable' import {color, input} from 'common/styles' import auto_bind from 'common/auto_bind' export default class SearchBar extends Component { constructor(props) { super(props) this.state = { query: "", results: [], } auto_bind(this) this.fuse = this.props.make_fuse() } static defaultProps = { on_query_change: () => {}, simple: false, extend: true, placeholder: "Recherche", make_fuse: () => null, items: [], default_results: [], onFocus: () => null, onBlur: () => null, } set_items(items) { this.fuse.set(items) } set_query(query = "") { if (this.mounted) { this.set_should_verify_results() this.setState((state) => ({...state, query})) } } verify_results() { const {query} = this.state const {default_results, on_query_change} = this.props const results = query == "" ? default_results : this.fuse.search(query) const results_changed = !tolerant_equal(results, this.previous.results) if (!tolerant_equal(query, this.previous.query) || results_changed) { if (results_changed) { this.setState({results}) } on_query_change(query, results) } } componentDidUpdate() { if (this.should_verify_results) { this.verify_results() this.should_verify_results = false } } componentDidMount() { this.mounted = true this.set_items(this.props.items) this.previous = {query: ''} this.verify_results() } set_should_verify_results() { this.previous = {...this.state} this.should_verify_results = true } componentWillReceiveProps(props) { const {items, default_results} = this.props if (!tolerant_equal(props.items, items)) { this.set_items(props.items) this.set_should_verify_results() } if (!tolerant_equal(props.default_results, default_results) && this.state.query == "") { this.set_should_verify_results() } } shouldComponentUpdate(props, state) { return state !== this.state || !tolerant_equal(props.items, this.props.items) || !tolerant_equal(props.default_results, this.props.default_results) || props.className !== this.props.className || props.placeholder !== this.props.placeholder } componentWillUnmount() { this.mounted = false } focus() { this.input.focus() } render() { const {className} = this.props return ( <Container className={className}> <Icon> <MdSearch /> </Icon> <Input innerRef={(input) => this.input = input} type="text" placeholder={this.props.placeholder} value={this.state.query} onChange={({target: {value: query}}) => this.set_query(query)} onFocus={(event) => { if (this.state.query != "") { let input = event.target setTimeout(() => input.select(), 100) } this.props.onFocus() }} onBlur={this.props.onBlur} /> </Container> ) } } const Container = styled.div` display: flex; align-items: center; border-bottom: solid 2px ${color('black', 'pale')}; ` const Icon = styled.div` color: ${color('black', 'bright')}; font-size: 20px; padding: 5px; flex-shrink: 0; ` const Input = styled.input` ${input} flex: 1; `