# Input OTP

InputOtp,
InputOtpGroup,
InputOtpSeparator,
InputOtpSlot,
REGEXP_ONLY_DIGITS_AND_CHARS,
} from "@/components/starwind/input-otp";

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
---

<InputOtp aria-label="Verification code" maxLength={6}>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <InputOtp aria-label="Verification code" maxLength={6}>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
        <InputOtpSlot index={4} />
        <InputOtpSlot index={5} />
      </InputOtpGroup>
    </InputOtp>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp aria-label="Verification code" :maxLength="6">
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Installation

```bash
npx starwind@latest add input-otp --framework astro
```
</DocsTabsContent>
```bash
npx starwind@latest add input-otp --framework react
```
</DocsTabsContent>
```bash
npx starwind@latest add input-otp --framework vue
```
</DocsTabsContent>
</DocsTabs>

## Usage

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
---

<InputOtp aria-label="Verification code" maxLength={6}>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <InputOtp aria-label="Verification code" maxLength={6}>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
        <InputOtpSlot index={4} />
        <InputOtpSlot index={5} />
      </InputOtpGroup>
    </InputOtp>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp aria-label="Verification code" :maxLength="6">
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Composition

Group slots and place separators between the groups:

```text
InputOtp
├── InputOtpGroup
│   ├── InputOtpSlot
│   ├── InputOtpSlot
│   └── InputOtpSlot
├── InputOtpSeparator
└── InputOtpGroup
    ├── InputOtpSlot
    ├── InputOtpSlot
    └── InputOtpSlot
```

## Behavior

Input OTP supports keyboard navigation, pasted values, and pattern validation for verification
codes and one-time passwords.

## With Separator

Use `InputOtpSeparator` to visually group slots, commonly used for phone verification codes or formatted inputs.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSeparator,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
---

<InputOtp aria-label="Verification code with separator" maxLength={6}>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
  </InputOtpGroup>
  <InputOtpSeparator />
  <InputOtpGroup>
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSeparator,
  InputOtpSlot,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <>
      <InputOtp aria-label="Verification code with separator" maxLength={6}>
        <InputOtpGroup>
          <InputOtpSlot index={0} />
          <InputOtpSlot index={1} />
          <InputOtpSlot index={2} />
        </InputOtpGroup>
        <InputOtpSeparator />
        <InputOtpGroup>
          <InputOtpSlot index={3} />
          <InputOtpSlot index={4} />
          <InputOtpSlot index={5} />
        </InputOtpGroup>
      </InputOtp>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSeparator,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp aria-label="Verification code with separator" :maxLength="6">
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
    </InputOtpGroup>
    <InputOtpSeparator />
    <InputOtpGroup>
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
  </div>
</FrameworkCodeSwitcher>

> **Info:** Name the `InputOtp` root rather than its individual slots; Runtime exposes the shared name on the
hidden input.

## Alphanumeric Pattern

Use the `pattern` prop with `REGEXP_ONLY_DIGITS_AND_CHARS` to allow both letters and numbers.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
  REGEXP_ONLY_DIGITS_AND_CHARS,
} from "@/components/starwind/input-otp";
---

<InputOtp
  aria-label="Alphanumeric verification code"
  maxLength={6}
  pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
  REGEXP_ONLY_DIGITS_AND_CHARS,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <>
      <InputOtp
        aria-label="Alphanumeric verification code"
        maxLength={6}
        pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
      >
        <InputOtpGroup>
          <InputOtpSlot index={0} />
          <InputOtpSlot index={1} />
          <InputOtpSlot index={2} />
          <InputOtpSlot index={3} />
          <InputOtpSlot index={4} />
          <InputOtpSlot index={5} />
        </InputOtpGroup>
      </InputOtp>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
  REGEXP_ONLY_DIGITS_AND_CHARS,
} from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp
    aria-label="Alphanumeric verification code"
    :maxLength="6"
    :pattern="REGEXP_ONLY_DIGITS_AND_CHARS"
  >
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
  </div>
</FrameworkCodeSwitcher>

> **Info:** Keep an explicit accessible name when the pattern changes what characters the shared input
accepts.

## Sizes

Set `size="sm"`, `size="md"` (the default), or `size="lg"` once on `InputOtp`. Every slot in the
code field inherits that physical visual scale; `InputOtpSlot` no longer accepts `size`.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
---

<div class="flex flex-col gap-6">
  <div class="space-y-2">
    <p class="text-muted-foreground text-sm">Small</p>
    <InputOtp size="sm" aria-label="Small verification code" maxLength={4}>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
      </InputOtpGroup>
    </InputOtp>
  </div>
  <div class="space-y-2">
    <p class="text-muted-foreground text-sm">Medium (default)</p>
    <InputOtp size="md" aria-label="Medium verification code" maxLength={4}>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
      </InputOtpGroup>
    </InputOtp>
  </div>
  <div class="space-y-2">
    <p class="text-muted-foreground text-sm">Large</p>
    <InputOtp size="lg" aria-label="Large verification code" maxLength={4}>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
      </InputOtpGroup>
    </InputOtp>
  </div>
</div>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <>
      <div className="flex flex-col gap-6">
        <div className="space-y-2">
          <p className="text-muted-foreground text-sm">Small</p>
          <InputOtp size="sm" aria-label="Small verification code" maxLength={4}>
            <InputOtpGroup>
              <InputOtpSlot index={0} />
              <InputOtpSlot index={1} />
              <InputOtpSlot index={2} />
              <InputOtpSlot index={3} />
            </InputOtpGroup>
          </InputOtp>
        </div>
        <div className="space-y-2">
          <p className="text-muted-foreground text-sm">Medium (default)</p>
          <InputOtp size="md" aria-label="Medium verification code" maxLength={4}>
            <InputOtpGroup>
              <InputOtpSlot index={0} />
              <InputOtpSlot index={1} />
              <InputOtpSlot index={2} />
              <InputOtpSlot index={3} />
            </InputOtpGroup>
          </InputOtp>
        </div>
        <div className="space-y-2">
          <p className="text-muted-foreground text-sm">Large</p>
          <InputOtp size="lg" aria-label="Large verification code" maxLength={4}>
            <InputOtpGroup>
              <InputOtpSlot index={0} />
              <InputOtpSlot index={1} />
              <InputOtpSlot index={2} />
              <InputOtpSlot index={3} />
            </InputOtpGroup>
          </InputOtp>
        </div>
      </div>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
</script>

<template>
  <div class="flex flex-col gap-6">
    <div class="space-y-2">
      <p class="text-muted-foreground text-sm">Small</p>
      <InputOtp size="sm" aria-label="Small verification code" :maxLength="4">
        <InputOtpGroup>
          <InputOtpSlot :index="0" />
          <InputOtpSlot :index="1" />
          <InputOtpSlot :index="2" />
          <InputOtpSlot :index="3" />
        </InputOtpGroup>
      </InputOtp>
    </div>
    <div class="space-y-2">
      <p class="text-muted-foreground text-sm">Medium (default)</p>
      <InputOtp size="md" aria-label="Medium verification code" :maxLength="4">
        <InputOtpGroup>
          <InputOtpSlot :index="0" />
          <InputOtpSlot :index="1" />
          <InputOtpSlot :index="2" />
          <InputOtpSlot :index="3" />
        </InputOtpGroup>
      </InputOtp>
    </div>
    <div class="space-y-2">
      <p class="text-muted-foreground text-sm">Large</p>
      <InputOtp size="lg" aria-label="Large verification code" :maxLength="4">
        <InputOtpGroup>
          <InputOtpSlot :index="0" />
          <InputOtpSlot :index="1" />
          <InputOtpSlot :index="2" />
          <InputOtpSlot :index="3" />
        </InputOtpGroup>
      </InputOtp>
    </div>
  </div>
</template>
```
  </div>
</FrameworkCodeSwitcher>

> **Info:** Size is visual, so each preview uses a distinct accessible name instead of relying on the nearby
size caption.

## Disabled

Use the `disabled` prop to prevent user interaction.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
---

<InputOtp aria-label="Verification code" maxLength={6} disabled>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>
```
  </div>
  <div slot="react">
```tsx
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";

export function Example() {
  return (
    <>
      <InputOtp aria-label="Verification code" maxLength={6} disabled>
        <InputOtpGroup>
          <InputOtpSlot index={0} />
          <InputOtpSlot index={1} />
          <InputOtpSlot index={2} />
          <InputOtpSlot index={3} />
          <InputOtpSlot index={4} />
          <InputOtpSlot index={5} />
        </InputOtpGroup>
      </InputOtp>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp aria-label="Verification code" :maxLength="6" disabled>
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
  </div>
</FrameworkCodeSwitcher>

> **Info:** Disabled controls still need an accessible name so assistive technology can identify them.

## Form Submission

The component integrates with native HTML forms using the `name` prop. The hidden input stores the complete OTP value.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
import {
  InputOtp,
  InputOtpGroup,
  InputOtpSlot,
} from "@/components/starwind/input-otp";
import { Label } from "@/components/starwind/label";
---

<form id="otp-demo-form" class="space-y-4">
  <div class="space-y-2">
    <Label for="otp-form">Verification Code</Label>
    <InputOtp id="otp-form" name="otp" maxLength={6} required>
      <InputOtpGroup>
        <InputOtpSlot index={0} />
        <InputOtpSlot index={1} />
        <InputOtpSlot index={2} />
        <InputOtpSlot index={3} />
        <InputOtpSlot index={4} />
        <InputOtpSlot index={5} />
      </InputOtpGroup>
    </InputOtp>
  </div>
  <Button type="submit">Submit Code</Button>
</form>
<div id="form-result" class="bg-muted mt-4 hidden rounded-md p-4 font-mono text-sm"></div>

<script>
  const form = document.getElementById("otp-demo-form") as HTMLFormElement;
  const resultDiv = document.getElementById("form-result");

  if (form && resultDiv) {
    form.addEventListener("submit", (e) => {
      e.preventDefault();
      const formData = new FormData(form);
      const otp = formData.get("otp");

      resultDiv.textContent = `Submitted OTP: ${otp}`;
      resultDiv.classList.remove("hidden");
    });
  }
</script>
```
  </div>
  <div slot="react">
```tsx
import type { FormEvent } from "react";
import { useState } from "react";
import { Button } from "@/components/starwind/button";
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
import { Label } from "@/components/starwind/label";

export function Example() {
  const [submittedOtp, setSubmittedOtp] = useState<string | null>(null);

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSubmittedOtp(String(new FormData(event.currentTarget).get("otp") ?? ""));
  }

  return (
    <>
      <form className="space-y-4" onSubmit={handleSubmit}>
        <div className="space-y-2">
          <Label htmlFor="otp-form">Verification Code</Label>
          <InputOtp id="otp-form" name="otp" maxLength={6} required>
            <InputOtpGroup>
              {Array.from({ length: 6 }, (_, index) => (
                <InputOtpSlot key={index} index={index} />
              ))}
            </InputOtpGroup>
          </InputOtp>
        </div>
        <Button type="submit">Submit Code</Button>
      </form>
      {submittedOtp !== null ? (
        <div className="bg-muted mt-4 rounded-md p-4 font-mono text-sm">
          Submitted OTP: {submittedOtp}
        </div>
      ) : null}
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
import { Label } from "@/components/starwind/label";
import { ref } from "vue";
const submitted = ref("");
function submit(event: Event) {
  const form = event.currentTarget as HTMLFormElement;
  submitted.value = `Submitted OTP: ${new FormData(form).get("otp")}`;
}
</script>

<template>
  <form @submit.prevent="submit" id="otp-demo-form" class="space-y-4">
    <div class="space-y-2">
      <Label for="otp-form">Verification Code</Label>
      <InputOtp id="otp-form" name="otp" :maxLength="6" required>
        <InputOtpGroup>
          <InputOtpSlot :index="0" />
          <InputOtpSlot :index="1" />
          <InputOtpSlot :index="2" />
          <InputOtpSlot :index="3" />
          <InputOtpSlot :index="4" />
          <InputOtpSlot :index="5" />
        </InputOtpGroup>
      </InputOtp>
    </div>
    <Button type="submit">Submit Code</Button>
  </form>
  <div v-if="submitted" class="bg-muted mt-4 rounded-md p-4 font-mono text-sm">{{ submitted }}</div>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Value Changes

Listen on the Input OTP root for `starwind:value-change`. Its detail includes `value`,
`previousValue`, `reason`, and `inputOtpId`; the event is cancelable before Runtime commits the
change.

<FrameworkCodeSwitcher>
<div slot="astro">
```astro
<InputOtp id="verification-code" aria-label="Verification code" maxLength={6}>
  <InputOtpGroup>
    <InputOtpSlot index={0} />
    <InputOtpSlot index={1} />
    <InputOtpSlot index={2} />
    <InputOtpSlot index={3} />
    <InputOtpSlot index={4} />
    <InputOtpSlot index={5} />
  </InputOtpGroup>
</InputOtp>

<script>
  const root = document.querySelector<HTMLElement>("#verification-code");
  root?.addEventListener("starwind:value-change", (event) => {
    const { value, reason } = (
      event as CustomEvent<{ value: string; reason: string }>
    ).detail;
    console.log(value, reason);
  });
</script>
```
</div>
<div slot="react">
```tsx
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";

export function Example() {
  return (
    <InputOtp
      aria-label="Verification code"
      maxLength={6}
      onValueChange={(value, details) => console.log(value, details.reason)}
    >
      <InputOtpGroup>
        {Array.from({ length: 6 }, (_, index) => (
          <InputOtpSlot key={index} index={index} />
        ))}
      </InputOtpGroup>
    </InputOtp>
  );
}
```
</div>
<div slot="vue">
```vue
<script setup lang="ts">
import { InputOtp, InputOtpGroup, InputOtpSlot } from "@/components/starwind/input-otp";
</script>

<template>
  <InputOtp
    @value-change="(value, detail) => console.log(value, detail.reason)"
    id="verification-code"
    aria-label="Verification code"
    :maxLength="6"
  >
    <InputOtpGroup>
      <InputOtpSlot :index="0" />
      <InputOtpSlot :index="1" />
      <InputOtpSlot :index="2" />
      <InputOtpSlot :index="3" />
      <InputOtpSlot :index="4" />
      <InputOtpSlot :index="5" />
    </InputOtpGroup>
  </InputOtp>
</template>
```
</div>
</FrameworkCodeSwitcher>

## Size Migration

| Before | After |
| --- | --- |
| `<InputOtp><InputOtpSlot index={0} size="lg" /></InputOtp>` | `<InputOtp size="lg"><InputOtpSlot index={0} /></InputOtp>` |

## API Reference
### InputOtp
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `size` | `"sm" \| "md" \| "lg"` | No | `"md"` | Wrapper prop | Selects the component's visual size. |
- Inherits div attributes. Omits `defaultValue`, `id`, `onChange`, `pattern`, and `value`.

### InputOtpGroup
- Inherits div attributes.

### InputOtpSlot
- Inherits div attributes.

### InputOtpSeparator
- Inherits div attributes.
### Primitive And Runtime API
Behavior, state, events, form participation, and imperative methods are documented in the lower-level references.
- Primitive: [Input OTP Primitive](/docs/primitives/input-otp/)
- Runtime factory: [`createInputOtp`](/docs/runtime/#create-input-otp) from `@starwind-ui/runtime/input-otp`

## Changelog

### v3.0.1

- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.

### v3.0.0

- Moved slot sizing from `InputOtpSlot` to the `InputOtp` root, with `md` as the default.
- Migration: `<InputOtpSlot index={0} size="sm" />` becomes
`<InputOtp size="sm"><InputOtpSlot index={0} /></InputOtp>`.

### v2.0.0

- Rebuilt Input OTP on Starwind Runtime for value state, form participation, paste handling, and value-change events.
- See the [Input OTP Primitive](/docs/primitives/input-otp/) for the underlying unstyled anatomy and behavior API.
- Input OTP now delegates keyboard navigation, paste distribution, pattern filtering, hidden form
input synchronization, and reset behavior to the Runtime. Give the root an accessible name
because its visible slots share one hidden input.

### v1.0.3

- Refactor tailwind variants functions into separate `variants.ts` file

### v1.0.1

- Auto focus hidden input on click to automatically open keyboards on mobile devices
- Update component to always focus the next empty index on click

### v1.0.0

- Initial release with starwind v1.15.0