text: import React from 'react'
  import PropTypes from 'prop-types'
  import ReactAutosuggest from 'react-autosuggest'
  import { withStyles } from 'material-ui/styles'
  import Fuse from 'fuse.js'
  import renderInput from './lib/render-input'
  import renderSuggestion from './lib/render-suggestion'
  import renderSuggestionsContainer from './lib/render-suggestions-container'
  import JssProvider from 'react-jss/lib/JssProvider'
  import { create } from 'jss'
  import { createGenerateClassName, jssPreset } from 'material-ui/styles'
  
  const styles = theme => ({
  	container: {
  		flexGrow: 1,
  		position: 'relative',
  		height: 200
  	},
  	containerFitContent: {
  		width: 'fit-content'
  	},
  	suggestionsContainerOpen: {
  		position: 'absolute',
  		marginTop: theme.spacing.unit,
  		marginBottom: theme.spacing.unit * 3,
  		left: 0,
  		right: 0,
  		zIndex: 9
  	},
  	suggestion: {
  		display: 'block'
  	},
  	suggestionsList: {
  		margin: 0,
  		padding: 0,
  		listStyleType: 'none'
  	}
  })
  
  class Autosuggest extends React.Component {
  	constructor(props) {
  		super(props)
  		this.state = {
  			value: props.value,
  			suggestions: []
  		}
  		this.fuzzySearcher = new Fuse(
  			props.suggestions,
  			props.fuzzySearchOpts
  		)
  
  		this.handleSuggestionsFetchRequested = this.handleSuggestionsFetchRequested.bind(this)
  		this.handleSuggestionsClearRequested = this.handleSuggestionsClearRequested.bind(this)
  		this.handleChange = this.handleChange.bind(this)
  		this.handleBlur = this.handleBlur.bind(this)
  		this.getSuggestions = this.getSuggestions.bind(this)
  		this.getSuggestionValue = this.getSuggestionValue.bind(this)
  		this.renderSuggestion = props.renderSuggestion && typeof props.renderSuggestion === 'function' ? props.renderSuggestion : renderSuggestion.bind(this)
  		this.renderInput = props.renderInput && typeof props.renderInput === 'function' ? props.renderInput : renderInput.bind(this)
  		this.renderSuggestionsContainer = props.renderSuggestionsContainer && typeof props.renderSuggestionsContainer === 'function' ? props.renderSuggestionsContainer : renderSuggestionsContainer.bind(this)
  		this.handleSuggestionsChange = this.handleSuggestionsChange.bind(this)
  	}
  
  	get suggestionLimit() {
  		const { suggestionLimit, suggestions } = this.props
  		return suggestionLimit < suggestions.length ? suggestionLimit : suggestions.length
  	}
  
  	getSuggestions(value) {
  		return this.fuzzySearcher
  			.search(value)
  			.slice(0, this.suggestionLimit)
  	}
  
  	getSuggestionValue(suggestion) {
  		return suggestion.item[this.props.labelKey]
  	}
  
  	handleBlur() {
  		const { labelKey } = this.props
  		let value = this.state.value
  		if (this.props.selectClosestMatch) {
  			const suggestion = this.state.suggestions[0]
  			if (suggestion) {
  				const match = suggestion.matches.find(item => (item.key === labelKey))
  				value = match &&
  					match.hasOwnProperty('value') &&
  					suggestion.hasOwnProperty('item') &&
  					suggestion.item.hasOwnProperty(labelKey) ?
  					match.value :
  					value
  			}
  			this.setState({ value })
  			this.props.onChange(value)
  		}
  		if (typeof this.props.onBlur === 'function') {
  			this.props.onBlur(value)
  		}
  	}
  
  	handleSuggestionsChange() {
  		const { onSuggestionsChange } = this.props
  		if (typeof onSuggestionsChange === 'function') {
  			onSuggestionsChange(this.state.suggestions.slice(0, this.suggestionLimit))
  		}
  	}
  
  	handleSuggestionsFetchRequested({ value }) {
  		this.setState({
  			suggestions: this.getSuggestions(value)
  		}, this.handleSuggestionsChange())
  	}
  
  	handleSuggestionsClearRequested() {
  		this.setState({
  			suggestions: []
  		}, this.handleSuggestionsChange())
  	}
  
  	handleChange(event, { newValue }) {
  		this.setState({
  			value: newValue
  		})
  		this.props.onChange(newValue)
  	}
  
  	render() {
  		const { classes, fullWidth, productionPrefix } = this.props
  		if (!fullWidth) {
  			classes.container += ` ${classes.containerFitContent}`
  		}
  
  		const generateClassName = createGenerateClassName({
  			productionPrefix: productionPrefix
  		})
  		const jss = create(jssPreset())
  
  		return (
  			<JssProvider jss={jss} generateClassName={generateClassName}>
  				<ReactAutosuggest
  					theme={{
  						container: classes.container,
  						suggestionsContainerOpen: classes.suggestionsContainerOpen,
  						suggestionsList: classes.suggestionsList,
  						suggestion: classes.suggestion
  					}}
  					renderInputComponent={this.renderInput}
  					suggestions={this.state.suggestions}
  					onSuggestionsFetchRequested={
  						this.handleSuggestionsFetchRequested
  					}
  					onSuggestionsClearRequested={
  						this.handleSuggestionsClearRequested
  					}
  					renderSuggestionsContainer={this.renderSuggestionsContainer}
  					getSuggestionValue={this.getSuggestionValue}
  					renderSuggestion={this.renderSuggestion}
  					ref='foo'
  					inputProps={{
  						classes,
  						value: this.state.value,
  						onChange: this.handleChange,
  						onBlur: this.handleBlur,
  						label: this.props.label,
  						inputLabelProps: this.props.inputLabelProps,
  						fullWidth: this.props.fullWidth,
  						error: this.props.error,
  						helperText: this.props.helperText,
  						...this.props.inputProps
  					}}
  				/>
  			</JssProvider>
  		)
  	}
  }
  
  Autosuggest.defaultProps = {
  	selectClosestMatch: false,
  	suggestionLimit: 5,
  	error: false,
  	value: '',
  	labelKey: 'label',
  	renderSuggestionProps: {
  		highlight: true,
  		renderSecondaryMatches: true
  	},
  	fuzzySearchOpts: {
  		shouldSort: true,
  		includeMatches: true,
  		findAllMatches: false,
  		threshold: 0.6,
  		location: 0,
  		distance: 100,
  		maxPatternLength: 32,
  		minMatchCharLength: 1,
  		keys: [ 'label' ]
  	},
  	fullWidth: true,
  	productionPrefix: 'mui-autosuggest'
  }
  
  Autosuggest.propTypes = {
  	/**
  	 * A custom function for rendering the input component
  	 */
  	renderInput: PropTypes.func,
  	/**
  	 * A custom function for rendering an individual suggestion element
  	 */
  	renderSuggestion: PropTypes.func,
  	/**
  	 * A custom function for rendering the suggestion containing element
  	 */
  	renderSuggestionsContainer: PropTypes.func,
  	/**
  	 * The array of suggestions
  	 */
  	suggestions: PropTypes.array.isRequired,
  	labelKey: PropTypes.string.isRequired,
  	classes: PropTypes.object.isRequired,
  	/**
  	 * The function to call when the value is changed
  	 */
  	onChange: PropTypes.func.isRequired,
  	/**
  	 * The function to call when the input element blurs
  	 */
  	onBlur: PropTypes.func,
  	/**
  	 * Addition inputProps for the input component
  	 */
  	inputProps: PropTypes.object,
  	/**
  	 * The value of the input
  	 */
  	value: PropTypes.string,
  	/**
  	 * Additional props for the inputLabel
  	 */
  	inputLabelProps: PropTypes.object,
  	/**
  	 * Whether or not the input should be rendered at full width
  	 */
  	fullWidth: PropTypes.bool,
  	/**
  	 * Whether or not the input should have error stylings
  	 */
  	error: PropTypes.bool,
  	/**
  	 * The helper text of the input element
  	 */
  	helperText: PropTypes.string,
  	/**
  	 * Select the closest match onBlur
  	 */
  	selectClosestMatch: PropTypes.bool,
  	/**
  	 * A function to call when suggestions are changed
  	 */
  	onSuggestionsChange: PropTypes.func,
  	/**
  	 * @see http://fusejs.io/#live-demo
  	 */
  	fuzzySearchOpts: PropTypes.object.isRequired,
  	/**
  	 * The number of suggestions to render
  	 */
  	suggestionLimit: PropTypes.number,
  	/**
  	 * The label for the rendered component
  	 */
  	label: PropTypes.string,
  	/**
  	 * Props used by the `renderSuggestion` function
  	 */
  	renderSuggestionProps: PropTypes.object,
  	/**
  	 * The prefix for generated JSS classNames
  	 */
  	productionPrefix: PropTypes.string.isRequired
  }
  
  export default withStyles(styles, { withTheme: true })(Autosuggest)
  
  exports.defaultProps = Autosuggest.defaultProps
  
  exports.propTypes = Autosuggest.propTypes
  