ProComponents, templates & AI tooling
HeroUI
27.7k

InputOTP

InputOTP 从 HeroUI v2 到 v3 的迁移指南。

完整的 API 参考、样式指南与高级示例请参阅 v3 InputOTP 文档。本指南只关注从 HeroUI v2 的迁移。

结构变化

在 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>
  );
}

主要变化

1. 组件结构

v2: 单个组件,自动渲染各个分段
v3: 复合组件:InputOTP.GroupInputOTP.SlotInputOTP.Separator

2. Prop 变更

v2 propv3 位置说明
lengthInputOTP已重命名为 maxLength
allowedKeysInputOTP已重命名为 pattern(正则表达式)
onValueChangeInputOTP改用 onChange
descriptionerrorMessage-通过外部 Description / FieldError 处理
variantInputOTP简化为仅 primary | secondary
colorsizeradius-已移除(请改用 Tailwind CSS)
classNames-改在各子组件上使用 className
-textAlign新增 prop:插槽内的文本对齐('left' | 'center' | 'right'
-inputMode新增 prop:移动端的虚拟键盘类型(默认 'numeric'
-placeholder新增 prop:空插槽的占位符文本
-pasteTransformer新增 prop:转换粘贴的文本(例如去掉连字符)

迁移示例

受控 InputOTP

import { useState } from "react";

const [value, setValue] = useState("");

<InputOtp length={4} value={value} onValueChange={setValue} />
import { useState } from "react";

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>

使用 allowedKeys / pattern

<InputOtp allowedKeys="^[a-z]*$" length={4} />
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>

表单校验

{/* With description */}
<InputOtp description="Enter the code sent to your email" length={4} />

{/* With error message */}
<InputOtp errorMessage="Invalid code" isInvalid length={4} />
import { Description, FieldError } from "@heroui/react";

{/* With description */}
<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>

{/* With error message */}
<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>

使用 onComplete 回调

<InputOtp
  length={6}
  onComplete={(value) => console.log("Complete:", value)}
/>
<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>

组件结构

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 中的新增 prop

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)

总结

  1. 组件结构:必须用 InputOTP.GroupInputOTP.Slot 手动声明插槽
  2. length → maxLength:prop 重命名
  3. allowedKeys → pattern:prop 重命名,改为接收正则表达式
  4. onValueChange → onChange:事件处理函数重命名
  5. 移除 description:改用独立的 Description 组件
  6. 移除 errorMessage:改用独立的错误展示组件
  7. 简化变体:v3 仅支持 variant="primary"variant="secondary"
  8. 移除 color:请用 Tailwind CSS 类设置样式
  9. 移除 size:请用 Tailwind CSS 类设置样式
  10. 移除 radius:请用 Tailwind CSS 类设置样式
  11. 移除 classNames:改在各子组件上使用 className prop
  12. 新增 prop:v3 新增了 textAligninputModeplaceholderpasteTransformer
  13. 导出的正则模式:可使用 REGEXP_ONLY_DIGITSREGEXP_ONLY_CHARSREGEXP_ONLY_DIGITS_AND_CHARS 作为 pattern 的取值

本页目录