react-jam-ui
Version:
React JAM UI components
176 lines (151 loc) • 4.66 kB
JavaScript
import React from 'react'
import classNames from 'classnames'
import Input from '../Input'
import './styles.styl'
export default class Suggest extends React.Component {
constructor(props) {
super(props);
this.state = {
value: props.value ? props.value : '',
showList: false,
clickInProcess: false,
focus: props.focus
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.value && (!this.state.value || nextProps.value !== this.state.value)) {
this.setState({
value: nextProps.value
})
}
}
onSuggestListMouseUp = el => {
const template = this.props.inputLabel || this.props.label
const str = this.parseTemplate(template, el)
this.setState({
value: str,
showList: false,
clickInProcess: false,
focus: false
});
if (this.props.onSelect) this.props.onSelect(el);
}
onChangeCapture = e => {
const value = e.target.value;
this.setState({
value
});
if (this.props.onChange) this.props.onChange(e);
}
onBlurCapture = () => {
const template = this.props.inputLabel || this.props.label
let value = this.state.value;
const str = this.parseTemplate(template, this.props.data[0])
if (
this.props.onSelect &&
this.props.data.length == 1 &&
value &&
value.toLowerCase() == str.toLowerCase()
) {
this.props.onSelect(this.props.data[0]);
value = this.props.data[0];
}
this.setState({
showList: false,
focus: false
})
if (this.props.onBlur && !this.state.clickInProcess) this.props.onBlur( value )
}
onFocusCapture = () => {
this.setState({
showList: true,
focus: true
})
}
onSuggestListMouseDown = () => {
this.setState({
clickInProcess: true
})
}
getObjectValueByString = (obj, path) => {
return path.split('.').reduce( (prev, key) => {
return prev ? prev[key] : undefined
}, obj || self)
}
parseTemplate = (template, obj) => template.replace(/\$\{.+?\}/g, match => this.getObjectValueByString(obj, match.slice(2, -1).trim()) || match)
render() {
const {
className,
size,
variant,
value,
onFocus,
onChange,
onBlur,
onSelect,
data,
label,
inputLabel,
...rest
} = this.props;
const classes = classNames(
'suggest',
size,
className,
{
'suggest-default': !variant,
[`suggest-${variant}`]: variant,
'value': this.state.value,
'focus': this.state.focus
}
);
return <div
className={ classes }
onBlur={ this.onBlurCapture }
onFocus={ this.onFocusCapture }
tabIndex='0'
>
<Input
variant={ variant }
size={ size }
value={ this.state.value }
onChange={ this.onChangeCapture }
autoComplete='off'
{ ... rest }
/>
<div className={'suggest-list' + (data.length > 0 && this.state.showList ? '' : ' hide')}>
{
data.map( row => <div
key={`suggest-${this.props.name}-${ this.getObjectValueByString(row, this.props.id) }`}
onMouseDown={ this.onSuggestListMouseDown }
onMouseUp={ () => { this.onSuggestListMouseUp(row) } }
className='suggest-item'
>{ this.parseTemplate(label, row) }</div>)
}
</div>
</div>
}
}
/**
* TODO: Возможность HTML в template
* TODO: Required field and validation
*/
/*
<Suggest
variant='material'
name='INN'
placeholder='ИНН'
value={ formBasic.INN }
data={ this.props.suggest }
inputLabel='${data.inn}'
label='${data.name.short_with_opf} (${data.inn}/${data.ogrn})'
id='data.hid'
onKeyUp={ this.onSuggestCompanies }
onSelect={ this.onSelectSuggestCompany }
onBlur={ this.onBlurSuggestCompany }
mask={{
name: 'number'
}}
maxLength='12'
/>
*/