diff --git a/src/components/OtpField.astro b/src/components/OtpField.astro new file mode 100644 index 0000000..15955e8 --- /dev/null +++ b/src/components/OtpField.astro @@ -0,0 +1,279 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import { cn } from "../utils/cn"; + +interface Props extends HTMLAttributes<"div"> { + id?: string; + name: string; + label?: string; + description?: string; + error?: string; // SSR error (optional) + required?: boolean; + disabled?: boolean; + value?: string; // initial value (e.g., from server) + length?: number; // number of boxes + placeholder?: string | string[]; + onlyDigits?: boolean; // restrict to 0-9 + size?: "sm" | "md" | "lg"; // box sizes + autoFocus?: boolean; + class?: string; +} + +const p = Astro.props as Props; + +const fieldId = p.id ?? p.name; +const descId = p.description ? `${fieldId}-desc` : undefined; +const errId = `${fieldId}-err`; + +const len = Math.max(1, p.length ?? 6); +const initial = (p.value ?? "").slice(0, len); +const boxesSSR = Array.from({ length: len }, (_, i) => initial[i] ?? ""); + +const sizeCls = + p.size === "sm" + ? "wr:h-10 wr:w-10 wr:text-base" + : p.size === "lg" + ? "wr:h-14 wr:w-14 wr:text-xl" + : "wr:h-12 wr:w-12 wr:text-lg"; + +const boxBase = + "wr:rounded-lg wr:border wr:border-gray-200 wr:bg-background wr:text-center wr:tracking-widest " + + "wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-primary/40 " + + "wr:disabled:opacity-50 wr:disabled:pointer-events-none " + + "wr:dark:bg-neutral-900 wr:dark:border-neutral-700 wr:dark:text-neutral-100"; + +const groupCls = "wr:flex wr:items-center wr:gap-2 wr:select-none"; +--- + +
+ { + p.label && ( + + ) + } + + + + + +
+ { + boxesSSR.map((ch, i) => ( + + )) + } +
+ + { + p.description && ( +

+ {p.description} +

+ ) + } + +
+ + diff --git a/src/layouts/ComponentLayout.astro b/src/layouts/ComponentLayout.astro index cad3eb8..ff28d8d 100644 --- a/src/layouts/ComponentLayout.astro +++ b/src/layouts/ComponentLayout.astro @@ -38,6 +38,9 @@ import Base from "./Base.astro";
  • Forms 4
  • +
  • + OTP Form +
  • PassForm
  • diff --git a/src/pages/otp-form.astro b/src/pages/otp-form.astro new file mode 100644 index 0000000..ccc5f12 --- /dev/null +++ b/src/pages/otp-form.astro @@ -0,0 +1,28 @@ +--- +import OtpField from "../components/OtpField.astro"; +import ComponentLayout from "../layouts/ComponentLayout.astro"; +--- + + +
    + + + +
    +