UNPKG

react-autocomplete-select

Version:
372 lines (280 loc) 14.7 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _templateObject = _taggedTemplateLiteralLoose(['\n * {\n box-sizing: border-box;\n}\n\nbody {\n font: 16px Arial; \n backgroundColor : \'black\'\n}\n\n/*the container must be positioned relative:*/\n.autocomplete {\n position: relative;\n display: inline-block;\n width:300px;\n}\n\ninput {\n border: 1px solid transparent;\n background-color: #f1f1f1;\n padding: 10px;\n font-size: 16px;\n width: 100%;\n}\n\n\n\n/*Dropdown options container css*/\n.___optionsDiv___ {\n\n position: absolute;\n border: 1px solid #d4d4d4;\n border-bottom: none;\n border-top: none;\n z-index: 99;\n /*position the autocomplete items to be the same width as the container:*/\n top: 100%;\n left: 0;\n right: 0;\n}\n\n\n/*Dropdown options each div css*/\n.___optionsDiv___ div {\n padding: 10px;\n cursor: pointer;\n background-color: #fff; \n border-bottom: 1px solid #d4d4d4; \n}\n\n/*Dropdown options each div on hover css*/\n\n.___optionsDiv___ div:hover {\n background-color: #e9e9e9; \n}\n\n\n/*when navigating through the items using the arrow keys:*/\n.autocomplete-active {\n background-color: DodgerBlue !important; \n color: #ffffff; \n}\n\n ', '\n'], ['\n * {\n box-sizing: border-box;\n}\n\nbody {\n font: 16px Arial; \n backgroundColor : \'black\'\n}\n\n/*the container must be positioned relative:*/\n.autocomplete {\n position: relative;\n display: inline-block;\n width:300px;\n}\n\ninput {\n border: 1px solid transparent;\n background-color: #f1f1f1;\n padding: 10px;\n font-size: 16px;\n width: 100%;\n}\n\n\n\n/*Dropdown options container css*/\n.___optionsDiv___ {\n\n position: absolute;\n border: 1px solid #d4d4d4;\n border-bottom: none;\n border-top: none;\n z-index: 99;\n /*position the autocomplete items to be the same width as the container:*/\n top: 100%;\n left: 0;\n right: 0;\n}\n\n\n/*Dropdown options each div css*/\n.___optionsDiv___ div {\n padding: 10px;\n cursor: pointer;\n background-color: #fff; \n border-bottom: 1px solid #d4d4d4; \n}\n\n/*Dropdown options each div on hover css*/\n\n.___optionsDiv___ div:hover {\n background-color: #e9e9e9; \n}\n\n\n/*when navigating through the items using the arrow keys:*/\n.autocomplete-active {\n background-color: DodgerBlue !important; \n color: #ffffff; \n}\n\n ', '\n']); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } import React, { Component, Fragment } from 'react'; import OptionsParent from './OptionsParent'; import Options from './Options'; import styled, { createGlobalStyle } from 'styled-components'; import PropTypes from 'prop-types'; import axios from 'axios'; var GlobalStyle = createGlobalStyle(_templateObject, function (props) { return props.globalStyle; }); export default Object.assign(function (_Component) { _inherits(_class2, _Component); function _class2() { var _temp, _this, _ret; _classCallCheck(this, _class2); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.state = { inputValue: "", currentActiveValue: "", itemsData: [], searchData: [], searchPattern: "containsString", placeholder: "Search", selectOnBlur: false, axiosConfig: false, onChange: false, onSelect: false, maxOptionsLimit: 10, getItemValue: false, inputRef: false, searchEnabled: false, optionsJSX: false, inputJSX: false, defaultInputValue: false }, _this.currentFocus = -1, _this.inputRef = React.createRef(), _this.optionRefs = [], _this.setRef = function (ref) { _this.optionRefs.push(ref); }, _this.closeAllItems = function () { for (var _len2 = arguments.length, methodsToBeCalled = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { methodsToBeCalled[_key2 - 1] = arguments[_key2]; } var withObject = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; setTimeout(function () { _this.setState(_extends({}, _this.state, withObject, { searchData: [] }), function () { methodsToBeCalled.forEach(function (methodToCall) { return methodToCall(); }); }); }, 1); _this.optionRefs = []; _this.currentFocus = -1; }, _this.addClickEventListener = function () { for (var i = 0; i < _this.optionRefs.length; i++) { _this.optionRefs[i] && _this.optionRefs[i].addEventListener('mousedown', function (e) { _this.closeAllItems({ inputValue: e.target.textContent, currentActiveValue: e.target.textContent }, _this.onSelect); }); } }, _this.setInputDefaultVal = function () { if (_this.props.defaultInputValue && !_this.state.currentActiveValue) setTimeout(function () { return _this.setState({ currentActiveValue: _this.props.defaultInputValue, inputValue: _this.props.defaultInputValue }); }, 10); }, _this.onBlur = function () { if (_this.state.selectOnBlur) _this.closeAllItems({ inputValue: _this.state.currentActiveValue }, _this.onSelect, _this.setInputDefaultVal);else setTimeout(function () { _this.closeAllItems({ currentActiveValue: _this.state.inputValue }, _this.onChange, _this.setInputDefaultVal); }, 1); }, _this.onFocus = function (elem) { var event = new Event('input', { 'bubbles': true, 'cancelable': true }); elem.target.dispatchEvent(event); }, _this.addActive = function () { /*remove null values*/ _this.optionRefs = _this.optionRefs.filter(function (val) { return val ? val : false; }); /*start by removing the "active" class on all items:*/ var currentActiveValue = void 0; _this.removeActive(); if (_this.currentFocus > _this.optionRefs.length) _this.currentFocus = 0; if (_this.currentFocus < -1) _this.currentFocus = _this.optionRefs.length - 1; if (_this.currentFocus == -1 || _this.currentFocus === _this.optionRefs.length) currentActiveValue = _this.state.inputValue;else currentActiveValue = _this.optionRefs[_this.currentFocus] && _this.optionRefs[_this.currentFocus].textContent || _this.state.inputValue; _this.setState(_extends({}, _this.state, { currentActiveValue: currentActiveValue }), function () { /* now calling onChange method */ _this.onChange(); }); if (_this.optionRefs[_this.currentFocus]) { _this.optionRefs[_this.currentFocus].classList.add("autocomplete-active"); } }, _this.onChange = function () { if (_this.state.onChange) _this.state.onChange(_this.state.currentActiveValue); }, _this.onSelect = function () { if (_this.state.onSelect) _this.state.onSelect(_this.state.inputValue); _this.onChange(); }, _this.removeActive = function () { /*a function to remove the "active" class from all autocomplete items:*/ for (var i = 0; i < _this.optionRefs.length; i++) { _this.optionRefs[i] && _this.optionRefs[i].classList.remove("autocomplete-active"); } }, _this.isSearched = function (value, inpValue) { if (!value) return; value = value.toString().toUpperCase(); inpValue = inpValue.toString().toUpperCase(); if (_this.state.searchPattern === 'containsString' && value.indexOf(inpValue) > -1) return value; if (_this.state.searchPattern === 'containsLetter') { var letters = inpValue.split(''); var response = value; for (var i = 0; i < letters.length; i++) { if (!(value.indexOf(letters[i]) > -1)) { response = false; break; } } return response; } if (_this.state.searchPattern === 'startsWith' && value.substr(0, inpValue.length) == inpValue) return value; if (_this.state.searchPattern === 'endsWith' && value.substr(-inpValue.length) == inpValue) return value; }, _this.makeAxiosRequest = function (inputValue) { var axiosConfig = _this.state.axiosConfig && _this.state.axiosConfig(inputValue); var self = _this; if (axiosConfig instanceof Object) { axios(axiosConfig).then(function (res) { _this.setData(res.data, inputValue); }).catch(function (err) { console.log(err, ' error occured.'); }); return true; } else return false; }, _this.onInput = function () { var inp = _this.inputRef.current; var storeInState = [], i = void 0, val = inp.value; /*close any already open item of autocompleted values*/ _this.closeAllItems({ inputValue: inp.value, currentActiveValue: inp.value }, _this.onChange); if (!val || !_this.makeAxiosRequest(val) && _this.state.itemsData.length === 0) return; /*for each item in the array...*/ _this.setData(_this.state.itemsData, val); }, _this.setData = function (dataToMakeSearch, inpValue, type) { var storeInState = []; if (type === 'axios' && !_this.state.searchEnabled) ;else storeInState = _this.makeLocalSearch(dataToMakeSearch, inpValue); setTimeout(function () { _this.setState(_extends({}, _this.state, { searchData: storeInState }), function () { _this.addClickEventListener(); }); }, 1); }, _this.makeLocalSearch = function (dataToMakeSearch, inpValue) { var storeInState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; for (var i = 0; i < dataToMakeSearch.length; i++) { /*check if the item starts with the same letters as the text field value:*/ if (_this.isSearched(_this.state.getItemValue(dataToMakeSearch[i]), inpValue)) { if (storeInState.length < _this.state.maxOptionsLimit) { storeInState.push(dataToMakeSearch[i]); } } } return storeInState; }, _this.onKeyDown = function (e) { var inp = _this.inputRef.current; // let {currentFocus} = this.state; if (_this.optionRefs.length === 0) return; if (e.keyCode == 40) { /*If the arrow DOWN key is pressed, increase the currentFocus variable:*/ if (_this.state.searchData.length > 0) { _this.currentFocus++; _this.addActive(); } } else if (e.keyCode == 38) { //up /*If the arrow UP key is pressed, decrease the currentFocus variable:*/ if (_this.state.searchData.length > 0) { _this.currentFocus--; _this.addActive(); } } else if (e.keyCode == 13) { /*If the ENTER key is pressed, prevent the form from being submitted,*/ e.preventDefault(); if (_this.currentFocus > -1 && _this.optionRefs.length > 0 && _this.optionRefs[_this.currentFocus]) { /*and simulate a click on the "active" item:*/ var event = new Event('mousedown'); _this.optionRefs[_this.currentFocus].dispatchEvent(event); } else _this.closeAllItems(_extends({}, _this.state), _this.onSelect); } }, _this.handleChange = function (e) { var value = e.target.value; _this.setState(_extends({}, _this.state, { inputValue: value, currentActiveValue: value })); }, _this.inputJSX = function () { var obj = { ref: _this.props.inputRef || _this.inputRef, onBlur: _this.onBlur, onFocus: _this.onFocus, onInput: _this.onInput, value: _this.state.currentActiveValue, onChange: _this.handleChange, onKeyDown: _this.onKeyDown, type: 'text', placeholder: _this.state.placeholder }; if (_this.state.inputJSX) return _this.state.inputJSX(obj); return React.createElement('input', obj); }, _temp), _possibleConstructorReturn(_this, _ret); } _class2.prototype.componentDidMount = function componentDidMount() { if (this.props.inputRef) this.inputRef = this.props.inputRef; this.setInputDefaultVal(); }; _class2.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) { var propsToBeState = ['searchPattern', 'data', 'placeholder', 'axiosConfig', 'selectOnBlur', 'onChange', 'onSelect', 'getItemValue', 'itemsData', 'inputRef', 'searchEnabled', 'optionsJSX', 'inputJSX']; var stateObj = {}; Object.entries(props).forEach(function (_ref) { var key = _ref[0], val = _ref[1]; if (propsToBeState.indexOf(key) > -1) stateObj[key] = val; }); return stateObj; }; /* handling user level methods*/ _class2.prototype.render = function render() { var _this2 = this; return React.createElement( Fragment, null, React.createElement( 'form', { autoComplete: 'off' }, React.createElement( 'div', { className: 'autocomplete' }, this.inputJSX(), React.createElement( OptionsParent, null, this.state.searchData.map(function (val, key) { return key <= _this2.state.maxOptionsLimit ? React.createElement(Options, { ref: _this2.setRef, JSX: _this2.state.optionsJSX || function (value) { return value; }, key: key, value: _this2.state.getItemValue(val) }) : null; }) ) ) ), React.createElement(GlobalStyle, { globalStyle: this.props.globalStyle }) ); }; return _class2; }(Component), { propTypes: { searchPattern: PropTypes.oneOf(['startsWith', 'endsWith', 'containsString', 'containsLetter']), getItemValue: PropTypes.func.isRequired, itemsData: PropTypes.array.isRequired, inputJSX: PropTypes.func, optionsJSX: PropTypes.func, maxOptionsLimit: PropTypes.number, searchEnabled: PropTypes.bool, selectOnBlur: PropTypes.bool, inputRef: PropTypes.object, onChange: PropTypes.func, onSelect: PropTypes.func, axiosConfig: PropTypes.func, placeholder: PropTypes.string, defaultInputValue: PropTypes.string } });