Repository: ant-design/ant-design-mobile
Pull request #6780 (2024-11-11 06:25:05)

feat(PasscodeInput): add inputMode props
#6736 
添加 inputMode 属性, 支持唤起原生英文键盘

github-actions[bot]: [<img width="500" alt="Prepare preview" src="https://user-images.githubusercontent.com/5378891/72351368-2c979e00-371b-11ea-9652-eb4e825d745e.gif">](https://preview-6780-ant-design-mobile.surge.sh)
<!-- AUTO_PREVIEW_HOOK -->
<!-- AUTO_PREVIEW_HOOK -->

Patch:
diff --git a/src/components/passcode-input/index.en.md b/src/components/passcode-input/index.en.md
index 85154b6e3..b91fbfc36 100644
--- a/src/components/passcode-input/index.en.md
+++ b/src/components/passcode-input/index.en.md
@@ -16,22 +16,23 @@ Input for password, captcha and verification code.
 
 ### Props
 
-| Name | Description | Type | Default |
-| --- | --- | --- | --- |
-| caret | Whether to show the caret | `boolean` | `true` |
-| className | ClassName of passcode | `string` | - |
-| defaultValue | The initial passcode content | `string` | - |
-| error | Whether to show the error style | `boolean` | `false` |
-| keyboard | The virtual keyboard component. If not set, it will use the native keyboard. | `NumberKeyboard` | - |
-| length | Length of passcode | `number` | `6` |
-| onBlur | Emitted when passcode is blurred | `() => void` | - |
-| onChange | Emitted when user input | `(value: string) => void` | - |
-| onFill | Emitted when passcode is filled | `() => void` | - |
-| onFocus | Emitted when passcode is focused | `() => void` | - |
-| plain | Whether to show the plain text | `boolean` | `false` |
-| seperated | Whether to make the cells seperated | `boolean` | `false` |
-| style | Style of passcode | `CSSProperties` | - |
-| value | The passcode content value | `string` | - |
+| Name | Description | Type | Default | Version |
+| --- | --- | --- | --- | --- |
+| caret | Whether to show the caret | `boolean` | `true` |  |
+| className | ClassName of passcode | `string` | - |  |
+| defaultValue | The initial passcode content | `string` | - |  |
+| error | Whether to show the error style | `boolean` | `false` |  |
+| keyboard | The virtual keyboard component. If not set, it will use the native keyboard. | `NumberKeyboard` | - |  |
+| inputMode | The type of the input box, which changes the native keyboard type | `'numeric' \| 'text'` | `'numeric'` | 5.39.0 |
+| length | Length of passcode | `number` | `6` |  |
+| plain | Whether to show the plain text | `boolean` | `false` |  |
+| seperated | Whether to make the cells seperated | `boolean` | `false` |  |
+| style | Style of passcode | `CSSProperties` | - |  |
+| value | The passcode content value | `string` | - |  |
+| onBlur | Emitted when passcode is blurred | `() => void` | - |  |
+| onChange | Emitted when user input | `(value: string) => void` | - |  |
+| onFill | Emitted when passcode is filled | `() => void` | - |  |
+| onFocus | Emitted when passcode is focused | `() => void` | - |  |
 
 When `length` is not a positive number, replace it with the default value.
 
diff --git a/src/components/passcode-input/index.zh.md b/src/components/passcode-input/index.zh.md
index d22043e57..b6a2984f4 100644
--- a/src/components/passcode-input/index.zh.md
+++ b/src/components/passcode-input/index.zh.md
@@ -16,22 +16,23 @@
 
 ### 属性
 
-| 属性 | 说明 | 类型 | 默认值 |
-| --- | --- | --- | --- |
-| caret | 是否展示光标 | `boolean` | `true` |
-| className | 外层 className | `string` | - |
-| defaultValue | 非受控值 | `string` | - |
-| error | 是否有错 | `boolean` | `false` |
-| keyboard | 键盘组件，如不传，默认使用系统原生的键盘 | `NumberKeyboard` | - |
-| length | 输入框长度 | `number` | `6` |
-| onBlur | 失去焦点回调 | `() => void` | - |
-| onChange | 输入时回调 | `(value: string) => void` | - |
-| onFill | 填写完成回调 | `() => void` | - |
-| onFocus | 获取焦点回调 | `() => void` | - |
-| plain | 是否展示明文 | `boolean` | `false` |
-| seperated | 格子是否是彼此分离的 | `boolean` | `false` |
-| style | 外层 style | `CSSProperties` | - |
-| value | 受控值 | `string` | - |
+| 属性 | 说明 | 类型 | 默认值 | 版本 |
+| --- | --- | --- | --- | --- |
+| caret | 是否展示光标 | `boolean` | `true` |  |
+| className | 外层 className | `string` | - |  |
+| defaultValue | 非受控值 | `string` | - |  |
+| error | 是否有错 | `boolean` | `false` |  |
+| keyboard | 键盘组件，如不传，默认使用系统原生的键盘 | `NumberKeyboard` | - |  |
+| inputMode | 输入框类型, 改变原生键盘类型 | `'numeric' \| 'text'` | `'numeric'` | 5.39.0 |
+| length | 输入框长度 | `number` | `6` |  |
+| plain | 是否展示明文 | `boolean` | `false` |  |
+| seperated | 格子是否是彼此分离的 | `boolean` | `false` |  |
+| style | 外层 style | `CSSProperties` | - |  |
+| value | 受控值 | `string` | - |  |
+| onBlur | 失去焦点回调 | `() => void` | - |  |
+| onChange | 输入时回调 | `(value: string) => void` | - |  |
+| onFill | 填写完成回调 | `() => void` | - |  |
+| onFocus | 获取焦点回调 | `() => void` | - |  |
 
 当 `length` 为非正数时以默认值为准。
 
diff --git a/src/components/passcode-input/passcode-input.tsx b/src/components/passcode-input/passcode-input.tsx
index 142907d92..ebbb2d461 100644
--- a/src/components/passcode-input/passcode-input.tsx
+++ b/src/components/passcode-input/passcode-input.tsx
@@ -1,31 +1,32 @@
+import classNames from 'classnames'
+import type { ReactElement } from 'react'
 import React, {
-  useState,
-  useEffect,
-  useRef,
   forwardRef,
+  useEffect,
   useImperativeHandle,
+  useRef,
+  useState,
 } from 'react'
-import type { ReactElement } from 'react'
-import { mergeProps } from '../../utils/with-default-props'
-import { NativeProps, withNativeProps } from '../../utils/native-props'
-import type { NumberKeyboardProps } from '../number-keyboard'
-import classNames from 'classnames'
 import { bound } from '../../utils/bound'
+import { NativeProps, withNativeProps } from '../../utils/native-props'
 import { usePropsValue } from '../../utils/use-props-value'
+import { mergeProps } from '../../utils/with-default-props'
 import { useConfig } from '../config-provider'
+import type { NumberKeyboardProps } from '../number-keyboard'
 
 export type PasscodeInputProps = {
   value?: string
   defaultValue?: string
-  onChange?: (val: string) => void
   length?: number
   plain?: boolean
   error?: boolean
   caret?: boolean
   seperated?: boolean
+  keyboard?: ReactElement<NumberKeyboardProps>
+  inputMode?: 'numeric' | 'text'
   onBlur?: () => void
   onFocus?: () => void
-  keyboard?: ReactElement<NumberKeyboardProps>
+  onChange?: (val: string) => void
   onFill?: (val: string) => void
 } & NativeProps<
   | '--cell-gap'
@@ -49,6 +50,7 @@ const defaultProps = {
   error: false,
   seperated: false,
   caret: true,
+  inputMode: 'numeric',
 }
 
 export const PasscodeInput = forwardRef<PasscodeInputRef, PasscodeInputProps>(
@@ -161,7 +163,7 @@ export const PasscodeInput = forwardRef<PasscodeInputRef, PasscodeInputProps>(
               value={value}
               type='text'
               pattern='[0-9]*'
-              inputMode='numeric'
+              inputMode={props.inputMode}
               onChange={e => {
                 setValue(e.target.value.slice(0, props.length))
               }}


Test patch:
diff --git a/src/components/passcode-input/tests/passcode-input.test.tsx b/src/components/passcode-input/tests/passcode-input.test.tsx
index 4562541f3..233e9fb55 100644
--- a/src/components/passcode-input/tests/passcode-input.test.tsx
+++ b/src/components/passcode-input/tests/passcode-input.test.tsx
@@ -1,7 +1,7 @@
+import { NumberKeyboard } from 'antd-mobile'
 import React, { createRef } from 'react'
-import { render, screen, fireEvent, userEvent, act } from 'testing'
+import { act, fireEvent, render, screen, userEvent } from 'testing'
 import PasscodeInput, { PasscodeInputRef } from '..'
-import { NumberKeyboard } from 'antd-mobile'
 
 const classPrefix = 'adm-passcode-input'
 const cellClassPrefix = 'adm-passcode-input-cell'
@@ -120,4 +120,14 @@ describe('PasscodeInput', () => {
     })
     expect(input).not.toHaveClass(`${classPrefix}-focused`)
   })
+
+  test('inputMode', () => {
+    const { container } = render(<PasscodeInput />)
+    const input = container.querySelector('input')
+    expect(input).toHaveAttribute('inputMode', 'numeric')
+
+    const { container: container2 } = render(<PasscodeInput inputMode='text' />)
+    const input2 = container2.querySelector('input')
+    expect(input2).toHaveAttribute('inputMode', 'text')
+  })
 })