index.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { SearchOutlined } from '@ant-design/icons';
  2. import { AutoComplete, Input } from 'antd';
  3. import useMergeValue from 'use-merge-value';
  4. import { AutoCompleteProps } from 'antd/es/auto-complete';
  5. import React, { useRef } from 'react';
  6. import classNames from 'classnames';
  7. import styles from './index.less';
  8. export interface HeaderSearchProps {
  9. onSearch?: (value?: string) => void;
  10. onChange?: (value?: string) => void;
  11. onVisibleChange?: (b: boolean) => void;
  12. className?: string;
  13. placeholder?: string;
  14. options: AutoCompleteProps['options'];
  15. defaultOpen?: boolean;
  16. open?: boolean;
  17. defaultValue?: string;
  18. value?: string;
  19. }
  20. const HeaderSearch: React.FC<HeaderSearchProps> = (props) => {
  21. const {
  22. className,
  23. defaultValue,
  24. onVisibleChange,
  25. placeholder,
  26. open,
  27. defaultOpen,
  28. ...restProps
  29. } = props;
  30. const inputRef = useRef(null);
  31. const [value, setValue] = useMergeValue<string | undefined>(defaultValue, {
  32. value: props.value,
  33. onChange: props.onChange,
  34. });
  35. const [searchMode, setSearchMode] = useMergeValue(defaultOpen || false, {
  36. value: props.open,
  37. onChange: onVisibleChange,
  38. });
  39. const inputClass = classNames(styles.input, {
  40. [styles.show]: searchMode,
  41. });
  42. return (
  43. <div
  44. className={classNames(className, styles.headerSearch)}
  45. onClick={() => {
  46. setSearchMode(true);
  47. if (searchMode && inputRef.current) {
  48. (inputRef.current as any).focus();
  49. }
  50. }}
  51. onTransitionEnd={({ propertyName }) => {
  52. if (propertyName === 'width' && !searchMode) {
  53. if (onVisibleChange) {
  54. onVisibleChange(searchMode);
  55. }
  56. }
  57. }}
  58. >
  59. <SearchOutlined
  60. key="Icon"
  61. style={{
  62. cursor: 'pointer',
  63. }}
  64. />
  65. <AutoComplete
  66. key="AutoComplete"
  67. className={inputClass}
  68. value={value}
  69. options={restProps.options}
  70. onChange={setValue}
  71. >
  72. <Input
  73. size="small"
  74. ref={inputRef}
  75. defaultValue={defaultValue}
  76. aria-label={placeholder}
  77. placeholder={placeholder}
  78. onKeyDown={(e) => {
  79. if (e.key === 'Enter') {
  80. if (restProps.onSearch) {
  81. restProps.onSearch(value);
  82. }
  83. }
  84. }}
  85. onBlur={() => {
  86. setSearchMode(false);
  87. }}
  88. />
  89. </AutoComplete>
  90. </div>
  91. );
  92. };
  93. export default HeaderSearch;