import * as React from "react"; import { QueryAccessor, SearchkitComponent, SearchkitComponentProps } from "../../../core" const defaults = require("lodash/defaults") const throttle = require("lodash/throttle") const assign = require("lodash/assign") const isUndefined = require("lodash/isUndefined") export interface SearchBoxProps extends SearchkitComponentProps { searchOnChange?:boolean searchThrottleTime?:number queryFields?:Array queryBuilder?:Function queryOptions?:any autofocus?:boolean id?: string mod?: string placeholder?: string prefixQueryFields?:Array prefixQueryOptions?:Object blurAction?:"search"|"restore" } export class SearchBox extends SearchkitComponent { accessor:QueryAccessor lastSearchMs:number throttledSearch: () => void static translations:any = { "searchbox.placeholder":"Search" } translations = SearchBox.translations static defaultProps = { id: 'q', mod: 'sk-search-box', searchThrottleTime:200, blurAction: "search" } static propTypes = defaults({ id:React.PropTypes.string, searchOnChange:React.PropTypes.bool, searchThrottleTime:React.PropTypes.number, queryBuilder:React.PropTypes.func, queryFields:React.PropTypes.arrayOf(React.PropTypes.string), autofocus:React.PropTypes.bool, queryOptions:React.PropTypes.object, prefixQueryFields:React.PropTypes.arrayOf(React.PropTypes.string), prefixQueryOptions:React.PropTypes.object, translations:SearchkitComponent.translationsPropType( SearchBox.translations ), mod: React.PropTypes.string, placeholder: React.PropTypes.string, blurAction: React.PropTypes.string }, SearchkitComponent.propTypes) constructor (props:SearchBoxProps) { super(props); this.state = { focused:false, input: undefined } this.lastSearchMs = 0 this.throttledSearch = throttle(()=> { this.searchQuery(this.accessor.getQueryString()) }, props.searchThrottleTime) } defineBEMBlocks() { return { container:this.props.mod }; } defineAccessor(){ const { id, prefixQueryFields, queryFields, queryBuilder, searchOnChange, queryOptions, prefixQueryOptions } = this.props return new QueryAccessor(id, { prefixQueryFields, prefixQueryOptions:assign({}, prefixQueryOptions), queryFields:queryFields || ["_all"], queryOptions:assign({}, queryOptions), queryBuilder, onQueryStateChange: () => { if (!this.unmounted && this.state.input){ this.setState({input: undefined}) } } }) } onSubmit(event) { event.preventDefault() this.searchQuery(this.getValue()) } searchQuery(query) { let shouldResetOtherState = false this.accessor.setQueryString(query, shouldResetOtherState ) let now = +new Date let newSearch = now - this.lastSearchMs <= 2000 this.lastSearchMs = now this.searchkit.performSearch(newSearch) } getValue(){ const { input } = this.state if (isUndefined(input)) { return this.getAccessorValue() } else { return input } } getAccessorValue(){ return (this.accessor.state.getValue() || "") + "" } onChange(e){ const query = e.target.value; if (this.props.searchOnChange) { this.accessor.setQueryString(query) this.throttledSearch() this.forceUpdate() } else { this.setState({ input: query }) } } setFocusState(focused:boolean) { if (!focused){ const { input } = this.state if (this.props.blurAction == "search" && !isUndefined(input) && input != this.getAccessorValue()){ this.searchQuery(input) } this.setState({ focused, input: undefined // Flush (should use accessor's state now) }) } else { this.setState({ focused }) } } render() { let block = this.bemBlocks.container return (
); } }