index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import React, { PureComponent } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { Input, Icon, AutoComplete } from 'antd';
  4. import classNames from 'classnames';
  5. import Debounce from 'lodash-decorators/debounce';
  6. import Bind from 'lodash-decorators/bind';
  7. import styles from './index.less';
  8. export default class HeaderSearch extends PureComponent {
  9. static propTypes = {
  10. className: PropTypes.string,
  11. placeholder: PropTypes.string,
  12. onSearch: PropTypes.func,
  13. onPressEnter: PropTypes.func,
  14. defaultActiveFirstOption: PropTypes.bool,
  15. dataSource: PropTypes.array,
  16. defaultOpen: PropTypes.bool,
  17. };
  18. static defaultProps = {
  19. defaultActiveFirstOption: false,
  20. onPressEnter: () => {},
  21. onSearch: () => {},
  22. className: '',
  23. placeholder: '',
  24. dataSource: [],
  25. defaultOpen: false,
  26. };
  27. constructor(props) {
  28. super(props);
  29. this.state = {
  30. searchMode: props.defaultOpen,
  31. value: '',
  32. };
  33. }
  34. componentWillUnmount() {
  35. clearTimeout(this.timeout);
  36. }
  37. onKeyDown = e => {
  38. if (e.key === 'Enter') {
  39. const { onPressEnter } = this.props;
  40. const { value } = this.state;
  41. this.timeout = setTimeout(() => {
  42. onPressEnter(value); // Fix duplicate onPressEnter
  43. }, 0);
  44. }
  45. };
  46. onChange = value => {
  47. const { onChange } = this.props;
  48. this.setState({ value });
  49. if (onChange) {
  50. onChange(value);
  51. }
  52. };
  53. enterSearchMode = () => {
  54. this.setState({ searchMode: true }, () => {
  55. const { searchMode } = this.state;
  56. if (searchMode) {
  57. this.input.focus();
  58. }
  59. });
  60. };
  61. leaveSearchMode = () => {
  62. this.setState({
  63. searchMode: false,
  64. value: '',
  65. });
  66. };
  67. // NOTE: 不能小于500,如果长按某键,第一次触发auto repeat的间隔是500ms,小于500会导致触发2次
  68. @Bind()
  69. @Debounce(500, {
  70. leading: true,
  71. trailing: false,
  72. })
  73. debouncePressEnter() {
  74. const { onPressEnter } = this.props;
  75. const { value } = this.state;
  76. onPressEnter(value);
  77. }
  78. render() {
  79. const { className, placeholder, ...restProps } = this.props;
  80. const { searchMode, value } = this.state;
  81. delete restProps.defaultOpen; // for rc-select not affected
  82. const inputClass = classNames(styles.input, {
  83. [styles.show]: searchMode,
  84. });
  85. return (
  86. <span className={classNames(className, styles.headerSearch)} onClick={this.enterSearchMode}>
  87. <Icon type="search" key="Icon" />
  88. <AutoComplete
  89. key="AutoComplete"
  90. {...restProps}
  91. className={inputClass}
  92. value={value}
  93. onChange={this.onChange}
  94. >
  95. <Input
  96. ref={node => {
  97. this.input = node;
  98. }}
  99. aria-label={placeholder}
  100. placeholder={placeholder}
  101. onKeyDown={this.onKeyDown}
  102. onBlur={this.leaveSearchMode}
  103. />
  104. </AutoComplete>
  105. </span>
  106. );
  107. }
  108. }