import React, { useRef, useImperativeHandle } from "react"; import classNames from "classnames"; import { InputProps, Input } from "../input"; import { Button } from "../button"; import { useDefaultValue, ChangeContext } from "../form/controlled"; import { ScaleTransition } from "../transition"; import { useConfig } from "../_util/config-context"; import { forwardRefWithStatics } from "../_util/forward-ref-with-statics"; import { noop } from "../_util/noop"; import { KeyMap } from "../_util/key-map"; import { callBoth } from "../_util/call-both"; import { mergeRefs } from "../util"; export interface SearchBoxProps extends InputProps { /** * 是否为多行搜索模式 * * @default false */ multiline?: boolean; /** * 是否为简洁模式 * * @default false */ simple?: boolean; /** * 点击搜索或输入回车时回调 * 如果自行绑定了 `onKeydown` 处理方法,则该回调不再提供 */ onSearch?: (keyword?: string, context?: ChangeContext) => void; /** * 用户清空搜索时回调 * */ onClear?: () => void; /** * 搜索框尺寸 */ size?: "full" | "l" | "m" | "s"; /** * 显示帮助按钮 * * @default false * @since 2.2.2 */ showHelp?: boolean; /** * 帮助按钮点击回调 * * @since 2.2.2 */ onHelp?: (e: React.MouseEvent) => void; /** * 搜索框容器 ref * * *组件 `ref` 指向了内部输入框* * * @since 2.7.0 */ searchBoxRef?: React.Ref; } export const SearchBox = forwardRefWithStatics( function SearchBox(props: SearchBoxProps, ref: React.Ref) { const { classPrefix } = useConfig(); const { multiline, simple, onSearch = noop, onClear = noop, className, style, size, showHelp, disabled, onHelp = noop, searchBoxRef, ..._inputProps } = props; const inputBoxClassNames = classNames({ [`${classPrefix}-search`]: true, [`${classPrefix}-search--multi`]: multiline, [`${classPrefix}-search--simple`]: simple, [className]: className, }); const inputProps = useDefaultValue(_inputProps, ""); const composingRef = useRef(null); // 需要使用到 inputRef,同时向外部暴露 const inputRef = useRef(null); useImperativeHandle(ref, () => inputRef.current); return (
{ const { key, ctrlKey, metaKey } = event; if (key === KeyMap.Esc) { event.preventDefault(); inputProps.onChange("", { event }); onClear(); } // 回车处理 onSearch 逻辑 if (key !== KeyMap.Enter) { return; } // 多行模式下,要按下 ctrl 或者 command if (multiline && !metaKey && !ctrlKey) { return; } event.preventDefault(); if (!composingRef.current) { onSearch(event.currentTarget.value, { event }); } }} {...inputProps} onCompositionStart={callBoth(() => { composingRef.current = true; }, inputProps.onCompositionStart)} onCompositionEnd={callBoth(() => { composingRef.current = false; }, inputProps.onCompositionEnd)} ref={inputRef} />
); }, { defaultLabelAlign: "middle", } ); SearchBox.displayName = "SearchBox";