diff --git a/app/pages/components/InputOTP.vue b/app/pages/components/InputOTP.vue
new file mode 100644
index 0000000..3c6cefa
--- /dev/null
+++ b/app/pages/components/InputOTP.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/pages/index.ts b/app/pages/index.ts
index f4714ea..fcd4aa3 100644
--- a/app/pages/index.ts
+++ b/app/pages/index.ts
@@ -27,6 +27,7 @@ export { default as Empty } from "./components/Empty.vue"
export { default as Flasher } from "./components/Flasher.vue"
export { default as Heading } from "./components/Heading.vue"
export { default as Input } from "./components/Input.vue"
+export { default as InputOTP } from "./components/InputOTP.vue"
export { default as Label } from "./components/Label.vue"
export { default as Pagination } from "./components/Pagination.vue"
export { default as Popover } from "./components/Popover.vue"
diff --git a/app/router/index.ts b/app/router/index.ts
index 3ae2648..db479d3 100644
--- a/app/router/index.ts
+++ b/app/router/index.ts
@@ -31,6 +31,7 @@ import {
Flasher,
Heading,
Input,
+ InputOTP,
Label,
Pagination,
Popover,
@@ -198,6 +199,12 @@ const routes = [
component: Input,
meta: { layout: ComponentLayout, shadcn: true },
},
+ {
+ name: "Input OTP",
+ path: "/components/input-otp",
+ component: InputOTP,
+ meta: { layout: ComponentLayout, shadcn: true },
+ },
{
name: "Label",
path: "/components/label",
diff --git a/package-lock.json b/package-lock.json
index 55f05ff..c4bc349 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,7 +20,8 @@
"reka-ui": "^2.5.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
- "vaul-vue": "^0.4.1"
+ "vaul-vue": "^0.4.1",
+ "vue-input-otp": "^0.3.2"
},
"devDependencies": {
"@inertiajs/vue3": "^1.0.0",
@@ -8310,9 +8311,9 @@
}
},
"node_modules/reka-ui": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.6.0.tgz",
- "integrity": "sha512-NrGMKrABD97l890mFS3TNUzB0BLUfbL3hh0NjcJRIUSUljb288bx3Mzo31nOyUcdiiW0HqFGXJwyCBh9cWgb0w==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.6.1.tgz",
+ "integrity": "sha512-XK7cJDQoNuGXfCNzBBo/81Yg/OgjPwvbabnlzXG2VsdSgNsT6iIkuPBPr+C0Shs+3bb0x0lbPvgQAhMSCKm5Ww==",
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.6.13",
@@ -10841,6 +10842,61 @@
"node": ">=4.0"
}
},
+ "node_modules/vue-input-otp": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/vue-input-otp/-/vue-input-otp-0.3.2.tgz",
+ "integrity": "sha512-QMl1842WB6uNAsK4+mZXIskb00TOfahH3AQt8rpRecbtQnOp+oHSUbL/Z3wekfy6pAl+hyN3e1rCUSkCMzbDLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@vueuse/core": "^12.8.2",
+ "reka-ui": "^2.6.1"
+ },
+ "peerDependencies": {
+ "vue": "^3.2.0"
+ }
+ },
+ "node_modules/vue-input-otp/node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "license": "MIT"
+ },
+ "node_modules/vue-input-otp/node_modules/@vueuse/core": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz",
+ "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/vue-input-otp/node_modules/@vueuse/metadata": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz",
+ "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/vue-input-otp/node_modules/@vueuse/shared": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz",
+ "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==",
+ "license": "MIT",
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/vue-router": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz",
diff --git a/package.json b/package.json
index c581519..65e42ea 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,8 @@
"reka-ui": "^2.5.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
- "vaul-vue": "^0.4.1"
+ "vaul-vue": "^0.4.1",
+ "vue-input-otp": "^0.3.2"
},
"devDependencies": {
"@inertiajs/vue3": "^1.0.0",
diff --git a/src/components/input-otp/InputOTP.vue b/src/components/input-otp/InputOTP.vue
new file mode 100644
index 0000000..f34b734
--- /dev/null
+++ b/src/components/input-otp/InputOTP.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/src/components/input-otp/InputOTPGroup.vue b/src/components/input-otp/InputOTPGroup.vue
new file mode 100644
index 0000000..1dea2ab
--- /dev/null
+++ b/src/components/input-otp/InputOTPGroup.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/src/components/input-otp/InputOTPSeparator.vue b/src/components/input-otp/InputOTPSeparator.vue
new file mode 100644
index 0000000..7675e25
--- /dev/null
+++ b/src/components/input-otp/InputOTPSeparator.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/input-otp/InputOTPSlot.vue b/src/components/input-otp/InputOTPSlot.vue
new file mode 100644
index 0000000..a165799
--- /dev/null
+++ b/src/components/input-otp/InputOTPSlot.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
diff --git a/src/components/input-otp/index.ts b/src/components/input-otp/index.ts
new file mode 100644
index 0000000..d97448a
--- /dev/null
+++ b/src/components/input-otp/index.ts
@@ -0,0 +1,4 @@
+export { default as InputOTP } from "./InputOTP.vue"
+export { default as InputOTPGroup } from "./InputOTPGroup.vue"
+export { default as InputOTPSeparator } from "./InputOTPSeparator.vue"
+export { default as InputOTPSlot } from "./InputOTPSlot.vue"
diff --git a/src/components/input-otp/input-otp.spec.ts b/src/components/input-otp/input-otp.spec.ts
new file mode 100644
index 0000000..ebcc4ad
--- /dev/null
+++ b/src/components/input-otp/input-otp.spec.ts
@@ -0,0 +1,5 @@
+describe("template spec", () => {
+ it("passes", () => {
+ cy.visit("/components/input-otp")
+ })
+})
diff --git a/src/index.ts b/src/index.ts
index 90d005a..191a1c5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -32,6 +32,7 @@ export * from "@/components/drawer"
export * from "@/components/dropdown-menu"
export * from "@/components/empty"
export * from "@/components/input"
+export * from "@/components/input-otp"
export * from "@/components/label"
export * from "@/components/pagination"
export * from "@/components/popover"