emoji-mart
Version:
Customizable Slack-like emoji picker for React
119 lines (110 loc) • 2.94 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { search as icons } from '../svgs';
import NimbleEmojiIndex from '../utils/emoji-index/nimble-emoji-index';
import { throttleIdleTask } from '../utils/index';
let id = 0;
export default class Search extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
icon: icons.search,
isSearching: false,
id: ++id
};
this.data = props.data;
this.emojiIndex = new NimbleEmojiIndex(this.data);
this.setRef = this.setRef.bind(this);
this.clear = this.clear.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this); // throttle keyboard input so that typing isn't delayed
this.handleChange = throttleIdleTask(this.handleChange.bind(this));
}
componentDidMount() {
// in some cases (e.g. preact) the input may already be pre-populated
// this.input is undefined in Jest tests
if (this.input && this.input.value) {
this.search(this.input.value);
}
}
search(value) {
if (value == '') this.setState({
icon: icons.search,
isSearching: false
});else this.setState({
icon: icons.delete,
isSearching: true
});
this.props.onSearch(this.emojiIndex.search(value, {
emojisToShowFilter: this.props.emojisToShowFilter,
maxResults: this.props.maxResults,
include: this.props.include,
exclude: this.props.exclude,
custom: this.props.custom
}));
}
clear() {
if (this.input.value == '') return;
this.input.value = '';
this.input.focus();
this.search('');
}
handleChange() {
if (this.input) {
this.search(this.input.value);
}
}
handleKeyUp(e) {
if (e.keyCode === 13) {
this.clear();
}
}
setRef(c) {
this.input = c;
}
render() {
const {
i18n,
autoFocus
} = this.props;
const {
icon,
isSearching,
id
} = this.state;
const inputId = `emoji-mart-search-${id}`;
return React.createElement("section", {
className: "emoji-mart-search",
"aria-label": i18n.search
}, React.createElement("input", {
id: inputId,
ref: this.setRef,
type: "search",
onChange: this.handleChange,
placeholder: i18n.search,
autoFocus: autoFocus
}), React.createElement("label", {
className: "emoji-mart-sr-only",
htmlFor: inputId
}, i18n.search), React.createElement("button", {
className: "emoji-mart-search-icon",
onClick: this.clear,
onKeyUp: this.handleKeyUp,
"aria-label": i18n.clear,
disabled: !isSearching
}, icon()));
}
}
Search.propTypes
/* remove-proptypes */
= {
onSearch: PropTypes.func,
maxResults: PropTypes.number,
emojisToShowFilter: PropTypes.func,
autoFocus: PropTypes.bool
};
Search.defaultProps = {
onSearch: () => {},
maxResults: 75,
emojisToShowFilter: null,
autoFocus: false
};