diff --git a/src/components/input/input.tsx b/src/components/input/input.tsx index 94d8dfdc78..4ee8f987ec 100644 --- a/src/components/input/input.tsx +++ b/src/components/input/input.tsx @@ -4,10 +4,10 @@ import { CloseCircleFill } from 'antd-mobile-icons' import { NativeProps, withNativeProps } from '../../utils/native-props' import { mergeProps } from '../../utils/with-default-props' import classNames from 'classnames' -import { useIsomorphicLayoutEffect } from 'ahooks' import { bound } from '../../utils/bound' import { isIOS } from '../../utils/validate' import { useConfig } from '../config-provider' +import useInputHandleKeyDown from './useInputHandleKeyDown' const classPrefix = `adm-input` @@ -45,6 +45,7 @@ export type InputProps = Pick< | 'placeholder' | 'readOnly' | 'disabled' + | 'enterKeyHint' > & { value?: string defaultValue?: string @@ -53,14 +54,6 @@ export type InputProps = Pick< onlyShowClearWhenFocus?: boolean onClear?: () => void onEnterPress?: (e: React.KeyboardEvent) => void - enterKeyHint?: - | 'enter' - | 'done' - | 'go' - | 'next' - | 'previous' - | 'search' - | 'send' min?: number max?: number } & NativeProps< @@ -87,6 +80,12 @@ export const Input = forwardRef((p, ref) => { const compositionStartRef = useRef(false) const nativeInputRef = useRef(null) const { locale } = useConfig() + const handleKeydown = useInputHandleKeyDown({ + onEnterPress: props.onEnterPress, + onKeyDown: props.onKeyDown, + nativeInputRef, + enterKeyHint: props.enterKeyHint, + }) useImperativeHandle(ref, () => ({ clear: () => { @@ -103,21 +102,6 @@ export const Input = forwardRef((p, ref) => { }, })) - const handleKeydown = (e: React.KeyboardEvent) => { - if (props.onEnterPress && (e.code === 'Enter' || e.keyCode === 13)) { - props.onEnterPress(e) - } - props.onKeyDown?.(e) - } - - useIsomorphicLayoutEffect(() => { - if (!props.enterKeyHint) return - nativeInputRef.current?.setAttribute('enterkeyhint', props.enterKeyHint) - return () => { - nativeInputRef.current?.removeAttribute('enterkeyhint') - } - }, [props.enterKeyHint]) - function checkValue() { let nextValue = value if (props.type === 'number') { diff --git a/src/components/input/useInputHandleKeyDown.ts b/src/components/input/useInputHandleKeyDown.ts new file mode 100644 index 0000000000..bef4590938 --- /dev/null +++ b/src/components/input/useInputHandleKeyDown.ts @@ -0,0 +1,37 @@ +import { useIsomorphicLayoutEffect } from 'ahooks' + +interface InputHandleKeyDownType { + onEnterPress?: (e: React.KeyboardEvent) => void + onKeyDown?: (e: React.KeyboardEvent) => void + enterKeyHint?: React.InputHTMLAttributes['enterKeyHint'] + nativeInputRef: React.RefObject +} + +export default function useInputHandleKeyDown< + T extends HTMLInputElement | HTMLTextAreaElement, +>({ + onEnterPress, + onKeyDown, + nativeInputRef, + enterKeyHint, +}: InputHandleKeyDownType) { + const handleKeydown = (e: React.KeyboardEvent) => { + if (onEnterPress && (e.code === 'Enter' || e.keyCode === 13)) { + onEnterPress(e) + } + onKeyDown?.(e) + } + + useIsomorphicLayoutEffect(() => { + const ele = nativeInputRef.current + + if (!enterKeyHint || !ele) return + + ele.setAttribute('enterkeyhint', enterKeyHint) + return () => { + ele.removeAttribute('enterkeyhint') + } + }, [enterKeyHint]) + + return handleKeydown +} diff --git a/src/components/text-area/tests/text-area.test.tsx b/src/components/text-area/tests/text-area.test.tsx index d5aba7ff61..7c9490798c 100644 --- a/src/components/text-area/tests/text-area.test.tsx +++ b/src/components/text-area/tests/text-area.test.tsx @@ -142,4 +142,27 @@ describe('TextArea', () => { const textarea = getByRole('textbox') expect(textarea).toHaveAttribute('rows', '1') }) + + test('should works with `onEnterPress`', async () => { + const onEnterPress = jest.fn() + const { getByRole } = render( +