The code powering m.abunchtell.com https://m.abunchtell.com
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.
 
 
 
 

134 lines
3.4 KiB

  1. import PureRenderMixin from 'react-addons-pure-render-mixin';
  2. import ImmutablePropTypes from 'react-immutable-proptypes';
  3. import Autosuggest from 'react-autosuggest';
  4. import AutosuggestAccountContainer from '../containers/autosuggest_account_container';
  5. import { debounce } from 'react-decoration';
  6. import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
  7. const messages = defineMessages({
  8. placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }
  9. });
  10. const getSuggestionValue = suggestion => suggestion.value;
  11. const renderSuggestion = suggestion => {
  12. if (suggestion.type === 'account') {
  13. return <AutosuggestAccountContainer id={suggestion.id} />;
  14. } else {
  15. return <span>#{suggestion.id}</span>
  16. }
  17. };
  18. const renderSectionTitle = section => (
  19. <strong><FormattedMessage id={`search.${section.title}`} defaultMessage={section.title} /></strong>
  20. );
  21. const getSectionSuggestions = section => section.items;
  22. const outerStyle = {
  23. padding: '10px',
  24. lineHeight: '20px',
  25. position: 'relative'
  26. };
  27. const inputStyle = {
  28. boxSizing: 'border-box',
  29. display: 'block',
  30. width: '100%',
  31. border: 'none',
  32. padding: '10px',
  33. paddingRight: '30px',
  34. fontFamily: 'inherit',
  35. background: '#282c37',
  36. color: '#9baec8',
  37. fontSize: '14px',
  38. margin: '0'
  39. };
  40. const iconStyle = {
  41. position: 'absolute',
  42. top: '18px',
  43. right: '20px',
  44. color: '#9baec8',
  45. fontSize: '18px',
  46. pointerEvents: 'none'
  47. };
  48. const Search = React.createClass({
  49. contextTypes: {
  50. router: React.PropTypes.object
  51. },
  52. propTypes: {
  53. suggestions: React.PropTypes.array.isRequired,
  54. value: React.PropTypes.string.isRequired,
  55. onChange: React.PropTypes.func.isRequired,
  56. onClear: React.PropTypes.func.isRequired,
  57. onFetch: React.PropTypes.func.isRequired,
  58. onReset: React.PropTypes.func.isRequired
  59. },
  60. mixins: [PureRenderMixin],
  61. onChange (_, { newValue }) {
  62. if (typeof newValue !== 'string') {
  63. return;
  64. }
  65. this.props.onChange(newValue);
  66. },
  67. onSuggestionsClearRequested () {
  68. this.props.onClear();
  69. },
  70. @debounce(500)
  71. onSuggestionsFetchRequested ({ value }) {
  72. value = value.replace('#', '');
  73. this.props.onFetch(value.trim());
  74. },
  75. onSuggestionSelected (_, { suggestion }) {
  76. if (suggestion.type === 'account') {
  77. this.context.router.push(`/accounts/${suggestion.id}`);
  78. } else {
  79. this.context.router.push(`/timelines/tag/${suggestion.id}`);
  80. }
  81. },
  82. render () {
  83. const inputProps = {
  84. placeholder: this.props.intl.formatMessage(messages.placeholder),
  85. value: this.props.value,
  86. onChange: this.onChange,
  87. style: inputStyle
  88. };
  89. return (
  90. <div style={outerStyle}>
  91. <Autosuggest
  92. multiSection={true}
  93. suggestions={this.props.suggestions}
  94. focusFirstSuggestion={true}
  95. focusInputOnSuggestionClick={false}
  96. alwaysRenderSuggestions={false}
  97. onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
  98. onSuggestionsClearRequested={this.onSuggestionsClearRequested}
  99. onSuggestionSelected={this.onSuggestionSelected}
  100. getSuggestionValue={getSuggestionValue}
  101. renderSuggestion={renderSuggestion}
  102. renderSectionTitle={renderSectionTitle}
  103. getSectionSuggestions={getSectionSuggestions}
  104. inputProps={inputProps}
  105. />
  106. <div style={iconStyle}><i className='fa fa-search' /></div>
  107. </div>
  108. );
  109. },
  110. });
  111. export default injectIntl(Search);