aural-ui 2.1.7 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/helper-text/index.tsx +2 -2
- package/dist/components/input/Input.stories.tsx +3 -0
- package/dist/components/input/index.tsx +16 -0
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +491 -0
- package/dist/components/otp-inputs/index.tsx +228 -0
- package/dist/components/otp-inputs/meta.ts +21 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ import { cn } from "@lib/utils"
|
|
|
9
9
|
type HelperTextVariant = "default" | "error" | "warning" | "success"
|
|
10
10
|
|
|
11
11
|
interface HelperTextProps {
|
|
12
|
-
variant
|
|
12
|
+
variant?: HelperTextVariant
|
|
13
13
|
className?: string
|
|
14
14
|
children: ReactNode
|
|
15
15
|
disabled?: boolean
|
|
@@ -17,7 +17,7 @@ interface HelperTextProps {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const HelperText = forwardRef<HTMLSpanElement, HelperTextProps>(
|
|
20
|
-
({ variant, className = "", children, disabled, id }, ref) => {
|
|
20
|
+
({ variant = "default", className = "", children, disabled, id }, ref) => {
|
|
21
21
|
return (
|
|
22
22
|
<SwitchCase value={variant}>
|
|
23
23
|
<Case value="error">
|
|
@@ -95,6 +95,7 @@ type InputProps = {
|
|
|
95
95
|
min?: number
|
|
96
96
|
max?: number
|
|
97
97
|
unstyled?: boolean
|
|
98
|
+
transparentOnAutofill?: boolean
|
|
98
99
|
classes?: {
|
|
99
100
|
root?: string
|
|
100
101
|
label?: string
|
|
@@ -237,6 +238,7 @@ const InputBase = forwardRef<
|
|
|
237
238
|
maxLength?: number
|
|
238
239
|
startIcon?: boolean // Indicates if start icon spacing should be applied
|
|
239
240
|
endIcon?: boolean // Indicates if end icon spacing should be applied
|
|
241
|
+
transparentOnAutofill?: boolean
|
|
240
242
|
} & Omit<
|
|
241
243
|
React.InputHTMLAttributes<HTMLInputElement>,
|
|
242
244
|
"onChange" | "onBlur" | "onFocus" | "defaultValue"
|
|
@@ -263,6 +265,7 @@ const InputBase = forwardRef<
|
|
|
263
265
|
startIcon = false,
|
|
264
266
|
endIcon = false,
|
|
265
267
|
ariaLabel,
|
|
268
|
+
transparentOnAutofill = false,
|
|
266
269
|
...props
|
|
267
270
|
},
|
|
268
271
|
ref
|
|
@@ -289,6 +292,16 @@ const InputBase = forwardRef<
|
|
|
289
292
|
// Determine focus state
|
|
290
293
|
const state = disabled ? "disabled" : isFocused ? "focused" : "default"
|
|
291
294
|
|
|
295
|
+
const autoFillStyle = transparentOnAutofill
|
|
296
|
+
? {
|
|
297
|
+
WebkitTextFillColor: "#ffffff",
|
|
298
|
+
color: "#ffffff",
|
|
299
|
+
caretColor: "#ffffff",
|
|
300
|
+
transition: "background-color 999999s ease-in-out 0s",
|
|
301
|
+
backgroundColor: "transparent",
|
|
302
|
+
}
|
|
303
|
+
: {}
|
|
304
|
+
|
|
292
305
|
// Apply styles only if not unstyled
|
|
293
306
|
const inputClassName = unstyled
|
|
294
307
|
? className
|
|
@@ -322,6 +335,7 @@ const InputBase = forwardRef<
|
|
|
322
335
|
onBlur={handleBlur}
|
|
323
336
|
required={required}
|
|
324
337
|
maxLength={maxLength}
|
|
338
|
+
style={autoFillStyle}
|
|
325
339
|
{...props}
|
|
326
340
|
/>
|
|
327
341
|
)
|
|
@@ -356,6 +370,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
356
370
|
decoration,
|
|
357
371
|
unstyled = false,
|
|
358
372
|
classes = {},
|
|
373
|
+
transparentOnAutofill = false,
|
|
359
374
|
...props
|
|
360
375
|
},
|
|
361
376
|
ref
|
|
@@ -436,6 +451,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
|
436
451
|
endIcon={!!(endIcon || type === "password")}
|
|
437
452
|
unstyled={unstyled}
|
|
438
453
|
className={unstyled ? className : classes.input}
|
|
454
|
+
transparentOnAutofill={transparentOnAutofill}
|
|
439
455
|
{...props}
|
|
440
456
|
/>
|
|
441
457
|
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import React, { useState } from "react"
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
3
|
+
|
|
4
|
+
import OtpInputs from "."
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof OtpInputs> = {
|
|
7
|
+
title: "Components/UI/OtpInputs",
|
|
8
|
+
component: OtpInputs,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "centered",
|
|
11
|
+
backgrounds: {
|
|
12
|
+
default: "dark",
|
|
13
|
+
values: [
|
|
14
|
+
{ name: "dark", value: "#0a0a0a" },
|
|
15
|
+
{ name: "light", value: "#ffffff" },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component: `
|
|
21
|
+
# OTP Input Component
|
|
22
|
+
|
|
23
|
+
A flexible and accessible OTP (One-Time Password) input component that allows users to enter verification codes with individual input fields.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Customizable Length**: Configure the number of input fields (default: 6)
|
|
28
|
+
- **Number/Text Input**: Support for both numeric and alphanumeric OTP codes
|
|
29
|
+
- **Keyboard Navigation**: Full keyboard support with arrow keys, backspace, and delete
|
|
30
|
+
- **Auto-focus Management**: Automatic focus progression when typing
|
|
31
|
+
- **Accessibility**: Proper ARIA attributes and keyboard navigation
|
|
32
|
+
- **Custom Styling**: Flexible styling options for inputs and container
|
|
33
|
+
- **Disabled State**: Support for disabled state
|
|
34
|
+
|
|
35
|
+
## Usage Examples
|
|
36
|
+
|
|
37
|
+
### Basic OTP Input
|
|
38
|
+
\`\`\`tsx
|
|
39
|
+
<OtpInputs
|
|
40
|
+
length={6}
|
|
41
|
+
onChangeOTP={(otp) => console.log(otp)}
|
|
42
|
+
/>
|
|
43
|
+
\`\`\`
|
|
44
|
+
|
|
45
|
+
### Alphanumeric OTP
|
|
46
|
+
\`\`\`tsx
|
|
47
|
+
<OtpInputs
|
|
48
|
+
length={6}
|
|
49
|
+
isNumberInput={false}
|
|
50
|
+
onChangeOTP={(otp) => console.log(otp)}
|
|
51
|
+
/>
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
## Props Overview
|
|
55
|
+
|
|
56
|
+
- **length**: Number of input fields (required)
|
|
57
|
+
- **isNumberInput**: Whether to restrict input to numbers only (default: true)
|
|
58
|
+
- **disabled**: Disable all inputs (default: false)
|
|
59
|
+
- **onChangeOTP**: Callback when OTP value changes (required)
|
|
60
|
+
- **inputStyle**: Inline styles for individual inputs
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
tags: ["autodocs"],
|
|
66
|
+
argTypes: {
|
|
67
|
+
length: {
|
|
68
|
+
control: { type: "number", min: 1, max: 10 },
|
|
69
|
+
description: "Number of input fields",
|
|
70
|
+
},
|
|
71
|
+
isNumberInput: {
|
|
72
|
+
control: { type: "boolean" },
|
|
73
|
+
description: "Whether to restrict input to numbers only",
|
|
74
|
+
},
|
|
75
|
+
disabled: {
|
|
76
|
+
control: { type: "boolean" },
|
|
77
|
+
description: "Disable all inputs",
|
|
78
|
+
},
|
|
79
|
+
onChangeOTP: {
|
|
80
|
+
action: "otpChanged",
|
|
81
|
+
description: "Callback when OTP value changes",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default meta
|
|
87
|
+
type Story = StoryObj<typeof OtpInputs>
|
|
88
|
+
|
|
89
|
+
export const Default: Story = {
|
|
90
|
+
args: {
|
|
91
|
+
length: 6,
|
|
92
|
+
isNumberInput: true,
|
|
93
|
+
disabled: false,
|
|
94
|
+
onChangeOTP: (otp: string) => console.log("OTP changed:", otp),
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const FourDigits: Story = {
|
|
99
|
+
args: {
|
|
100
|
+
length: 4,
|
|
101
|
+
isNumberInput: true,
|
|
102
|
+
disabled: false,
|
|
103
|
+
onChangeOTP: (otp: string) => console.log("OTP changed:", otp),
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const EightDigits: Story = {
|
|
108
|
+
args: {
|
|
109
|
+
length: 8,
|
|
110
|
+
isNumberInput: true,
|
|
111
|
+
onChangeOTP: (otp: string) => console.log("OTP changed:", otp),
|
|
112
|
+
},
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const Alphanumeric: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
length: 6,
|
|
118
|
+
isNumberInput: false,
|
|
119
|
+
onChangeOTP: (otp: string) => console.log("OTP changed:", otp),
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export const Disabled: Story = {
|
|
124
|
+
args: {
|
|
125
|
+
length: 6,
|
|
126
|
+
isNumberInput: true,
|
|
127
|
+
disabled: true,
|
|
128
|
+
onChangeOTP: (otp: string) => console.log("OTP changed:", otp),
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export const Interactive: Story = {
|
|
133
|
+
render: () => {
|
|
134
|
+
const [otpValue, setOtpValue] = useState("")
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div className="space-y-4">
|
|
138
|
+
<OtpInputs length={6} onChangeOTP={setOtpValue} />
|
|
139
|
+
<p className="text-sm text-gray-600">
|
|
140
|
+
Current OTP: {otpValue || "Empty"}
|
|
141
|
+
</p>
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const WithValidation: Story = {
|
|
148
|
+
render: () => {
|
|
149
|
+
const [isValid, setIsValid] = useState<boolean | null>(null)
|
|
150
|
+
|
|
151
|
+
const handleOtpChange = (otp: string) => {
|
|
152
|
+
if (otp.length === 6) {
|
|
153
|
+
setIsValid(otp === "123456")
|
|
154
|
+
} else {
|
|
155
|
+
setIsValid(null)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<OtpInputs
|
|
161
|
+
length={6}
|
|
162
|
+
onChangeOTP={handleOtpChange}
|
|
163
|
+
isValid={isValid}
|
|
164
|
+
messages={{
|
|
165
|
+
error: "Invalid OTP, try: 123456",
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export const AllVariants: Story = {
|
|
173
|
+
render: () => {
|
|
174
|
+
const [otp4, setOtp4] = useState("")
|
|
175
|
+
const [otp6, setOtp6] = useState("")
|
|
176
|
+
const [otp8, setOtp8] = useState("")
|
|
177
|
+
const [alphanumericOtp, setAlphanumericOtp] = useState("")
|
|
178
|
+
const [validatedOtp, setValidatedOtp] = useState("")
|
|
179
|
+
const [isValid, setIsValid] = useState<boolean | null>(null)
|
|
180
|
+
|
|
181
|
+
const handleValidation = (otp: string) => {
|
|
182
|
+
setValidatedOtp(otp)
|
|
183
|
+
if (otp.length === 6) {
|
|
184
|
+
setIsValid(otp === "123456")
|
|
185
|
+
} else {
|
|
186
|
+
setIsValid(null)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<div className="max-w-4xl space-y-8 p-6">
|
|
192
|
+
<div className="space-y-2">
|
|
193
|
+
<h2 className="text-2xl font-bold text-white">
|
|
194
|
+
OTP Input - All Variants
|
|
195
|
+
</h2>
|
|
196
|
+
<p className="text-gray-400">
|
|
197
|
+
Comprehensive showcase of all OTP input configurations, states, and
|
|
198
|
+
use cases.
|
|
199
|
+
</p>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
{/* Basic Length Variants */}
|
|
203
|
+
<div className="space-y-4">
|
|
204
|
+
<h3 className="text-xl font-semibold text-white">Length Variants</h3>
|
|
205
|
+
|
|
206
|
+
<div className="space-y-3">
|
|
207
|
+
<div>
|
|
208
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
209
|
+
4-Digit OTP (Common for SMS)
|
|
210
|
+
</label>
|
|
211
|
+
<OtpInputs
|
|
212
|
+
length={4}
|
|
213
|
+
isNumberInput={true}
|
|
214
|
+
onChangeOTP={setOtp4}
|
|
215
|
+
/>
|
|
216
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
217
|
+
Current: {otp4 || "Empty"}
|
|
218
|
+
</p>
|
|
219
|
+
</div>
|
|
220
|
+
|
|
221
|
+
<div>
|
|
222
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
223
|
+
6-Digit OTP (Standard)
|
|
224
|
+
</label>
|
|
225
|
+
<OtpInputs
|
|
226
|
+
length={6}
|
|
227
|
+
isNumberInput={true}
|
|
228
|
+
onChangeOTP={setOtp6}
|
|
229
|
+
/>
|
|
230
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
231
|
+
Current: {otp6 || "Empty"}
|
|
232
|
+
</p>
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<div>
|
|
236
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
237
|
+
8-Digit OTP (Extended Security)
|
|
238
|
+
</label>
|
|
239
|
+
<OtpInputs
|
|
240
|
+
length={8}
|
|
241
|
+
isNumberInput={true}
|
|
242
|
+
onChangeOTP={setOtp8}
|
|
243
|
+
/>
|
|
244
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
245
|
+
Current: {otp8 || "Empty"}
|
|
246
|
+
</p>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
{/* Input Type Variants */}
|
|
252
|
+
<div className="space-y-4">
|
|
253
|
+
<h3 className="text-xl font-semibold text-white">
|
|
254
|
+
Input Type Variants
|
|
255
|
+
</h3>
|
|
256
|
+
|
|
257
|
+
<div className="space-y-3">
|
|
258
|
+
<div>
|
|
259
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
260
|
+
Numeric Only (Default)
|
|
261
|
+
</label>
|
|
262
|
+
<OtpInputs
|
|
263
|
+
length={6}
|
|
264
|
+
isNumberInput={true}
|
|
265
|
+
onChangeOTP={(otp) => console.log("Numeric OTP:", otp)}
|
|
266
|
+
/>
|
|
267
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
268
|
+
Accepts only numbers (0-9)
|
|
269
|
+
</p>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
<div>
|
|
273
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
274
|
+
Alphanumeric (Letters + Numbers)
|
|
275
|
+
</label>
|
|
276
|
+
<OtpInputs
|
|
277
|
+
length={6}
|
|
278
|
+
isNumberInput={false}
|
|
279
|
+
onChangeOTP={setAlphanumericOtp}
|
|
280
|
+
/>
|
|
281
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
282
|
+
Current: {alphanumericOtp || "Empty"} | Accepts letters and
|
|
283
|
+
numbers
|
|
284
|
+
</p>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
{/* State Variants */}
|
|
290
|
+
<div className="space-y-4">
|
|
291
|
+
<h3 className="text-xl font-semibold text-white">State Variants</h3>
|
|
292
|
+
|
|
293
|
+
<div className="space-y-3">
|
|
294
|
+
<div>
|
|
295
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
296
|
+
Enabled State (Default)
|
|
297
|
+
</label>
|
|
298
|
+
<OtpInputs
|
|
299
|
+
length={6}
|
|
300
|
+
isNumberInput={true}
|
|
301
|
+
onChangeOTP={(otp) => console.log("Enabled OTP:", otp)}
|
|
302
|
+
/>
|
|
303
|
+
</div>
|
|
304
|
+
|
|
305
|
+
<div>
|
|
306
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
307
|
+
Disabled State
|
|
308
|
+
</label>
|
|
309
|
+
<OtpInputs
|
|
310
|
+
length={6}
|
|
311
|
+
isNumberInput={true}
|
|
312
|
+
disabled={true}
|
|
313
|
+
onChangeOTP={(otp) => console.log("Disabled OTP:", otp)}
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
{/* Validation States */}
|
|
320
|
+
<div className="space-y-4">
|
|
321
|
+
<h3 className="text-xl font-semibold text-white">
|
|
322
|
+
Validation States
|
|
323
|
+
</h3>
|
|
324
|
+
|
|
325
|
+
<div className="space-y-3">
|
|
326
|
+
<div>
|
|
327
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
328
|
+
Neutral State (No validation)
|
|
329
|
+
</label>
|
|
330
|
+
<OtpInputs
|
|
331
|
+
length={6}
|
|
332
|
+
isNumberInput={true}
|
|
333
|
+
onChangeOTP={(otp) => console.log("Neutral OTP:", otp)}
|
|
334
|
+
isValid={null}
|
|
335
|
+
messages={{
|
|
336
|
+
neutral: "Enter your 6-digit verification code",
|
|
337
|
+
}}
|
|
338
|
+
/>
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
<div>
|
|
342
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
343
|
+
Success State (Valid OTP)
|
|
344
|
+
</label>
|
|
345
|
+
<OtpInputs
|
|
346
|
+
length={6}
|
|
347
|
+
isNumberInput={true}
|
|
348
|
+
onChangeOTP={(otp) => console.log("Success OTP:", otp)}
|
|
349
|
+
isValid={true}
|
|
350
|
+
messages={{
|
|
351
|
+
success: "✓ Verification successful!",
|
|
352
|
+
}}
|
|
353
|
+
/>
|
|
354
|
+
</div>
|
|
355
|
+
|
|
356
|
+
<div>
|
|
357
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
358
|
+
Error State (Invalid OTP)
|
|
359
|
+
</label>
|
|
360
|
+
<OtpInputs
|
|
361
|
+
length={6}
|
|
362
|
+
isNumberInput={true}
|
|
363
|
+
onChangeOTP={(otp) => console.log("Error OTP:", otp)}
|
|
364
|
+
isValid={false}
|
|
365
|
+
messages={{
|
|
366
|
+
error: "✗ Invalid code. Please try again.",
|
|
367
|
+
}}
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
<div>
|
|
372
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
373
|
+
Interactive Validation (Try: 123456)
|
|
374
|
+
</label>
|
|
375
|
+
<OtpInputs
|
|
376
|
+
length={6}
|
|
377
|
+
isNumberInput={true}
|
|
378
|
+
onChangeOTP={handleValidation}
|
|
379
|
+
isValid={isValid}
|
|
380
|
+
messages={{
|
|
381
|
+
neutral: "Enter 6-digit code",
|
|
382
|
+
success: "✓ Code verified successfully!",
|
|
383
|
+
error: "✗ Invalid code. Try: 123456",
|
|
384
|
+
}}
|
|
385
|
+
/>
|
|
386
|
+
<p className="mt-1 text-xs text-gray-500">
|
|
387
|
+
Current: {validatedOtp || "Empty"} | Status:{" "}
|
|
388
|
+
{isValid === null
|
|
389
|
+
? "Neutral"
|
|
390
|
+
: isValid === true
|
|
391
|
+
? "Valid"
|
|
392
|
+
: "Invalid"}
|
|
393
|
+
</p>
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
</div>
|
|
397
|
+
|
|
398
|
+
{/* Custom Styling Examples */}
|
|
399
|
+
<div className="space-y-4">
|
|
400
|
+
<h3 className="text-xl font-semibold text-white">Custom Styling</h3>
|
|
401
|
+
|
|
402
|
+
<div className="space-y-3">
|
|
403
|
+
<div>
|
|
404
|
+
<label className="mb-2 block text-sm font-medium text-gray-300">
|
|
405
|
+
Custom Input Styling
|
|
406
|
+
</label>
|
|
407
|
+
<OtpInputs
|
|
408
|
+
length={6}
|
|
409
|
+
isNumberInput={true}
|
|
410
|
+
onChangeOTP={(otp) => console.log("Custom styled OTP:", otp)}
|
|
411
|
+
inputStyle={{
|
|
412
|
+
backgroundColor: "#1f2937",
|
|
413
|
+
borderColor: "#374151",
|
|
414
|
+
color: "#f9fafb",
|
|
415
|
+
}}
|
|
416
|
+
inputClassName="border-2 border-blue-500 focus:border-blue-400"
|
|
417
|
+
/>
|
|
418
|
+
</div>
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
421
|
+
|
|
422
|
+
{/* Usage Examples */}
|
|
423
|
+
<div className="space-y-4">
|
|
424
|
+
<h3 className="text-xl font-semibold text-white">Common Use Cases</h3>
|
|
425
|
+
|
|
426
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
427
|
+
<div className="rounded-lg bg-gray-800 p-4">
|
|
428
|
+
<h4 className="mb-2 font-medium text-white">SMS Verification</h4>
|
|
429
|
+
<OtpInputs
|
|
430
|
+
length={4}
|
|
431
|
+
isNumberInput={true}
|
|
432
|
+
onChangeOTP={(otp) => console.log("SMS OTP:", otp)}
|
|
433
|
+
messages={{
|
|
434
|
+
neutral: "Enter SMS code",
|
|
435
|
+
}}
|
|
436
|
+
/>
|
|
437
|
+
</div>
|
|
438
|
+
|
|
439
|
+
<div className="rounded-lg bg-gray-800 p-4">
|
|
440
|
+
<h4 className="mb-2 font-medium text-white">
|
|
441
|
+
Email Verification
|
|
442
|
+
</h4>
|
|
443
|
+
<OtpInputs
|
|
444
|
+
length={6}
|
|
445
|
+
isNumberInput={true}
|
|
446
|
+
onChangeOTP={(otp) => console.log("Email OTP:", otp)}
|
|
447
|
+
messages={{
|
|
448
|
+
neutral: "Enter email code",
|
|
449
|
+
}}
|
|
450
|
+
/>
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
<div className="rounded-lg bg-gray-800 p-4">
|
|
454
|
+
<h4 className="mb-2 font-medium text-white">
|
|
455
|
+
2FA Authentication
|
|
456
|
+
</h4>
|
|
457
|
+
<OtpInputs
|
|
458
|
+
length={6}
|
|
459
|
+
isNumberInput={true}
|
|
460
|
+
onChangeOTP={(otp) => console.log("2FA OTP:", otp)}
|
|
461
|
+
messages={{
|
|
462
|
+
neutral: "Enter authenticator code",
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
</div>
|
|
466
|
+
|
|
467
|
+
<div className="rounded-lg bg-gray-800 p-4">
|
|
468
|
+
<h4 className="mb-2 font-medium text-white">Alphanumeric Code</h4>
|
|
469
|
+
<OtpInputs
|
|
470
|
+
length={6}
|
|
471
|
+
isNumberInput={false}
|
|
472
|
+
onChangeOTP={(otp) => console.log("Alphanumeric OTP:", otp)}
|
|
473
|
+
messages={{
|
|
474
|
+
neutral: "Enter alphanumeric code",
|
|
475
|
+
}}
|
|
476
|
+
/>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
</div>
|
|
481
|
+
)
|
|
482
|
+
},
|
|
483
|
+
parameters: {
|
|
484
|
+
docs: {
|
|
485
|
+
description: {
|
|
486
|
+
story: `
|
|
487
|
+
This comprehensive story demonstrates all available variants, states, and configurations of the OTP Input component:`,
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
}
|