diff --git a/comps/form/field/type/TypeOTP.tsx b/comps/form/field/type/TypeOTP.tsx
index f7f35a0..482f238 100755
--- a/comps/form/field/type/TypeOTP.tsx
+++ b/comps/form/field/type/TypeOTP.tsx
@@ -2,6 +2,8 @@ import { useLocal } from "lib/utils/use-local";
import { FC, useEffect } from "react";
import { FieldLocal, FieldProp, FMLocal } from "../../typings";
import { PropTypeInput } from "./TypeInput";
+import { InputOTP, InputOTPGroup, InputOTPSlot } from "lib/comps/ui/input-otp";
+import { REGEXP_ONLY_DIGITS } from "input-otp";
export const FieldOTP: FC<{
digit: number;
@@ -11,81 +13,44 @@ export const FieldOTP: FC<{
arg: FieldProp;
}> = ({ digit, fm, field }) => {
const local = useLocal({
- otp: [] as string[],
+ otp: "",
ref: [] as HTMLInputElement[],
});
- if (local.otp.length === 0 && digit) {
- for (let i = 0; i < digit; i++) {
- local.otp.push("");
- }
- }
-
return (
-
- {local.otp.map((item, idx) => (
-
{
- if (ref) local.ref[idx] = ref;
- }}
- onPaste={(e) => {
- e.preventDefault();
-
- var clipboardData =
- e.clipboardData || (window as any).clipboardData;
- var pastedData = clipboardData.getData("text");
- for (let i = 0; i < pastedData.length; i++) {
- if (i >= local.otp.length) break;
- local.otp[i] = pastedData[i];
- }
- local.render();
- }}
- onKeyDown={async (e) => {
- if (e.key === "Backspace") {
- let _idx = idx;
- if (local.otp[_idx].length === 0) {
- _idx--;
- }
- local.otp[_idx] = "";
- local.render();
- const ref = local.ref[Math.max(0, _idx - 1)];
- if (ref) {
- ref.focus();
- }
- } else if (parseInt(e.key) || e.key === "0") {
- local.otp[idx] = e.key;
- local.render();
- const ref = local.ref[idx + 1];
- if (ref) {
- ref.focus();
- }
- }
-
- const otp = local.otp.join("");
- fm.data[field.name] = otp;
- if (otp.length === digit) {
- fm.render();
- }
- // local.render();
- }}
- />
- ))}
+
+ {
+ local.otp = value;
+ local.render();
+ if (field.on_change) {
+ field.on_change({ value, name: field.name, fm });
+ }
+ }}
+ pattern={REGEXP_ONLY_DIGITS}
+ inputMode="decimal"
+ >
+
+
+
+
+
+
+
);
};
diff --git a/comps/ui/input-otp.tsx b/comps/ui/input-otp.tsx
new file mode 100755
index 0000000..4edde46
--- /dev/null
+++ b/comps/ui/input-otp.tsx
@@ -0,0 +1,69 @@
+import * as React from "react"
+import { OTPInput, OTPInputContext } from "input-otp"
+import { Dot } from "lucide-react"
+
+import { cn } from "@/utils"
+
+const InputOTP = React.forwardRef<
+ React.ElementRef
,
+ React.ComponentPropsWithoutRef
+>(({ className, containerClassName, ...props }, ref) => (
+
+))
+InputOTP.displayName = "InputOTP"
+
+const InputOTPGroup = React.forwardRef<
+ React.ElementRef<"div">,
+ React.ComponentPropsWithoutRef<"div">
+>(({ className, ...props }, ref) => (
+
+))
+InputOTPGroup.displayName = "InputOTPGroup"
+
+const InputOTPSlot = React.forwardRef<
+ React.ElementRef<"div">,
+ React.ComponentPropsWithoutRef<"div"> & { index: number }
+>(({ index, className, ...props }, ref) => {
+ const inputOTPContext = React.useContext(OTPInputContext)
+ const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
+
+ return (
+
+ {char}
+ {hasFakeCaret && (
+
+ )}
+
+ )
+})
+InputOTPSlot.displayName = "InputOTPSlot"
+
+const InputOTPSeparator = React.forwardRef<
+ React.ElementRef<"div">,
+ React.ComponentPropsWithoutRef<"div">
+>(({ ...props }, ref) => (
+
+
+
+))
+InputOTPSeparator.displayName = "InputOTPSeparator"
+
+export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }