import * as React from 'react'; import {debounce as db, filter, isArray, isEmpty, isEqual, keys, remove, template, templateSettings, trim, trimStart} from 'lodash'; import OutsideClickHandler from 'react-outside-click-handler'; import classNames from 'classnames'; import FormComponent from '../FormComponent'; import {getId, searchDataFetch,} from '../function'; import RenderHtml from '../renderFunction'; import PropsTypes from './types'; import * as JsSearch from 'js-search'; import Result from '../Result' import InputDropdown from "../InputDropdown"; let jsoptions = new JsSearch.Search('id'); templateSettings.interpolate = /{{([\s\S]+?)}}/g; interface State extends PropsTypes { focus: boolean, uuid: string, listData: any[], selectedData: any[], isActiveComponent: boolean, inputClear: boolean, value:string } function addDocumentsForSearch(data:any) { if (data && data.data && isArray(data.data) && data.data.length) { keys(data.data[0]).forEach(c => { jsoptions.addIndex(c) }); data.data.forEach((k:any) => { jsoptions.addDocuments([k]) }) } } function setDocumentIndex(data:any) { if (data && data.length) { keys(data[0]).forEach(c => { jsoptions.addIndex(c) }); jsoptions.addDocuments(data) } } export default class Input extends FormComponent { public state: State; private input = React.createRef(); constructor(props: PropsTypes, {}) { super(props); const uuid = getId(props.id, this.defaultId); const {options} = this.props; if (options) { jsoptions = new JsSearch.Search(this.getDisplayItem('displayValue')); } addDocumentsForSearch(options); this.state = { focus: false, listData: [], selectedData: [], uuid: uuid, value: '', autoFocus: false, inputClear: false, isActiveComponent: false, ...props, }; this.debounce = db(this.debounce, 0); } async componentDidMount() { await this.setSelectedData(); const {autoFocus} = this.state; if (autoFocus) { await this.focus(); } this.validate(this.getInputData()['value']); this.props.element && this.props.element(this.input); } setSelectedData() { const {options} = this.props; if (options && !isEmpty(options) && options.selected) { if (options.selected && isArray(options.selected) && options.selected.length) { this.setState({ selectedData: this.getDisplayItem('selected'), listData: [] },() => { this.setInputValue(); }) } else { this.dataSelectItem(this.getDisplayItem('selected')) } } } inputClear() { this.setState({ inputClear: true }) } focus() { const {selectedData, value} = this.state; const {options} = this.props; this.input.current && this.input.current.focus(); this.setState({ focus: true, listData: this.getDisplayItem('data') ? this.getDisplayItem('data') : selectedData, value: options && !isEmpty(options) ? '' : value, isActiveComponent: true }) } debounce(val: string) { const {selectedData} = this.state; const {options} = this.props; if (options && !isEmpty(options)) { if (options.remote && !isEmpty(options.remote)) { let url: any = options && template(options.remote); url = url({key: val}); searchDataFetch(url, val, (callback: any) => { setDocumentIndex(callback.data); this.setState({ listData: val ? callback.data : selectedData, loading: callback.loading }) }) } if (options.data && !isEmpty(options.data)) { let filterData: any[] = []; filterData = jsoptions.search(val); this.setState({ listData: trim(val) ? filterData : options.data }); } } } dataOnReady() { this.props.onChange && this.props.onChange(this.getInputData()['output']) } handleChange(e: any) { let inputValue: string = e.target.value; this.setState({ value: inputValue }, () => { this.debounce(inputValue); this.validate(this.getInputData()['value']); }) } handleBlur = () => { this.props.onBlur && this.props.onBlur(this.getInputData()['output']) }; handleClick = () => { this.props.onClick && this.props.onClick() }; handlePress = (e: any) => { const {value, listData} = this.state; const {addTag} = this.props; if (e.key === 'Enter') { if (addTag && !listData.length) { if(addTag && trim(value)) { this.dataSelectItem({ [this.getDisplayItem('displayField')]: value, [this.getDisplayItem('displayValue')]: Number(String(Math.random()).split('.')[1]), }); this.inputClear() } } e.preventDefault(); } this.props.onKeyPress && this.props.onKeyPress(e) }; handleDown = (e: any) => { this.props.onKeyDown && this.props.onKeyDown(e) }; setInputValue() { const {inputClear} = this.state; let val: any = this.getInputData()['value']; let iClear:boolean = false; val = inputClear ? '' : this.getInputData()['value']; iClear= false; this.setState({ value: val, inputClear: iClear }, () => { this.validate(this.getInputData()['value']); this.dataOnReady() }) } async dataSelectItem(val: any) { const {selectedData, value} = this.state; const {options, multiple, openAfterAddTag} = this.props; let afterData: any = {}; let tempselectedData: any[] = selectedData; await (() => { if (options && !isEmpty(options)) { if (multiple) { if (filter(tempselectedData, k => isEqual(val, k)).length > 0) { remove(tempselectedData, item => isEqual(val, item)); } else { tempselectedData.push(val) } let ldata:any = {} if (openAfterAddTag) { ldata = { listData: this.getDisplayItem('data') } } afterData = { selectedData: tempselectedData, value: !selectedData.length ? '' : value, ...ldata } } else { tempselectedData = []; val && tempselectedData.push(val); afterData = { selectedData: tempselectedData, listData: [] } } } })(); this.setState({ ...afterData }, () => { this.setInputValue(); this.dataOnReady() }) } getInputData() { const {selectedData, value} = this.state; let result: Object = {}; let output: any = null; let str: string | undefined = value; if (selectedData && selectedData.length) { if (selectedData.length === 1) { str = selectedData[0][this.getDisplayItem('displayField')] } else { str = ''; selectedData.forEach((item: any) => { if (item) { str = str + ', ' + item[this.getDisplayItem('displayField')] } }); str = trimStart(str, ' ,'); } } else { str = ''; } output = selectedData; result = { value: str, output }; return result } async removeTag(val: any) { const {selectedData, value} = this.state; let tempselectedData: any[] = selectedData; if (val) { await remove(tempselectedData, item => isEqual(val, item)); this.setState({ selectedData: tempselectedData, value: !selectedData.length ? '' : value }, () => { this.setInputValue() }) } } removeAll() { this.setState({ selectedData: [], listData: [], value: '' }, () => { this.setInputValue() }) } outsideClick() { const {isActiveComponent} = this.state; if (isActiveComponent) { this.setState({ focus: false, listData: [], isActiveComponent: false, }, () => { this.setInputValue() }) } } renderResult() { const {listData, selectedData, value} = this.state; const {addTag, multiple, removeAfterSelect} = this.props; if (listData && listData.length) { return this.removeTag(item)} onRemoveAll={() => this.removeAll()} onSelectItem={(val:any) => this.dataSelectItem(val)} /> } return null } renderInputDropdown() { const {listData} = this.state; if (listData && listData.length) { return {this.renderResult()} } return null } public render(): JSX.Element { const {value, listData, uuid} = this.state; const {label, icon, disabled, loading, color, rounded, customStyle, infoText, noBorder, noRadius} = this.props; const uiClass = classNames(`krax-input ${this.size()} is-${color || 'default'}`, { 'is-rounded': rounded, 'is-danger': this.error(), 'is-focused': this.error(), 'is-bottom-radius-none': listData.length, 'no-border': noBorder, 'no-radius': noRadius, }), containerClass = classNames(`krax-control is-expanded ${this.size()}`, { 'has-icons-left': this.iconLeft(), 'has-icons-right': this.iconRight(), 'is-loading': loading, 'is-data': value }), fieldClass = classNames(`krax-field ${customStyle || ''}`, { 'has-addons': label, }), captionClass = classNames('caption-text-ui', { 'is-data': value }); return ( { this.outsideClick() }}>
this.focus()}>
{RenderHtml.renderLabel(label, 'left', this.size())}
this.handleChange(val)} onBlur={() => this.handleBlur()} onClick={() => this.handleClick()} onKeyPress={(e) => {this.handlePress(e)}} onKeyDown={(e) => this.handleDown(e)} spellCheck={false} disabled={disabled} readOnly={this.readOnly()} ref={this.input} tabIndex={0} autoCorrect={'off'} />
{this.getCaption()}
{/*{this.renderResult()}*/} {this.renderInputDropdown()} {RenderHtml.renderIcon(icon, 'left', this.size())} {!loading ? RenderHtml.renderIcon(icon, 'right', this.size()) : null}
{RenderHtml.renderError(this.error())} {isEmpty(this.error()) ?
{infoText}
: null}
); } getCaption() { const {selectedData, value} = this.state; const {multiple, caption} = this.props; if (multiple && selectedData.length && value) { return `${selectedData.length} öğe seçildi` } if (multiple && selectedData.length && !value) { return 'ara..' } return caption } getDisplayItem(type: string) { const {options} = this.props; if (options && options[type] && !isEmpty(options[type])) { return options && options[type]; } return false } }