UNPKG

react-spatial

Version:

Components to build React map apps.

293 lines (257 loc) 8.82 kB
import React, { PureComponent } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import SearchInput from '../SearchInput'; import List from '../List'; var propTypes = { /** * Content for submit button. */ button: PropTypes.any, /** * Value of the input. */ value: PropTypes.string, /** * Placeholder of the input. */ placeholder: PropTypes.string, /** * Items to display on input change. */ items: PropTypes.array, /** * Items always display in suggestions list. */ defaultItems: PropTypes.array, /** * Function that render the title display on top the default items list. */ renderTitle: PropTypes.func, /** * Function that render an item. */ renderItem: PropTypes.func, /** * Function triggered on input change, focus, and on button click. */ onChange: PropTypes.func, /** * Function triggered on item selection and on click outside the autocomplete * element. */ onSelect: PropTypes.func, /** * Function triggered when the autocomplete component (input, buttons and list) get the focus. * element. */ onFocus: PropTypes.func, /** * Function triggered when the autocomplete component (input, buttons and list) loose the focus. * element. */ onBlur: PropTypes.func, /** * Get the key for each item used when react creates the list. */ getItemKey: PropTypes.func, /** * CSS class added to container. */ className: PropTypes.string, /** * CSS class added to container of the results list. */ classNameResults: PropTypes.string, }; var defaultProps = { button: 'submit', value: '', placeholder: '', items: [], defaultItems: [], renderTitle: function (t) { return t; }, renderItem: function (i) { return i; }, getItemKey: function (k) { return k; }, onBlur: function () {}, onChange: function () {}, onFocus: function () {}, onSelect: function () {}, className: 'tm-autocomplete', classNameResults: 'tm-autocomplete-results', }; /** * This component displays a search input with a list of suggestions. */ var Autocomplete = /*@__PURE__*/(function (PureComponent) { function Autocomplete(props) { PureComponent.call(this, props); this.state = { showList: false, refList: null, focus: false, }; this.onDocClick = this.onDocClick.bind(this); this.ref = null; this.refSearchInput = null; } if ( PureComponent ) Autocomplete.__proto__ = PureComponent; Autocomplete.prototype = Object.create( PureComponent && PureComponent.prototype ); Autocomplete.prototype.constructor = Autocomplete; Autocomplete.prototype.componentDidMount = function componentDidMount () { // Close the list when clicking outside the list or the input document.addEventListener('click', this.onDocClick); }; Autocomplete.prototype.componentDidUpdate = function componentDidUpdate (prevProps, prevState) { // Close the list when clicking outside the list or the input document.removeEventListener('click', this.onDocClick); document.addEventListener('click', this.onDocClick); // Trigger onFocus and onBlur event var ref = this.state; var focus = ref.focus; var ref$1 = this.props; var onBlur = ref$1.onBlur; var onFocus = ref$1.onFocus; if (prevState.focus && !focus) { onBlur(); } else if (!prevState.focus && focus) { onFocus(); } }; Autocomplete.prototype.componentWillUnmount = function componentWillUnmount () { document.removeEventListener('click', this.onDocClick); }; Autocomplete.prototype.onDocClick = function onDocClick (e) { // If the click comes from an element of Autocomplete, don't close the list. if (this.ref && this.ref.contains(e.target)) { return; } this.setState({ showList: false, focus: false }); }; Autocomplete.prototype.onChange = function onChange (evt, val) { var ref = this.props; var onChange = ref.onChange; this.setState({ showList: true, focus: true }); onChange(val); }; Autocomplete.prototype.onFocus = function onFocus () { this.setState({ showList: true, focus: true }); }; Autocomplete.prototype.onBlurInput = function onBlurInput (evt, lastKeyPress) { if (lastKeyPress && lastKeyPress.which !== 40) { this.setState({ showList: false, focus: false }); } }; Autocomplete.prototype.onKeyPress = function onKeyPress (evt) { var ref = this.state; var refList = ref.refList; var ref$1 = this.props; var items = ref$1.items; if (evt.which === 40 && refList && refList.querySelector('.tm-list-item')) { // Give focus to the first element of the results // eslint-disable-next-line react/no-find-dom-node refList.querySelector('.tm-list-item').focus(); } if (evt.which === 13 && refList && items.length) { this.onSelect(evt, items[0]); } }; Autocomplete.prototype.onKeyPressItem = function onKeyPressItem (evt) { if (evt.which !== 40 && evt.which !== 38) { return; } var delta = 1; if (evt.which === 38) { delta = -1; } var ref = this.state; var refList = ref.refList; var liFocused = document.activeElement; var lis = refList.querySelectorAll('.tm-list-item'); var idxItemFocused = Array.prototype.slice.call(lis).indexOf(liFocused); var nextIndex = idxItemFocused + delta; if (nextIndex < 0) { // Move focus to input search // eslint-disable-next-line react/no-find-dom-node ReactDOM.findDOMNode(this.refSearchInput) .querySelector('input') .focus(); nextIndex = lis.length - 1; return; } if (nextIndex === lis.length) { // Move focus to the beginning of the list nextIndex = 0; } lis[nextIndex].focus(); }; Autocomplete.prototype.onSelect = function onSelect (evt, item) { var ref = this.props; var onSelect = ref.onSelect; onSelect(item); this.setState({ showList: false, focus: false }); }; Autocomplete.prototype.render = function render () { var this$1 = this; var ref = this.props; var button = ref.button; var value = ref.value; var placeholder = ref.placeholder; var items = ref.items; var defaultItems = ref.defaultItems; var renderTitle = ref.renderTitle; var renderItem = ref.renderItem; var getItemKey = ref.getItemKey; var className = ref.className; var classNameResults = ref.classNameResults; var ref$1 = this.state; var showList = ref$1.showList; var refList = ref$1.refList; var display = !showList || (!items.length && !defaultItems.length) ? 'none' : null; var hr = items.length && defaultItems.length ? React.createElement( 'hr', null ) : null; return ( React.createElement( 'div', { className: className, ref: function (node) { this$1.ref = node; } }, React.createElement( SearchInput, { button: button, value: value, placeholder: placeholder, onChange: function (e, val) { return this$1.onChange(e, val); }, onFocus: function (e) { return this$1.onFocus(e); }, onKeyPress: function (e) { return this$1.onKeyPress(e); }, onBlurInput: function (e, keyPress) { return this$1.onBlurInput(e, keyPress); }, onClickSearchButton: function () { if (showList) { this$1.setState({ showList: false, focus: false }); } }, ref: function (node) { this$1.refSearchInput = node; } }), React.createElement( 'div', { ref: function (node) { if (node && !refList) { this$1.setState({ refList: node }); } }, style: display && { display: display, }, className: classNameResults }, React.createElement( List, { items: items, renderItem: function (item) { return renderItem(item); }, getItemKey: function (item) { return getItemKey(item); }, onSelect: function (e, item) { this$1.onSelect(e, item); }, onKeyDownItem: function (e) { this$1.onKeyPressItem(e); } }), hr, renderTitle(), React.createElement( List, { items: defaultItems, renderItem: function (item) { return renderItem(item); }, getItemKey: function (item) { return getItemKey(item); }, onSelect: function (e, item) { this$1.onSelect(e, item); }, onKeyDownItem: function (e) { this$1.onKeyPressItem(e); } }) ) ) ); }; return Autocomplete; }(PureComponent)); Autocomplete.propTypes = propTypes; Autocomplete.defaultProps = defaultProps; export default Autocomplete; //# sourceMappingURL=Autocomplete.js.map