awesome-auth-input 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 awesome-auth-input contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # awesome-auth-input
2
+
3
+ A headless, accessible, and fully-typed React component for OTP/auth code inputs with support for numeric, alphabetic, and custom validation patterns.
4
+
5
+ ## Features
6
+
7
+ - **Headless** - Bring your own styles, no CSS included
8
+ - **Accessible** - Full keyboard navigation, screen reader support, ARIA labels
9
+ - **Flexible validation** - Numeric, alphabetic, alphanumeric, or custom regex patterns
10
+ - **Controlled & uncontrolled** - Works both ways
11
+ - **Auto-submit** - Optional auto-submit when all fields are filled
12
+ - **Form integration** - Hidden input for native form submission
13
+ - **Password mode** - Mask input characters
14
+ - **Paste support** - Paste codes directly
15
+ - **TypeScript** - Fully typed with exported types
16
+ - **Zero dependencies** - Only React as a peer dependency
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install awesome-auth-input
22
+ ```
23
+
24
+ ```bash
25
+ yarn add awesome-auth-input
26
+ ```
27
+
28
+ ```bash
29
+ pnpm add awesome-auth-input
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ```tsx
35
+ import { AuthCode } from 'awesome-auth-input';
36
+
37
+ function OTPInput() {
38
+ return (
39
+ <AuthCode.Group onComplete={(code) => console.log('Code:', code)}>
40
+ <AuthCode.Input index={0} />
41
+ <AuthCode.Input index={1} />
42
+ <AuthCode.Input index={2} />
43
+ <AuthCode.Input index={3} />
44
+ <AuthCode.Input index={4} />
45
+ <AuthCode.Input index={5} />
46
+ </AuthCode.Group>
47
+ );
48
+ }
49
+ ```
50
+
51
+ ## API Reference
52
+
53
+ ### `<AuthCode.Group>`
54
+
55
+ The root component that manages state and validation for auth code inputs.
56
+
57
+ | Prop | Type | Default | Description |
58
+ |------|------|---------|-------------|
59
+ | `children` | `ReactNode` | - | The `<AuthCode.Input>` components |
60
+ | `name` | `string` | - | Name attribute for form submission |
61
+ | `validation` | `ValidationPattern` | `{ type: "numeric" }` | Validation pattern for input characters |
62
+ | `autoSubmit` | `boolean` | `true` | Auto-submit the form when all fields are filled |
63
+ | `onComplete` | `(value: string) => void` | - | Callback when all fields are filled |
64
+ | `value` | `string` | - | Controlled value |
65
+ | `onValueChange` | `(value: string) => void` | - | Callback when value changes |
66
+ | `defaultValue` | `string` | - | Initial value for uncontrolled mode |
67
+ | `type` | `"text" \| "password"` | `"text"` | Input type (text shows, password masks) |
68
+ | `disabled` | `boolean` | `false` | Disable all inputs |
69
+
70
+ Plus all standard `div` props (className, style, etc.)
71
+
72
+ ### `<AuthCode.Input>`
73
+
74
+ Individual input field for a single character. Must be used within `<AuthCode.Group>`.
75
+
76
+ | Prop | Type | Description |
77
+ |------|------|-------------|
78
+ | `index` | `number` | **Required.** Position of this input (0-based) |
79
+
80
+ Plus most standard `input` props (className, style, onKeyDown, etc.)
81
+
82
+ ### Validation Patterns
83
+
84
+ ```tsx
85
+ // Numeric only (default)
86
+ <AuthCode.Group validation={{ type: "numeric" }} />
87
+
88
+ // Alphabetic only (a-z, A-Z)
89
+ <AuthCode.Group validation={{ type: "alpha" }} />
90
+
91
+ // Alphanumeric (letters and numbers)
92
+ <AuthCode.Group validation={{ type: "alphanumeric" }} />
93
+
94
+ // Custom validation with regex
95
+ <AuthCode.Group
96
+ validation={{
97
+ type: "custom",
98
+ regex: /^[A-Z]$/, // Validation regex
99
+ pattern: "[A-Z]{1}", // HTML pattern attribute
100
+ inputMode: "text" // Virtual keyboard hint
101
+ }}
102
+ />
103
+ ```
104
+
105
+ ## Examples
106
+
107
+ ### Controlled Component
108
+
109
+ ```tsx
110
+ import { useState } from 'react';
111
+ import { AuthCode } from 'awesome-auth-input';
112
+
113
+ function ControlledOTP() {
114
+ const [code, setCode] = useState('');
115
+
116
+ return (
117
+ <>
118
+ <AuthCode.Group
119
+ value={code}
120
+ onValueChange={setCode}
121
+ onComplete={(value) => verifyCode(value)}
122
+ >
123
+ <AuthCode.Input index={0} />
124
+ <AuthCode.Input index={1} />
125
+ <AuthCode.Input index={2} />
126
+ <AuthCode.Input index={3} />
127
+ </AuthCode.Group>
128
+ <button onClick={() => setCode('')}>Clear</button>
129
+ </>
130
+ );
131
+ }
132
+ ```
133
+
134
+ ### Form Integration
135
+
136
+ ```tsx
137
+ import { AuthCode } from 'awesome-auth-input';
138
+
139
+ function OTPForm() {
140
+ return (
141
+ <form onSubmit={(e) => {
142
+ e.preventDefault();
143
+ const formData = new FormData(e.currentTarget);
144
+ console.log('OTP:', formData.get('otp'));
145
+ }}>
146
+ <AuthCode.Group name="otp" autoSubmit>
147
+ <AuthCode.Input index={0} />
148
+ <AuthCode.Input index={1} />
149
+ <AuthCode.Input index={2} />
150
+ <AuthCode.Input index={3} />
151
+ <AuthCode.Input index={4} />
152
+ <AuthCode.Input index={5} />
153
+ </AuthCode.Group>
154
+ <button type="submit">Verify</button>
155
+ </form>
156
+ );
157
+ }
158
+ ```
159
+
160
+ ### Password/PIN Mode
161
+
162
+ ```tsx
163
+ <AuthCode.Group type="password">
164
+ <AuthCode.Input index={0} />
165
+ <AuthCode.Input index={1} />
166
+ <AuthCode.Input index={2} />
167
+ <AuthCode.Input index={3} />
168
+ </AuthCode.Group>
169
+ ```
170
+
171
+ ### With Separator
172
+
173
+ ```tsx
174
+ <AuthCode.Group>
175
+ <AuthCode.Input index={0} />
176
+ <AuthCode.Input index={1} />
177
+ <AuthCode.Input index={2} />
178
+ <span className="separator">-</span>
179
+ <AuthCode.Input index={3} />
180
+ <AuthCode.Input index={4} />
181
+ <AuthCode.Input index={5} />
182
+ </AuthCode.Group>
183
+ ```
184
+
185
+ ### Custom Styling
186
+
187
+ The component is completely unstyled. Add your own CSS:
188
+
189
+ ```css
190
+ .otp-group {
191
+ display: flex;
192
+ gap: 8px;
193
+ }
194
+
195
+ .otp-input {
196
+ width: 48px;
197
+ height: 56px;
198
+ text-align: center;
199
+ font-size: 24px;
200
+ border: 2px solid #ccc;
201
+ border-radius: 8px;
202
+ }
203
+
204
+ .otp-input:focus {
205
+ outline: none;
206
+ border-color: #0070f3;
207
+ box-shadow: 0 0 0 3px rgba(0, 112, 243, 0.15);
208
+ }
209
+ ```
210
+
211
+ ```tsx
212
+ <AuthCode.Group className="otp-group">
213
+ <AuthCode.Input index={0} className="otp-input" />
214
+ <AuthCode.Input index={1} className="otp-input" />
215
+ {/* ... */}
216
+ </AuthCode.Group>
217
+ ```
218
+
219
+ ## TypeScript
220
+
221
+ Types are exported for your convenience:
222
+
223
+ ```tsx
224
+ import type {
225
+ AuthCodeGroupProps,
226
+ AuthCodeInputProps,
227
+ ValidationPattern,
228
+ CustomValidation,
229
+ } from 'awesome-auth-input';
230
+ ```
231
+
232
+ ## Keyboard Navigation
233
+
234
+ - **Arrow Left/Right** - Navigate between inputs
235
+ - **Backspace** - Delete current character and move to previous
236
+ - **Ctrl/Cmd + Backspace** - Clear all inputs
237
+ - **Enter** - Submit the form
238
+ - **Paste** - Paste code from clipboard (auto-fills all fields)
239
+
240
+ ## Accessibility
241
+
242
+ - Proper ARIA labels for each input
243
+ - Focus management with roving tabindex
244
+ - Screen reader announcements
245
+ - Respects `prefers-reduced-motion`
246
+ - Works with password managers (disabled with data attributes)
247
+
248
+ ## Browser Support
249
+
250
+ - Chrome, Firefox, Safari, Edge (latest versions)
251
+ - Mobile browsers with virtual keyboards
252
+
253
+ ## License
254
+
255
+ MIT
@@ -0,0 +1,159 @@
1
+ import { type ReactNode } from "react";
2
+ interface AuthCodeCustomField {
3
+ /**
4
+ * The child components, typically `<AuthCode.Input>` components.
5
+ *
6
+ * All `<AuthCode.Input>` components must be direct or nested children of `<AuthCode.Group>`.
7
+ */
8
+ children: ReactNode;
9
+ /**
10
+ * A string specifying a name for the input control. This name is submitted
11
+ * along with the control's value when the form data is submitted.
12
+ *
13
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name
14
+ */
15
+ name?: string;
16
+ /**
17
+ * Specifies what type of validation the user agent has to provide for each
18
+ * character input. Allows "numeric", "alpha", "alphanumeric", or a custom
19
+ * validation pattern with regex.
20
+ *
21
+ * @defaultValue `{ type: "numeric" }`
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * // Numeric only (default)
26
+ * <AuthCode.Group validation={{ type: "numeric" }} />
27
+ *
28
+ * // Alphabetic only
29
+ * <AuthCode.Group validation={{ type: "alpha" }} />
30
+ *
31
+ * // Custom validation
32
+ * <AuthCode.Group
33
+ * validation={{
34
+ * type: "custom",
35
+ * regex: /^[A-Z]$/,
36
+ * pattern: "[A-Z]{1}",
37
+ * inputMode: "text"
38
+ * }}
39
+ * />
40
+ * ```
41
+ */
42
+ validation?: ValidationPattern;
43
+ /**
44
+ * Whether or not the component should attempt to automatically submit when
45
+ * all fields are filled. If the field is associated with an HTML `form`
46
+ * element, the form's `requestSubmit` method will be called.
47
+ *
48
+ * @defaultValue `true`
49
+ *
50
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/requestSubmit
51
+ */
52
+ autoSubmit?: boolean;
53
+ /**
54
+ * When the `autoSubmit` prop is set to `true`, this callback will be fired
55
+ * before attempting to submit the associated form. It will be called whether
56
+ * or not a form is located, or if submission is not allowed.
57
+ *
58
+ * The callback receives the complete auth code value as a string.
59
+ *
60
+ * @example
61
+ * ```tsx
62
+ * <AuthCode.Group
63
+ * onComplete={(value) => {
64
+ * console.log('Code entered:', value);
65
+ * verifyCode(value);
66
+ * }}
67
+ * />
68
+ * ```
69
+ */
70
+ onComplete?: (value: string) => void;
71
+ /**
72
+ * The controlled value of the field. When provided, the component operates
73
+ * in controlled mode. This string's value, if present, must match the total
74
+ * number of `<AuthCode.Input>` components.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * const [code, setCode] = useState('');
79
+ * <AuthCode.Group value={code} onValueChange={setCode} />
80
+ * ```
81
+ */
82
+ value?: string;
83
+ /**
84
+ * A callback fired whenever the field value changes. This callback is called
85
+ * with the complete auth code value as a string.
86
+ *
87
+ * Use this prop together with `value` to create a controlled component.
88
+ */
89
+ onValueChange?: (value: string) => void;
90
+ /**
91
+ * The initial value of the uncontrolled field. When provided without `value`,
92
+ * the component operates in uncontrolled mode.
93
+ *
94
+ * @example
95
+ * ```tsx
96
+ * <AuthCode.Group defaultValue="123" />
97
+ * ```
98
+ */
99
+ defaultValue?: string;
100
+ /**
101
+ * The type of control to render. Allows "text" or "password".
102
+ *
103
+ * When set to "password", the input characters will be masked.
104
+ *
105
+ * @defaultValue `"text"`
106
+ *
107
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type
108
+ */
109
+ type?: "text" | "password";
110
+ /**
111
+ * Whether or not the input elements are disabled.
112
+ *
113
+ * When set to `true`, all `<AuthCode.Input>` components will be disabled
114
+ * and users will not be able to interact with them.
115
+ *
116
+ * @defaultValue `false`
117
+ *
118
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled
119
+ */
120
+ disabled?: boolean;
121
+ }
122
+ interface AuthCodeFieldProps extends AuthCodeCustomField, Omit<React.ComponentProps<"div">, keyof AuthCodeCustomField> {
123
+ }
124
+ declare const AuthCodeField: import("react").ForwardRefExoticComponent<Omit<AuthCodeFieldProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
125
+ declare const AuthCodeHiddenInput: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
126
+ /**
127
+ * Input component for entering a single character of the auth code.
128
+ *
129
+ * **Must be used within `<AuthCode.Group>`**
130
+ *
131
+ * @example
132
+ *
133
+ * <AuthCode.Group>
134
+ * <AuthCode.Input index={0} />
135
+ * <AuthCode.Input index={1} />
136
+ * </AuthCode.Group>
137
+ * */
138
+ export declare function AuthCodeInput({ index, ...props }: AuthCodeInputProps): import("react/jsx-runtime").JSX.Element;
139
+ type InputMode = "text" | "numeric" | "none";
140
+ type ValidationPattern = ({
141
+ type: "custom";
142
+ } & CustomValidation) | {
143
+ type: "alpha";
144
+ } | {
145
+ type: "alphanumeric";
146
+ } | {
147
+ type: "numeric";
148
+ };
149
+ type CustomValidation = {
150
+ regex: RegExp;
151
+ pattern: string;
152
+ inputMode: InputMode;
153
+ };
154
+ interface AuthCodeInputProps extends Omit<React.ComponentProps<"input">, "value" | "placeholder" | "disabled" | "autoComplete" | "defaultValue" | "type"> {
155
+ index: number;
156
+ }
157
+ export { AuthCodeField as Group, AuthCodeInput as Input, AuthCodeHiddenInput as HiddenInput, };
158
+ export type { AuthCodeFieldProps as AuthCodeGroupProps, AuthCodeInputProps, ValidationPattern, CustomValidation, };
159
+ //# sourceMappingURL=OneTimePassword.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OneTimePassword.d.ts","sourceRoot":"","sources":["../../src/AuthCode/OneTimePassword.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAGf,UAAU,mBAAmB;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,kBACR,SAAQ,mBAAmB,EACzB,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,mBAAmB,CAAC;CAAG;AAEnE,QAAA,MAAM,aAAa,4HAyPlB,CAAC;AAEF,QAAA,MAAM,mBAAmB,sNAyBvB,CAAC;AAEH;;;;;;;;;;;MAWM;AACN,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,kBAAkB,2CAkKpE;AAgHD,KAAK,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7C,KAAK,iBAAiB,GAClB,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,gBAAgB,CAAC,GACvC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,KAAK,gBAAgB,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,UAAU,kBACR,SAAQ,IAAI,CACV,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAC3B,OAAO,GACP,aAAa,GACb,UAAU,GACV,cAAc,GACd,cAAc,GACd,MAAM,CACT;IACD,KAAK,EAAE,MAAM,CAAC;CACf;AAgED,OAAO,EACL,aAAa,IAAI,KAAK,EACtB,aAAa,IAAI,KAAK,EACtB,mBAAmB,IAAI,WAAW,GACnC,CAAC;AAEF,YAAY,EACV,kBAAkB,IAAI,kBAAkB,EACxC,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,GACjB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './OneTimePassword';
2
+ export { Group as default } from './OneTimePassword';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/AuthCode/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC"}