react-spatial
Version:
Components to build React map apps.
293 lines (257 loc) • 8.82 kB
JavaScript
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