diff --git a/README.md b/README.md index 45bb9da..56024f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![image](https://user-images.githubusercontent.com/1719915/159336862-113dfbdd-e415-4237-afdb-f9df6628aaf7.png) +![image](https://user-images.githubusercontent.com/1719915/159784302-4bb83708-e993-4800-9bcf-091ecb709ef7.png) # React Auth Code Input @@ -26,6 +26,8 @@ or yarn add react-auth-code-input ``` +# Version 3+ + ## Basic Usage ```tsx @@ -44,7 +46,7 @@ const App = () => { ## Mode -By default you can type anything in the inputs as the `allowedCharacters` prop is defaulted to `alphanumeric` but you can also choose between allowing only letters or only numbers by setting the prop to `alpha` or `numeric` respectively. +By default you can type numbers and letters in the inputs as the `allowedCharacters` prop is defaulted to `alphanumeric` but you can also choose between allowing only letters or only numbers by setting the prop to `alpha` or `numeric` respectively. ```tsx import React, { useState } from 'react'; @@ -122,20 +124,26 @@ This component supports autofill from SMS's received, tested on Safari and Chrom | :------------------- | :---------------------- | :---------------------------------------------------------- | :------------- | :----------------------------------------------- | | `allowedCharacters` | String | Type of allowed characters for your code. | `alphanumeric` | Valid values: `alpha`, `alphanumeric`, `numeric` | | `ariaLabel` | String | Accessibility. | | | -| `autoFocus` | Boolean | Wether the first input is focused on mount or not.. | true | | +| `autoFocus` | Boolean | Wether the first input is focused on mount or not.. | true | Since version 3.1.0 | | `length` | Number | The number of inputs to display. | 6 | | | `containerClassName` | String | The styles to be applied to the container. | | | | `inputClassName` | String | The styles to be applied to each input. | | | | `onChange` | Function(value: String) | Callback function called every time an input value changes. | | Required | | `isPassword` | Boolean | Whether to display the inputs as passwords or not. | false | | +| `disabled` | Boolean | Makes all the inputs disabled if true. | false | Since version 3.1.1 | ## Changelog ### 3.1.0 +- Add `disabled` prop to disable all the inputs. +- Make the backspace delete the previous character if the current is empty. Previously it just moved the focus making the user hit twice the backspace to delete the value. + +### 3.1.0 + - Add `autoFocus` prop set to true by default to not break current usages. -- Expose a `focus` method to handle the focus of the first input manually. -- Expose a `clear` method to clear the input programmatically. +- Expose a `focus` method using references to handle the focus of the first input manually. +- Expose a `clear` method using references to clear the input programmatically. - Add validations for when not using typescript. - Update React peerDependency to use any version 16+. @@ -146,36 +154,6 @@ This component supports autofill from SMS's received, tested on Safari and Chrom - Improved tests. - Improved types. -### 2.1.0 - -- Support to fill one-time-codes directly from SMS's. -- Displays numeric keyboard on mobile devices when the `inputType` prop is set to `number` -- Add `ariaLabel` prop for accessibility. - -### 2.0.0 - -- Remove `inputStyle` prop in favor of `inputClassName`. -- Remove `containerStyle` prop in favor of `containerClassName`. -- Remove `password` prop in favor of `inputType` which accepts _text_, _password_ or _number_ value. - -### 1.2.1 - -- Add missing dist files. - -### 1.2.0 - -- Add `inputClassName` and `containerClassName` props. -- Deprecate `inputStyle` and `containerStyle`. -- Make `onChange` prop mandatory. - -### 1.1.0 - -- Typescript support. - -### 1.0.0 - -- Initial Version. | | deprecated since version 1.2.0 | - ## License Licensed under the MIT License, Copyright © 2020-present Luis Guerrero [drac94](https://github.com/drac94). diff --git a/dist/index.js b/dist/index.js index da43925..8b3510a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -29,6 +29,7 @@ var AuthCode = React.forwardRef(function (_ref, ref) { ariaLabel = _ref.ariaLabel, _ref$autoFocus = _ref.autoFocus, autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus, + disabled = _ref.disabled, _ref$length = _ref.length, length = _ref$length === void 0 ? 6 : _ref$length, containerClassName = _ref.containerClassName, @@ -111,9 +112,11 @@ var AuthCode = React.forwardRef(function (_ref, ref) { var target = e.target; if (key === 'Backspace') { - if (target.value === '' && target.previousElementSibling !== null) { + if (target.value === '') { if (target.previousElementSibling !== null) { - target.previousElementSibling.focus(); + var t = target.previousElementSibling; + t.value = ''; + t.focus(); e.preventDefault(); } } else { @@ -169,7 +172,8 @@ var AuthCode = React.forwardRef(function (_ref, ref) { maxLength: 1, className: inputClassName, autoComplete: i === 0 ? 'one-time-code' : 'off', - "aria-label": ariaLabel ? ariaLabel + ". Character " + (i + 1) + "." : "Character " + (i + 1) + "." + "aria-label": ariaLabel ? ariaLabel + ". Character " + (i + 1) + "." : "Character " + (i + 1) + ".", + disabled: disabled }))); }; diff --git a/dist/index.js.map b/dist/index.js.map index bd6290b..d869d67 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React, {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef\n} from 'react';\n\nconst allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric'] as const;\n\ntype Props = {\n allowedCharacters?: typeof allowedCharactersValues[number];\n ariaLabel?: string;\n autoFocus?: boolean;\n length?: number;\n containerClassName?: string;\n inputClassName?: string;\n isPassword?: boolean;\n onChange: (res: string) => void;\n};\n\ntype InputMode = 'text' | 'numeric';\n\ntype InputType = 'text' | 'number' | 'password';\n\ntype InputProps = {\n type: InputType;\n inputMode: InputMode;\n pattern: string;\n min?: string;\n max?: string;\n};\n\nexport type AuthCodeRef = {\n focus: () => void;\n clear: () => void;\n};\n\nconst propsMap: { [key: string]: InputProps } = {\n alpha: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z]{1}'\n },\n\n alphanumeric: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z0-9]{1}'\n },\n\n numeric: {\n type: 'number',\n inputMode: 'numeric',\n pattern: '[0-9]{1}',\n min: '0',\n max: '9'\n }\n};\n\nconst AuthCode = forwardRef(\n (\n {\n allowedCharacters = 'alphanumeric',\n ariaLabel,\n autoFocus = true,\n length = 6,\n containerClassName,\n inputClassName,\n isPassword = false,\n onChange\n },\n ref\n ) => {\n if (isNaN(length) || length < 1) {\n throw new Error('Length should be a number and greater than 0');\n }\n\n if (!allowedCharactersValues.some((value) => value === allowedCharacters)) {\n throw new Error(\n 'Invalid value for allowedCharacters. Use alpha, numeric, or alphanumeric'\n );\n }\n\n const inputsRef = useRef>([]);\n const inputProps = propsMap[allowedCharacters];\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n if (inputsRef.current) {\n inputsRef.current[0].focus();\n }\n },\n clear: () => {\n if (inputsRef.current) {\n for (let i = 0; i < inputsRef.current.length; i++) {\n inputsRef.current[i].value = '';\n }\n inputsRef.current[0].focus();\n }\n sendResult();\n }\n }));\n\n useEffect(() => {\n if (autoFocus) {\n inputsRef.current[0].focus();\n }\n }, []);\n\n const sendResult = () => {\n const res = inputsRef.current.map((input) => input.value).join('');\n onChange && onChange(res);\n };\n\n const handleOnChange = (e: React.ChangeEvent) => {\n const {\n target: { value, nextElementSibling }\n } = e;\n if (value.length > 1) {\n e.target.value = value.charAt(0);\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n if (value.match(inputProps.pattern)) {\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n e.target.value = '';\n }\n }\n sendResult();\n };\n\n const handleOnKeyDown = (e: React.KeyboardEvent) => {\n const { key } = e;\n const target = e.target as HTMLInputElement;\n if (key === 'Backspace') {\n if (target.value === '' && target.previousElementSibling !== null) {\n if (target.previousElementSibling !== null) {\n (target.previousElementSibling as HTMLInputElement).focus();\n e.preventDefault();\n }\n } else {\n target.value = '';\n }\n sendResult();\n }\n };\n\n const handleOnFocus = (e: React.FocusEvent) => {\n e.target.select();\n };\n\n const handleOnPaste = (e: React.ClipboardEvent) => {\n const pastedValue = e.clipboardData.getData('Text');\n\n let currentInput = 0;\n\n for (let i = 0; i < pastedValue.length; i++) {\n const pastedCharacter = pastedValue.charAt(i);\n const currentValue = inputsRef.current[currentInput].value;\n if (pastedCharacter.match(inputProps.pattern)) {\n if (!currentValue) {\n inputsRef.current[currentInput].value = pastedCharacter;\n if (inputsRef.current[currentInput].nextElementSibling !== null) {\n (inputsRef.current[currentInput]\n .nextElementSibling as HTMLInputElement).focus();\n currentInput++;\n }\n }\n }\n }\n sendResult();\n\n e.preventDefault();\n };\n\n const inputs = [];\n for (let i = 0; i < length; i++) {\n inputs.push(\n {\n inputsRef.current[i] = el;\n }}\n maxLength={1}\n className={inputClassName}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={\n ariaLabel\n ? `${ariaLabel}. Character ${i + 1}.`\n : `Character ${i + 1}.`\n }\n />\n );\n }\n\n return
{inputs}
;\n }\n);\n\nexport default AuthCode;\n"],"names":["allowedCharactersValues","propsMap","alpha","type","inputMode","pattern","alphanumeric","numeric","min","max","AuthCode","forwardRef","ref","allowedCharacters","ariaLabel","autoFocus","length","containerClassName","inputClassName","isPassword","onChange","isNaN","Error","some","value","inputsRef","useRef","inputProps","useImperativeHandle","focus","current","clear","i","sendResult","useEffect","res","map","input","join","handleOnChange","e","target","nextElementSibling","charAt","match","handleOnKeyDown","key","previousElementSibling","preventDefault","handleOnFocus","select","handleOnPaste","pastedValue","clipboardData","getData","currentInput","pastedCharacter","currentValue","inputs","push","React","onKeyDown","onFocus","onPaste","el","maxLength","className","autoComplete"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React, {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef\n} from 'react';\n\nconst allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric'] as const;\n\ntype Props = {\n allowedCharacters?: typeof allowedCharactersValues[number];\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n length?: number;\n containerClassName?: string;\n inputClassName?: string;\n isPassword?: boolean;\n onChange: (res: string) => void;\n};\n\ntype InputMode = 'text' | 'numeric';\n\ntype InputType = 'text' | 'number' | 'password';\n\ntype InputProps = {\n type: InputType;\n inputMode: InputMode;\n pattern: string;\n min?: string;\n max?: string;\n};\n\nexport type AuthCodeRef = {\n focus: () => void;\n clear: () => void;\n};\n\nconst propsMap: { [key: string]: InputProps } = {\n alpha: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z]{1}'\n },\n\n alphanumeric: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z0-9]{1}'\n },\n\n numeric: {\n type: 'number',\n inputMode: 'numeric',\n pattern: '[0-9]{1}',\n min: '0',\n max: '9'\n }\n};\n\nconst AuthCode = forwardRef(\n (\n {\n allowedCharacters = 'alphanumeric',\n ariaLabel,\n autoFocus = true,\n disabled,\n length = 6,\n containerClassName,\n inputClassName,\n isPassword = false,\n onChange\n },\n ref\n ) => {\n if (isNaN(length) || length < 1) {\n throw new Error('Length should be a number and greater than 0');\n }\n\n if (!allowedCharactersValues.some((value) => value === allowedCharacters)) {\n throw new Error(\n 'Invalid value for allowedCharacters. Use alpha, numeric, or alphanumeric'\n );\n }\n\n const inputsRef = useRef>([]);\n const inputProps = propsMap[allowedCharacters];\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n if (inputsRef.current) {\n inputsRef.current[0].focus();\n }\n },\n clear: () => {\n if (inputsRef.current) {\n for (let i = 0; i < inputsRef.current.length; i++) {\n inputsRef.current[i].value = '';\n }\n inputsRef.current[0].focus();\n }\n sendResult();\n }\n }));\n\n useEffect(() => {\n if (autoFocus) {\n inputsRef.current[0].focus();\n }\n }, []);\n\n const sendResult = () => {\n const res = inputsRef.current.map((input) => input.value).join('');\n onChange && onChange(res);\n };\n\n const handleOnChange = (e: React.ChangeEvent) => {\n const {\n target: { value, nextElementSibling }\n } = e;\n if (value.length > 1) {\n e.target.value = value.charAt(0);\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n if (value.match(inputProps.pattern)) {\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n e.target.value = '';\n }\n }\n sendResult();\n };\n\n const handleOnKeyDown = (e: React.KeyboardEvent) => {\n const { key } = e;\n const target = e.target as HTMLInputElement;\n if (key === 'Backspace') {\n if (target.value === '') {\n if (target.previousElementSibling !== null) {\n const t = target.previousElementSibling as HTMLInputElement;\n t.value = '';\n t.focus();\n e.preventDefault();\n }\n } else {\n target.value = '';\n }\n sendResult();\n }\n };\n\n const handleOnFocus = (e: React.FocusEvent) => {\n e.target.select();\n };\n\n const handleOnPaste = (e: React.ClipboardEvent) => {\n const pastedValue = e.clipboardData.getData('Text');\n\n let currentInput = 0;\n\n for (let i = 0; i < pastedValue.length; i++) {\n const pastedCharacter = pastedValue.charAt(i);\n const currentValue = inputsRef.current[currentInput].value;\n if (pastedCharacter.match(inputProps.pattern)) {\n if (!currentValue) {\n inputsRef.current[currentInput].value = pastedCharacter;\n if (inputsRef.current[currentInput].nextElementSibling !== null) {\n (inputsRef.current[currentInput]\n .nextElementSibling as HTMLInputElement).focus();\n currentInput++;\n }\n }\n }\n }\n sendResult();\n\n e.preventDefault();\n };\n\n const inputs = [];\n for (let i = 0; i < length; i++) {\n inputs.push(\n {\n inputsRef.current[i] = el;\n }}\n maxLength={1}\n className={inputClassName}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={\n ariaLabel\n ? `${ariaLabel}. Character ${i + 1}.`\n : `Character ${i + 1}.`\n }\n disabled={disabled}\n />\n );\n }\n\n return
{inputs}
;\n }\n);\n\nexport default AuthCode;\n"],"names":["allowedCharactersValues","propsMap","alpha","type","inputMode","pattern","alphanumeric","numeric","min","max","AuthCode","forwardRef","ref","allowedCharacters","ariaLabel","autoFocus","disabled","length","containerClassName","inputClassName","isPassword","onChange","isNaN","Error","some","value","inputsRef","useRef","inputProps","useImperativeHandle","focus","current","clear","i","sendResult","useEffect","res","map","input","join","handleOnChange","e","target","nextElementSibling","charAt","match","handleOnKeyDown","key","previousElementSibling","t","preventDefault","handleOnFocus","select","handleOnPaste","pastedValue","clipboardData","getData","currentInput","pastedCharacter","currentValue","inputs","push","React","onKeyDown","onFocus","onPaste","el","maxLength","className","autoComplete"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.modern.js b/dist/index.modern.js index d5be7dc..3f9b307 100644 --- a/dist/index.modern.js +++ b/dist/index.modern.js @@ -1,7 +1,7 @@ import React, { forwardRef, useRef, useImperativeHandle, useEffect } from 'react'; -var allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric']; -var propsMap = { +const allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric']; +const propsMap = { alpha: { type: 'text', inputMode: 'text', @@ -20,69 +20,63 @@ var propsMap = { max: '9' } }; -var AuthCode = forwardRef(function (_ref, ref) { - var _ref$allowedCharacter = _ref.allowedCharacters, - allowedCharacters = _ref$allowedCharacter === void 0 ? 'alphanumeric' : _ref$allowedCharacter, - ariaLabel = _ref.ariaLabel, - _ref$autoFocus = _ref.autoFocus, - autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus, - _ref$length = _ref.length, - length = _ref$length === void 0 ? 6 : _ref$length, - containerClassName = _ref.containerClassName, - inputClassName = _ref.inputClassName, - _ref$isPassword = _ref.isPassword, - isPassword = _ref$isPassword === void 0 ? false : _ref$isPassword, - onChange = _ref.onChange; - - if (isNaN(length) || length < 1) { +const AuthCode = forwardRef(({ + allowedCharacters: _allowedCharacters = 'alphanumeric', + ariaLabel, + autoFocus: _autoFocus = true, + disabled, + length: _length = 6, + containerClassName, + inputClassName, + isPassword: _isPassword = false, + onChange +}, ref) => { + if (isNaN(_length) || _length < 1) { throw new Error('Length should be a number and greater than 0'); } - if (!allowedCharactersValues.some(function (value) { - return value === allowedCharacters; - })) { + if (!allowedCharactersValues.some(value => value === _allowedCharacters)) { throw new Error('Invalid value for allowedCharacters. Use alpha, numeric, or alphanumeric'); } - var inputsRef = useRef([]); - var inputProps = propsMap[allowedCharacters]; - useImperativeHandle(ref, function () { - return { - focus: function focus() { - if (inputsRef.current) { - inputsRef.current[0].focus(); - } - }, - clear: function clear() { - if (inputsRef.current) { - for (var i = 0; i < inputsRef.current.length; i++) { - inputsRef.current[i].value = ''; - } - - inputsRef.current[0].focus(); + const inputsRef = useRef([]); + const inputProps = propsMap[_allowedCharacters]; + useImperativeHandle(ref, () => ({ + focus: () => { + if (inputsRef.current) { + inputsRef.current[0].focus(); + } + }, + clear: () => { + if (inputsRef.current) { + for (let i = 0; i < inputsRef.current.length; i++) { + inputsRef.current[i].value = ''; } - sendResult(); + inputsRef.current[0].focus(); } - }; - }); - useEffect(function () { - if (autoFocus) { + + sendResult(); + } + })); + useEffect(() => { + if (_autoFocus) { inputsRef.current[0].focus(); } }, []); - var sendResult = function sendResult() { - var res = inputsRef.current.map(function (input) { - return input.value; - }).join(''); + const sendResult = () => { + const res = inputsRef.current.map(input => input.value).join(''); onChange && onChange(res); }; - var handleOnChange = function handleOnChange(e) { - var _e$target = e.target, - value = _e$target.value, - nextElementSibling = _e$target.nextElementSibling; + const handleOnChange = e => { + const { + target: { + value, + nextElementSibling + } + } = e; if (value.length > 1) { e.target.value = value.charAt(0); @@ -103,14 +97,18 @@ var AuthCode = forwardRef(function (_ref, ref) { sendResult(); }; - var handleOnKeyDown = function handleOnKeyDown(e) { - var key = e.key; - var target = e.target; + const handleOnKeyDown = e => { + const { + key + } = e; + const target = e.target; if (key === 'Backspace') { - if (target.value === '' && target.previousElementSibling !== null) { + if (target.value === '') { if (target.previousElementSibling !== null) { - target.previousElementSibling.focus(); + const t = target.previousElementSibling; + t.value = ''; + t.focus(); e.preventDefault(); } } else { @@ -121,17 +119,17 @@ var AuthCode = forwardRef(function (_ref, ref) { } }; - var handleOnFocus = function handleOnFocus(e) { + const handleOnFocus = e => { e.target.select(); }; - var handleOnPaste = function handleOnPaste(e) { - var pastedValue = e.clipboardData.getData('Text'); - var currentInput = 0; + const handleOnPaste = e => { + const pastedValue = e.clipboardData.getData('Text'); + let currentInput = 0; - for (var i = 0; i < pastedValue.length; i++) { - var pastedCharacter = pastedValue.charAt(i); - var currentValue = inputsRef.current[currentInput].value; + for (let i = 0; i < pastedValue.length; i++) { + const pastedCharacter = pastedValue.charAt(i); + const currentValue = inputsRef.current[currentInput].value; if (pastedCharacter.match(inputProps.pattern)) { if (!currentValue) { @@ -149,9 +147,9 @@ var AuthCode = forwardRef(function (_ref, ref) { e.preventDefault(); }; - var inputs = []; + const inputs = []; - var _loop = function _loop(i) { + for (let i = 0; i < _length; i++) { inputs.push(React.createElement("input", Object.assign({ key: i, onChange: handleOnChange, @@ -159,19 +157,16 @@ var AuthCode = forwardRef(function (_ref, ref) { onFocus: handleOnFocus, onPaste: handleOnPaste }, inputProps, { - type: isPassword ? 'password' : inputProps.type, - ref: function ref(el) { + type: _isPassword ? 'password' : inputProps.type, + ref: el => { inputsRef.current[i] = el; }, maxLength: 1, className: inputClassName, autoComplete: i === 0 ? 'one-time-code' : 'off', - "aria-label": ariaLabel ? ariaLabel + ". Character " + (i + 1) + "." : "Character " + (i + 1) + "." + "aria-label": ariaLabel ? `${ariaLabel}. Character ${i + 1}.` : `Character ${i + 1}.`, + disabled: disabled }))); - }; - - for (var i = 0; i < length; i++) { - _loop(i); } return React.createElement("div", { diff --git a/dist/index.modern.js.map b/dist/index.modern.js.map index 150c20f..3073f47 100644 --- a/dist/index.modern.js.map +++ b/dist/index.modern.js.map @@ -1 +1 @@ -{"version":3,"file":"index.modern.js","sources":["../src/index.tsx"],"sourcesContent":["import React, {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef\n} from 'react';\n\nconst allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric'] as const;\n\ntype Props = {\n allowedCharacters?: typeof allowedCharactersValues[number];\n ariaLabel?: string;\n autoFocus?: boolean;\n length?: number;\n containerClassName?: string;\n inputClassName?: string;\n isPassword?: boolean;\n onChange: (res: string) => void;\n};\n\ntype InputMode = 'text' | 'numeric';\n\ntype InputType = 'text' | 'number' | 'password';\n\ntype InputProps = {\n type: InputType;\n inputMode: InputMode;\n pattern: string;\n min?: string;\n max?: string;\n};\n\nexport type AuthCodeRef = {\n focus: () => void;\n clear: () => void;\n};\n\nconst propsMap: { [key: string]: InputProps } = {\n alpha: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z]{1}'\n },\n\n alphanumeric: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z0-9]{1}'\n },\n\n numeric: {\n type: 'number',\n inputMode: 'numeric',\n pattern: '[0-9]{1}',\n min: '0',\n max: '9'\n }\n};\n\nconst AuthCode = forwardRef(\n (\n {\n allowedCharacters = 'alphanumeric',\n ariaLabel,\n autoFocus = true,\n length = 6,\n containerClassName,\n inputClassName,\n isPassword = false,\n onChange\n },\n ref\n ) => {\n if (isNaN(length) || length < 1) {\n throw new Error('Length should be a number and greater than 0');\n }\n\n if (!allowedCharactersValues.some((value) => value === allowedCharacters)) {\n throw new Error(\n 'Invalid value for allowedCharacters. Use alpha, numeric, or alphanumeric'\n );\n }\n\n const inputsRef = useRef>([]);\n const inputProps = propsMap[allowedCharacters];\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n if (inputsRef.current) {\n inputsRef.current[0].focus();\n }\n },\n clear: () => {\n if (inputsRef.current) {\n for (let i = 0; i < inputsRef.current.length; i++) {\n inputsRef.current[i].value = '';\n }\n inputsRef.current[0].focus();\n }\n sendResult();\n }\n }));\n\n useEffect(() => {\n if (autoFocus) {\n inputsRef.current[0].focus();\n }\n }, []);\n\n const sendResult = () => {\n const res = inputsRef.current.map((input) => input.value).join('');\n onChange && onChange(res);\n };\n\n const handleOnChange = (e: React.ChangeEvent) => {\n const {\n target: { value, nextElementSibling }\n } = e;\n if (value.length > 1) {\n e.target.value = value.charAt(0);\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n if (value.match(inputProps.pattern)) {\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n e.target.value = '';\n }\n }\n sendResult();\n };\n\n const handleOnKeyDown = (e: React.KeyboardEvent) => {\n const { key } = e;\n const target = e.target as HTMLInputElement;\n if (key === 'Backspace') {\n if (target.value === '' && target.previousElementSibling !== null) {\n if (target.previousElementSibling !== null) {\n (target.previousElementSibling as HTMLInputElement).focus();\n e.preventDefault();\n }\n } else {\n target.value = '';\n }\n sendResult();\n }\n };\n\n const handleOnFocus = (e: React.FocusEvent) => {\n e.target.select();\n };\n\n const handleOnPaste = (e: React.ClipboardEvent) => {\n const pastedValue = e.clipboardData.getData('Text');\n\n let currentInput = 0;\n\n for (let i = 0; i < pastedValue.length; i++) {\n const pastedCharacter = pastedValue.charAt(i);\n const currentValue = inputsRef.current[currentInput].value;\n if (pastedCharacter.match(inputProps.pattern)) {\n if (!currentValue) {\n inputsRef.current[currentInput].value = pastedCharacter;\n if (inputsRef.current[currentInput].nextElementSibling !== null) {\n (inputsRef.current[currentInput]\n .nextElementSibling as HTMLInputElement).focus();\n currentInput++;\n }\n }\n }\n }\n sendResult();\n\n e.preventDefault();\n };\n\n const inputs = [];\n for (let i = 0; i < length; i++) {\n inputs.push(\n {\n inputsRef.current[i] = el;\n }}\n maxLength={1}\n className={inputClassName}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={\n ariaLabel\n ? `${ariaLabel}. Character ${i + 1}.`\n : `Character ${i + 1}.`\n }\n />\n );\n }\n\n return
{inputs}
;\n }\n);\n\nexport default AuthCode;\n"],"names":["allowedCharactersValues","propsMap","alpha","type","inputMode","pattern","alphanumeric","numeric","min","max","AuthCode","forwardRef","ref","allowedCharacters","ariaLabel","autoFocus","length","containerClassName","inputClassName","isPassword","onChange","isNaN","Error","some","value","inputsRef","useRef","inputProps","useImperativeHandle","focus","current","clear","i","sendResult","useEffect","res","map","input","join","handleOnChange","e","target","nextElementSibling","charAt","match","handleOnKeyDown","key","previousElementSibling","preventDefault","handleOnFocus","select","handleOnPaste","pastedValue","clipboardData","getData","currentInput","pastedCharacter","currentValue","inputs","push","React","onKeyDown","onFocus","onPaste","el","maxLength","className","autoComplete"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.modern.js","sources":["../src/index.tsx"],"sourcesContent":["import React, {\n useRef,\n useEffect,\n useImperativeHandle,\n forwardRef\n} from 'react';\n\nconst allowedCharactersValues = ['alpha', 'numeric', 'alphanumeric'] as const;\n\ntype Props = {\n allowedCharacters?: typeof allowedCharactersValues[number];\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n length?: number;\n containerClassName?: string;\n inputClassName?: string;\n isPassword?: boolean;\n onChange: (res: string) => void;\n};\n\ntype InputMode = 'text' | 'numeric';\n\ntype InputType = 'text' | 'number' | 'password';\n\ntype InputProps = {\n type: InputType;\n inputMode: InputMode;\n pattern: string;\n min?: string;\n max?: string;\n};\n\nexport type AuthCodeRef = {\n focus: () => void;\n clear: () => void;\n};\n\nconst propsMap: { [key: string]: InputProps } = {\n alpha: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z]{1}'\n },\n\n alphanumeric: {\n type: 'text',\n inputMode: 'text',\n pattern: '[a-zA-Z0-9]{1}'\n },\n\n numeric: {\n type: 'number',\n inputMode: 'numeric',\n pattern: '[0-9]{1}',\n min: '0',\n max: '9'\n }\n};\n\nconst AuthCode = forwardRef(\n (\n {\n allowedCharacters = 'alphanumeric',\n ariaLabel,\n autoFocus = true,\n disabled,\n length = 6,\n containerClassName,\n inputClassName,\n isPassword = false,\n onChange\n },\n ref\n ) => {\n if (isNaN(length) || length < 1) {\n throw new Error('Length should be a number and greater than 0');\n }\n\n if (!allowedCharactersValues.some((value) => value === allowedCharacters)) {\n throw new Error(\n 'Invalid value for allowedCharacters. Use alpha, numeric, or alphanumeric'\n );\n }\n\n const inputsRef = useRef>([]);\n const inputProps = propsMap[allowedCharacters];\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n if (inputsRef.current) {\n inputsRef.current[0].focus();\n }\n },\n clear: () => {\n if (inputsRef.current) {\n for (let i = 0; i < inputsRef.current.length; i++) {\n inputsRef.current[i].value = '';\n }\n inputsRef.current[0].focus();\n }\n sendResult();\n }\n }));\n\n useEffect(() => {\n if (autoFocus) {\n inputsRef.current[0].focus();\n }\n }, []);\n\n const sendResult = () => {\n const res = inputsRef.current.map((input) => input.value).join('');\n onChange && onChange(res);\n };\n\n const handleOnChange = (e: React.ChangeEvent) => {\n const {\n target: { value, nextElementSibling }\n } = e;\n if (value.length > 1) {\n e.target.value = value.charAt(0);\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n if (value.match(inputProps.pattern)) {\n if (nextElementSibling !== null) {\n (nextElementSibling as HTMLInputElement).focus();\n }\n } else {\n e.target.value = '';\n }\n }\n sendResult();\n };\n\n const handleOnKeyDown = (e: React.KeyboardEvent) => {\n const { key } = e;\n const target = e.target as HTMLInputElement;\n if (key === 'Backspace') {\n if (target.value === '') {\n if (target.previousElementSibling !== null) {\n const t = target.previousElementSibling as HTMLInputElement;\n t.value = '';\n t.focus();\n e.preventDefault();\n }\n } else {\n target.value = '';\n }\n sendResult();\n }\n };\n\n const handleOnFocus = (e: React.FocusEvent) => {\n e.target.select();\n };\n\n const handleOnPaste = (e: React.ClipboardEvent) => {\n const pastedValue = e.clipboardData.getData('Text');\n\n let currentInput = 0;\n\n for (let i = 0; i < pastedValue.length; i++) {\n const pastedCharacter = pastedValue.charAt(i);\n const currentValue = inputsRef.current[currentInput].value;\n if (pastedCharacter.match(inputProps.pattern)) {\n if (!currentValue) {\n inputsRef.current[currentInput].value = pastedCharacter;\n if (inputsRef.current[currentInput].nextElementSibling !== null) {\n (inputsRef.current[currentInput]\n .nextElementSibling as HTMLInputElement).focus();\n currentInput++;\n }\n }\n }\n }\n sendResult();\n\n e.preventDefault();\n };\n\n const inputs = [];\n for (let i = 0; i < length; i++) {\n inputs.push(\n {\n inputsRef.current[i] = el;\n }}\n maxLength={1}\n className={inputClassName}\n autoComplete={i === 0 ? 'one-time-code' : 'off'}\n aria-label={\n ariaLabel\n ? `${ariaLabel}. Character ${i + 1}.`\n : `Character ${i + 1}.`\n }\n disabled={disabled}\n />\n );\n }\n\n return
{inputs}
;\n }\n);\n\nexport default AuthCode;\n"],"names":["allowedCharactersValues","propsMap","alpha","type","inputMode","pattern","alphanumeric","numeric","min","max","AuthCode","forwardRef","allowedCharacters","ariaLabel","autoFocus","disabled","length","containerClassName","inputClassName","isPassword","onChange","ref","isNaN","Error","some","value","inputsRef","useRef","inputProps","useImperativeHandle","focus","current","clear","i","sendResult","useEffect","res","map","input","join","handleOnChange","e","target","nextElementSibling","charAt","match","handleOnKeyDown","key","previousElementSibling","t","preventDefault","handleOnFocus","select","handleOnPaste","pastedValue","clipboardData","getData","currentInput","pastedCharacter","currentValue","inputs","push","React","onKeyDown","onFocus","onPaste","el","maxLength","className","autoComplete"],"mappings":"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"} \ No newline at end of file diff --git a/example/src/App.tsx b/example/src/App.tsx index 5cf08b4..d2fac10 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -6,6 +6,8 @@ import './index.css'; const App = () => { const AuthInputRef = useRef(null); const [result, setResult] = useState(''); + const [isPassword, setIsPassword] = useState(false); + const [disabled, setDisabled] = useState(false); const handleOnChange = (res: string) => { setResult(res); }; @@ -43,45 +45,46 @@ const App = () => {

+

+ Two-Factor +
Authentication +

- -

Result: {result}

- - +

+ A message with a verification code has been sent to
+ your devices. Enter the code to continue. +

+

Code: {result}

+
+
+ setIsPassword(e.target.checked)} + /> + +
+
+ setDisabled(e.target.checked)} + /> + +
+ + +
- - {` -import React, { useRef, useState } from 'react'; -import AuthCode, { AuthCodeRef } from 'react-auth-code-input'; - -const App = () => { - const AuthInputRef = useRef(null); - const [result, setResult] = useState(''); - const handleOnChange = (res: string) => { - setResult(res); - }; - return ( -
- - -

Result: {result}

- - -
- ); -} - `} -
); diff --git a/example/src/index.css b/example/src/index.css index 4e272ca..3a8865a 100644 --- a/example/src/index.css +++ b/example/src/index.css @@ -7,6 +7,7 @@ body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; + color: #494949; } .main { @@ -18,44 +19,53 @@ body { .badges > * { margin-right: 8px; } - -code { - display: block; - margin-bottom: 12px; - margin-top: 1em; - background: rgba(255, 255, 255, 0.2); - white-space: pre; - text-align: left; - padding: 12px; -} - .container { padding: 16px; } .input { - width: 2ch; - padding: 8px; - border-radius: 8px; - font-size: 40px; + width: 45px; + height: 45px; + padding: 0; + font-size: 24px; text-align: center; margin-right: 12px; - border: 1px solid #787878; text-transform: uppercase; + color: #494949; + font-family: SF Pro Text, SF Pro Icons, Helvetica Neue, Helvetica, Arial, + sans-serif; + border: 1px solid #d6d6d6; + border-radius: 4px; + background: #fff; + background-clip: padding-box; } -.github-fork-ribbon:before { - background-color: #333; +.input:focus { + appearance: none; + outline: 0; + box-shadow: 0 0 0 3px rgb(131 192 253 / 50%); } -table { - text-align: left; - margin: 0 auto; +button { + appearance: none; + background: #0071e3; + border-radius: 980px; + text-align: center; + border: none; + color: #fff; + margin: 8px; + padding: 4px 11px; +} + +p { + font-size: 17px; + line-height: 1.47059; } -table, -td { - padding: 8px; - border: 1px solid; - border-collapse: collapse; +.controls { + display: flex; + justify-content: space-between; + align-items: center; + border: 1px solid #d6d6d6; + padding: 8px 16px; } diff --git a/package.json b/package.json index decfd10..4217db0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-auth-code-input", - "version": "3.1.0", + "version": "3.1.1", "description": "One-time password (OTP) React input component, uncontrolled, zero dependencies, fully tested.", "author": "drac94", "license": "MIT", diff --git a/src/index.test.tsx b/src/index.test.tsx index 9b953e6..1974cfe 100644 --- a/src/index.test.tsx +++ b/src/index.test.tsx @@ -38,6 +38,28 @@ describe('AuthCode', () => { expect(onChangeFn).toHaveBeenCalledTimes(1); }); + it('should delete the previous value if the current input is empty', async () => { + const onChangeFn = jest.fn(); + render(); + + const input4 = screen.getAllByRole('textbox')[4] as HTMLInputElement; + const input5 = screen.getAllByRole('textbox')[5] as HTMLInputElement; + + userEvent.type(input4, 'A'); + expect(input4).toHaveValue('A'); + + userEvent.type(input5, 'B'); + expect(input5).toHaveValue('B'); + + userEvent.keyboard('[Backspace]'); + expect(input5).toHaveValue(''); + expect(input5).toHaveFocus(); + + userEvent.keyboard('[Backspace]'); + expect(input4).toHaveValue(''); + expect(input4).toHaveFocus(); + }); + describe('Alphanumeric', () => { it('should not change the input value when typing a not allowed character', async () => { const onChangeFn = jest.fn(); diff --git a/src/index.tsx b/src/index.tsx index 192dd36..83f41bc 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,6 +11,7 @@ type Props = { allowedCharacters?: typeof allowedCharactersValues[number]; ariaLabel?: string; autoFocus?: boolean; + disabled?: boolean; length?: number; containerClassName?: string; inputClassName?: string; @@ -63,6 +64,7 @@ const AuthCode = forwardRef( allowedCharacters = 'alphanumeric', ariaLabel, autoFocus = true, + disabled, length = 6, containerClassName, inputClassName, @@ -137,9 +139,11 @@ const AuthCode = forwardRef( const { key } = e; const target = e.target as HTMLInputElement; if (key === 'Backspace') { - if (target.value === '' && target.previousElementSibling !== null) { + if (target.value === '') { if (target.previousElementSibling !== null) { - (target.previousElementSibling as HTMLInputElement).focus(); + const t = target.previousElementSibling as HTMLInputElement; + t.value = ''; + t.focus(); e.preventDefault(); } } else { @@ -199,6 +203,7 @@ const AuthCode = forwardRef( ? `${ariaLabel}. Character ${i + 1}.` : `Character ${i + 1}.` } + disabled={disabled} /> ); }