apps/docs/content/docs/cn/react/migration/(components)/input-otp.mdx
在 v2 中,InputOtp 根据 length prop 自动渲染插槽:
import { InputOtp } from "@heroui/react";
export default function App() {
return <InputOtp length={4} />;
}
在 v3 中,InputOTP 改为复合组件,需要手动声明插槽:
import { InputOTP } from "@heroui/react";
export default function App() {
return (
<InputOTP maxLength={4}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
</InputOTP.Group>
</InputOTP>
);
}
v2: 单个组件,自动渲染各个分段
v3: 复合组件:InputOTP.Group、InputOTP.Slot、InputOTP.Separator
| v2 prop | v3 位置 | 说明 |
|---|---|---|
length | InputOTP | 已重命名为 maxLength |
allowedKeys | InputOTP | 已重命名为 pattern(正则表达式) |
onValueChange | InputOTP | 改用 onChange |
description、errorMessage | - | 通过外部 Description / FieldError 处理 |
variant | InputOTP | 简化为仅 primary | secondary |
color、size、radius | - | 已移除(请改用 Tailwind CSS) |
classNames | - | 改在各子组件上使用 className |
| - | textAlign | 新增 prop:插槽内的文本对齐('left' | 'center' | 'right') |
| - | inputMode | 新增 prop:移动端的虚拟键盘类型(默认 'numeric') |
| - | placeholder | 新增 prop:空插槽的占位符文本 |
| - | pasteTransformer | 新增 prop:转换粘贴的文本(例如去掉连字符) |
<Tabs items={["v2", "v3"]}> <Tab value="v2"> ```tsx import { useState } from "react";
const [value, setValue] = useState("");
<InputOtp length={4} value={value} onValueChange={setValue} />
```
const [value, setValue] = useState("");
<InputOTP maxLength={4} value={value} onChange={setValue}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
</InputOTP.Group>
</InputOTP>
```
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <InputOtp allowedKeys="^[a-z]*$" length={4} />
</Tab>
<Tab value="v3">
```tsx
import { REGEXP_ONLY_CHARS } from "@heroui/react";
<InputOTP maxLength={4} pattern={REGEXP_ONLY_CHARS}>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
<InputOTP.Slot index={3} />
</InputOTP.Group>
</InputOTP>
```
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <InputOtp description="Enter the code sent to your email" length={4} /> <InputOtp errorMessage="Invalid code" isInvalid length={4} />
</Tab>
<Tab value="v3">
tsx import { Description, FieldError } from "@heroui/react"; <div className="flex flex-col gap-2"> <InputOTP maxLength={4}> <InputOTP.Group> <InputOTP.Slot index={0} /> <InputOTP.Slot index={1} /> <InputOTP.Slot index={2} /> <InputOTP.Slot index={3} /> </InputOTP.Group> </InputOTP> <Description>Enter the code sent to your email</Description> </div> <div className="flex flex-col gap-2"> <InputOTP isInvalid maxLength={4}> <InputOTP.Group> <InputOTP.Slot index={0} /> <InputOTP.Slot index={1} /> <InputOTP.Slot index={2} /> <InputOTP.Slot index={3} /> </InputOTP.Group> </InputOTP> <FieldError>Invalid code</FieldError> </div>
</Tab>
</Tabs>
<Tabs items={["v2", "v3"]}>
<Tab value="v2">
tsx <InputOtp length={6} onComplete={(value) => console.log("Complete:", value)} />
</Tab>
<Tab value="v3">
tsx <InputOTP maxLength={6} onComplete={(value) => console.log("Complete:", value)} > <InputOTP.Group> <InputOTP.Slot index={0} /> <InputOTP.Slot index={1} /> <InputOTP.Slot index={2} /> </InputOTP.Group> <InputOTP.Separator /> <InputOTP.Group> <InputOTP.Slot index={3} /> <InputOTP.Slot index={4} /> <InputOTP.Slot index={5} /> </InputOTP.Group> </InputOTP>
</Tab>
</Tabs>
v3 InputOTP 遵循以下结构:
InputOTP (Root)
├── InputOTP.Group
│ ├── InputOTP.Slot (index={0})
│ ├── InputOTP.Slot (index={1})
│ └── ...
├── InputOTP.Separator (optional)
└── InputOTP.Group (optional, for grouping)
└── InputOTP.Slot (index={...})
v3 引入了几个 v2 中没有的 prop:
textAlign:控制插槽内的文本对齐('left' | 'center' | 'right',默认 'left')inputMode:设置移动端虚拟键盘类型('numeric' | 'text' | 'decimal' | 'tel' | 'search' | 'email' | 'url',默认 'numeric')placeholder:设置空插槽的占位符文本pasteTransformer:(text: string) => string 类型的函数,用于转换粘贴的文本(例如从粘贴的代码中移除连字符)<InputOTP
maxLength={6}
inputMode="numeric"
textAlign="center"
placeholder="-"
pasteTransformer={(text) => text.replace(/-/g, "")}
>
<InputOTP.Group>
<InputOTP.Slot index={0} />
<InputOTP.Slot index={1} />
<InputOTP.Slot index={2} />
</InputOTP.Group>
<InputOTP.Separator />
<InputOTP.Group>
<InputOTP.Slot index={3} />
<InputOTP.Slot index={4} />
<InputOTP.Slot index={5} />
</InputOTP.Group>
</InputOTP>
为方便使用,HeroUI 从 input-otp 库再导出了几个常用的正则模式:
import { REGEXP_ONLY_DIGITS, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS_AND_CHARS } from "@heroui/react";
// Use with the pattern prop
<InputOTP pattern={REGEXP_ONLY_DIGITS} maxLength={6}>
</InputOTP>
REGEXP_ONLY_DIGITS —— 仅限数字字符(0-9)REGEXP_ONLY_CHARS —— 仅限字母字符(a-z、A-Z)REGEXP_ONLY_DIGITS_AND_CHARS —— 字母数字字符(0-9、a-z、A-Z)InputOTP.Group 与 InputOTP.Slot 手动声明插槽Description 组件variant="primary" 与 variant="secondary"className proptextAlign、inputMode、placeholder 与 pasteTransformerREGEXP_ONLY_DIGITS、REGEXP_ONLY_CHARS、REGEXP_ONLY_DIGITS_AND_CHARS 作为 pattern 的取值