You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.2 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { connect } from 'react-redux';
  4. import { defineMessages, injectIntl } from 'react-intl';
  5. import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists';
  6. import classNames from 'classnames';
  7. import Icon from 'mastodon/components/icon';
  8. const messages = defineMessages({
  9. search: { id: 'lists.search', defaultMessage: 'Search among people you follow' },
  10. });
  11. const mapStateToProps = state => ({
  12. value: state.getIn(['listEditor', 'suggestions', 'value']),
  13. });
  14. const mapDispatchToProps = dispatch => ({
  15. onSubmit: value => dispatch(fetchListSuggestions(value)),
  16. onClear: () => dispatch(clearListSuggestions()),
  17. onChange: value => dispatch(changeListSuggestions(value)),
  18. });
  19. class Search extends React.PureComponent {
  20. static propTypes = {
  21. intl: PropTypes.object.isRequired,
  22. value: PropTypes.string.isRequired,
  23. onChange: PropTypes.func.isRequired,
  24. onSubmit: PropTypes.func.isRequired,
  25. onClear: PropTypes.func.isRequired,
  26. };
  27. handleChange = e => {
  28. this.props.onChange(e.target.value);
  29. };
  30. handleKeyUp = e => {
  31. if (e.keyCode === 13) {
  32. this.props.onSubmit(this.props.value);
  33. }
  34. };
  35. handleClear = () => {
  36. this.props.onClear();
  37. };
  38. render () {
  39. const { value, intl } = this.props;
  40. const hasValue = value.length > 0;
  41. return (
  42. <div className='list-editor__search search'>
  43. <label>
  44. <span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
  45. <input
  46. className='search__input'
  47. type='text'
  48. value={value}
  49. onChange={this.handleChange}
  50. onKeyUp={this.handleKeyUp}
  51. placeholder={intl.formatMessage(messages.search)}
  52. />
  53. </label>
  54. <div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
  55. <Icon id='search' className={classNames({ active: !hasValue })} />
  56. <Icon id='times-circle' aria-label={intl.formatMessage(messages.search)} className={classNames({ active: hasValue })} />
  57. </div>
  58. </div>
  59. );
  60. }
  61. }
  62. export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(Search));