@matin_mortazavi/react-otp-input 1.0.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/lib/index.cjs ADDED
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
6
+
7
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
8
+
9
+ var isStyleObject = function (obj) { return typeof obj === 'object' && obj !== null; };
10
+ var OTPInput = function (_a) {
11
+ var _b = _a.value, value = _b === void 0 ? '' : _b, _c = _a.numInputs, numInputs = _c === void 0 ? 4 : _c, onChange = _a.onChange, onPaste = _a.onPaste, shouldBlurOnFinish = _a.shouldBlurOnFinish, renderInput = _a.renderInput, _d = _a.shouldAutoFocus, shouldAutoFocus = _d === void 0 ? false : _d, _e = _a.inputType, inputType = _e === void 0 ? 'text' : _e, renderSeparator = _a.renderSeparator, placeholder = _a.placeholder, containerStyle = _a.containerStyle, inputStyle = _a.inputStyle, _f = _a.skipDefaultStyles, skipDefaultStyles = _f === void 0 ? false : _f;
12
+ var _g = React__default["default"].useState(0), activeInput = _g[0], setActiveInput = _g[1];
13
+ var inputRefs = React__default["default"].useRef([]);
14
+ var getOTPValue = function () { return (value ? value.toString().split('') : []); };
15
+ var isInputNum = inputType === 'number' || inputType === 'tel';
16
+ React__default["default"].useEffect(function () {
17
+ inputRefs.current = inputRefs.current.slice(0, numInputs);
18
+ }, [numInputs]);
19
+ React__default["default"].useEffect(function () {
20
+ var _a;
21
+ if (shouldAutoFocus) {
22
+ (_a = inputRefs.current[0]) === null || _a === void 0 ? void 0 : _a.focus();
23
+ }
24
+ }, [shouldAutoFocus]);
25
+ React__default["default"].useEffect(function () {
26
+ var _a;
27
+ if (shouldBlurOnFinish && numInputs === (value === null || value === void 0 ? void 0 : value.length)) {
28
+ (_a = inputRefs.current[numInputs]) === null || _a === void 0 ? void 0 : _a.blur();
29
+ }
30
+ }, [shouldBlurOnFinish, numInputs, value]);
31
+ var getPlaceholderValue = function () {
32
+ if (typeof placeholder === 'string') {
33
+ if (placeholder.length === numInputs) {
34
+ return placeholder;
35
+ }
36
+ if (placeholder.length > 0) {
37
+ console.error('Length of the placeholder should be equal to the number of inputs.');
38
+ }
39
+ }
40
+ return undefined;
41
+ };
42
+ var isInputValueValid = function (value) {
43
+ var isTypeValid = isInputNum ? !isNaN(Number(value)) : typeof value === 'string';
44
+ return isTypeValid && value.trim().length === 1;
45
+ };
46
+ var handleChange = function (event) {
47
+ var value = event.target.value;
48
+ if (isInputValueValid(value)) {
49
+ changeCodeAtFocus(value);
50
+ focusInput(activeInput + 1);
51
+ }
52
+ };
53
+ var handleInputChange = function (event) {
54
+ var nativeEvent = event.nativeEvent;
55
+ var value = event.target.value;
56
+ if (!isInputValueValid(value)) {
57
+ // Pasting from the native autofill suggestion on a mobile device can pass
58
+ // the pasted string as one long input to one of the cells. This ensures
59
+ // that we handle the full input and not just the first character.
60
+ if (value.length === numInputs) {
61
+ var hasInvalidInput = value.split('').some(function (cellInput) { return !isInputValueValid(cellInput); });
62
+ if (!hasInvalidInput) {
63
+ handleOTPChange(value.split(''));
64
+ focusInput(numInputs - 1);
65
+ }
66
+ }
67
+ // @ts-expect-error - This was added previously to handle and edge case
68
+ // for dealing with keyCode "229 Unidentified" on Android. Check if this is
69
+ // still needed.
70
+ if (nativeEvent.data === null && nativeEvent.inputType === 'deleteContentBackward') {
71
+ event.preventDefault();
72
+ changeCodeAtFocus('');
73
+ focusInput(activeInput - 1);
74
+ }
75
+ // Clear the input if it's not valid value because firefox allows
76
+ // pasting non-numeric characters in a number type input
77
+ event.target.value = '';
78
+ }
79
+ };
80
+ var handleFocus = function (event) { return function (index) {
81
+ setActiveInput(index);
82
+ event.target.select();
83
+ }; };
84
+ var handleBlur = function () {
85
+ setActiveInput(activeInput - 1);
86
+ };
87
+ var handleKeyDown = function (event) {
88
+ var otp = getOTPValue();
89
+ if ([event.code, event.key].includes('Backspace')) {
90
+ event.preventDefault();
91
+ changeCodeAtFocus('');
92
+ focusInput(activeInput - 1);
93
+ }
94
+ else if (event.code === 'Delete') {
95
+ event.preventDefault();
96
+ changeCodeAtFocus('');
97
+ }
98
+ else if (event.code === 'ArrowLeft') {
99
+ event.preventDefault();
100
+ focusInput(activeInput - 1);
101
+ }
102
+ else if (event.code === 'ArrowRight') {
103
+ event.preventDefault();
104
+ focusInput(activeInput + 1);
105
+ }
106
+ // React does not trigger onChange when the same value is entered
107
+ // again. So we need to focus the next input manually in this case.
108
+ else if (event.key === otp[activeInput]) {
109
+ event.preventDefault();
110
+ focusInput(activeInput + 1);
111
+ }
112
+ else if (event.code === 'Spacebar' ||
113
+ event.code === 'Space' ||
114
+ event.code === 'ArrowUp' ||
115
+ event.code === 'ArrowDown') {
116
+ event.preventDefault();
117
+ }
118
+ };
119
+ var focusInput = function (index) {
120
+ var _a, _b;
121
+ var activeInput = Math.max(Math.min(numInputs - 1, index), 0);
122
+ if (inputRefs.current[activeInput]) {
123
+ (_a = inputRefs.current[activeInput]) === null || _a === void 0 ? void 0 : _a.focus();
124
+ (_b = inputRefs.current[activeInput]) === null || _b === void 0 ? void 0 : _b.select();
125
+ setActiveInput(activeInput);
126
+ }
127
+ };
128
+ var changeCodeAtFocus = function (value) {
129
+ var otp = getOTPValue();
130
+ otp[activeInput] = value[0];
131
+ handleOTPChange(otp);
132
+ };
133
+ var handleOTPChange = function (otp) {
134
+ var otpValue = otp.join('');
135
+ onChange(otpValue);
136
+ };
137
+ var handlePaste = function (event) {
138
+ var _a;
139
+ event.preventDefault();
140
+ var otp = getOTPValue();
141
+ var nextActiveInput = activeInput;
142
+ // Get pastedData in an array of max size (num of inputs - current position)
143
+ var pastedData = event.clipboardData
144
+ .getData('text/plain')
145
+ .slice(0, numInputs - activeInput)
146
+ .split('');
147
+ // Prevent pasting if the clipboard data contains non-numeric values for number inputs
148
+ if (isInputNum && pastedData.some(function (value) { return isNaN(Number(value)); })) {
149
+ return;
150
+ }
151
+ // Paste data from focused input onwards
152
+ for (var pos = 0; pos < numInputs; ++pos) {
153
+ if (pos >= activeInput && pastedData.length > 0) {
154
+ otp[pos] = (_a = pastedData.shift()) !== null && _a !== void 0 ? _a : '';
155
+ nextActiveInput++;
156
+ }
157
+ }
158
+ focusInput(nextActiveInput);
159
+ handleOTPChange(otp);
160
+ };
161
+ return (React__default["default"].createElement("div", { style: Object.assign({ display: 'flex', alignItems: 'center' }, isStyleObject(containerStyle) && containerStyle), className: typeof containerStyle === 'string' ? containerStyle : undefined, onPaste: onPaste }, Array.from({ length: numInputs }, function (_, index) { return index; }).map(function (index) {
162
+ var _a, _b, _c;
163
+ return (React__default["default"].createElement(React__default["default"].Fragment, { key: index },
164
+ renderInput({
165
+ value: (_a = getOTPValue()[index]) !== null && _a !== void 0 ? _a : '',
166
+ placeholder: (_c = (_b = getPlaceholderValue()) === null || _b === void 0 ? void 0 : _b[index]) !== null && _c !== void 0 ? _c : undefined,
167
+ ref: function (element) { return (inputRefs.current[index] = element); },
168
+ onChange: handleChange,
169
+ onFocus: function (event) { return handleFocus(event)(index); },
170
+ onBlur: handleBlur,
171
+ onKeyDown: handleKeyDown,
172
+ onPaste: handlePaste,
173
+ autoComplete: 'off',
174
+ 'aria-label': "Please enter OTP character ".concat(index + 1),
175
+ style: Object.assign(!skipDefaultStyles ? { width: '1em', textAlign: 'center' } : {}, isStyleObject(inputStyle) ? inputStyle : {}),
176
+ className: typeof inputStyle === 'string' ? inputStyle : undefined,
177
+ type: inputType,
178
+ inputMode: isInputNum ? 'numeric' : 'text',
179
+ onInput: handleInputChange,
180
+ }, index),
181
+ index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator)));
182
+ })));
183
+ };
184
+
185
+ module.exports = OTPInput;
186
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/index.tsx"],"sourcesContent":["import React from 'react';\r\n\r\ntype AllowedInputTypes = 'password' | 'text' | 'number' | 'tel';\r\n\r\ntype InputProps = Required<\r\n Pick<\r\n React.InputHTMLAttributes<HTMLInputElement>,\r\n | 'value'\r\n | 'onChange'\r\n | 'onFocus'\r\n | 'onBlur'\r\n | 'onKeyDown'\r\n | 'onPaste'\r\n | 'aria-label'\r\n | 'autoComplete'\r\n | 'style'\r\n | 'inputMode'\r\n | 'onInput'\r\n > & {\r\n ref: React.RefCallback<HTMLInputElement>;\r\n placeholder: string | undefined;\r\n className: string | undefined;\r\n type: AllowedInputTypes;\r\n }\r\n>;\r\n\r\ninterface OTPInputProps {\r\n /** Value of the OTP input */\r\n value?: string;\r\n /** Number of OTP inputs to be rendered */\r\n numInputs?: number;\r\n /** Blur after last char entered (close keyboard on mobile) */\r\n shouldBlurOnFinish?: boolean;\r\n /** Callback to be called when the OTP value changes */\r\n onChange: (otp: string) => void;\r\n /** Callback to be called when pasting content into the component */\r\n onPaste?: (event: React.ClipboardEvent<HTMLDivElement>) => void;\r\n /** Function to render the input */\r\n renderInput: (inputProps: InputProps, index: number) => React.ReactNode;\r\n /** Whether the first input should be auto focused */\r\n shouldAutoFocus?: boolean;\r\n /** Placeholder for the inputs */\r\n placeholder?: string;\r\n /** Function to render the separator */\r\n renderSeparator?: ((index: number) => React.ReactNode) | React.ReactNode;\r\n /** Style for the container */\r\n containerStyle?: React.CSSProperties | string;\r\n /** Style for the input */\r\n inputStyle?: React.CSSProperties | string;\r\n /** The type that will be passed to the input being rendered */\r\n inputType?: AllowedInputTypes;\r\n /** Do not apply the default styles to the inputs, will be removed in future versions */\r\n skipDefaultStyles?: boolean; // TODO: Remove in next major release\r\n}\r\n\r\nconst isStyleObject = (obj: unknown) => typeof obj === 'object' && obj !== null;\r\n\r\nconst OTPInput = ({\r\n value = '',\r\n numInputs = 4,\r\n onChange,\r\n onPaste,\r\n shouldBlurOnFinish,\r\n renderInput,\r\n shouldAutoFocus = false,\r\n inputType = 'text',\r\n renderSeparator,\r\n placeholder,\r\n containerStyle,\r\n inputStyle,\r\n skipDefaultStyles = false,\r\n}: OTPInputProps) => {\r\n const [activeInput, setActiveInput] = React.useState(0);\r\n const inputRefs = React.useRef<Array<HTMLInputElement | null>>([]);\r\n\r\n const getOTPValue = () => (value ? value.toString().split('') : []);\r\n\r\n const isInputNum = inputType === 'number' || inputType === 'tel';\r\n\r\n React.useEffect(() => {\r\n inputRefs.current = inputRefs.current.slice(0, numInputs);\r\n }, [numInputs]);\r\n\r\n React.useEffect(() => {\r\n if (shouldAutoFocus) {\r\n inputRefs.current[0]?.focus();\r\n }\r\n }, [shouldAutoFocus]);\r\n\r\n React.useEffect(() => {\r\n if (shouldBlurOnFinish && numInputs === value?.length) {\r\n inputRefs.current[numInputs]?.blur();\r\n }\r\n }, [shouldBlurOnFinish, numInputs, value]);\r\n\r\n const getPlaceholderValue = () => {\r\n if (typeof placeholder === 'string') {\r\n if (placeholder.length === numInputs) {\r\n return placeholder;\r\n }\r\n\r\n if (placeholder.length > 0) {\r\n console.error('Length of the placeholder should be equal to the number of inputs.');\r\n }\r\n }\r\n return undefined;\r\n };\r\n\r\n const isInputValueValid = (value: string) => {\r\n const isTypeValid = isInputNum ? !isNaN(Number(value)) : typeof value === 'string';\r\n return isTypeValid && value.trim().length === 1;\r\n };\r\n\r\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const { value } = event.target;\r\n\r\n if (isInputValueValid(value)) {\r\n changeCodeAtFocus(value);\r\n focusInput(activeInput + 1);\r\n }\r\n };\r\n\r\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const { nativeEvent } = event;\r\n const value = event.target.value;\r\n\r\n if (!isInputValueValid(value)) {\r\n // Pasting from the native autofill suggestion on a mobile device can pass\r\n // the pasted string as one long input to one of the cells. This ensures\r\n // that we handle the full input and not just the first character.\r\n if (value.length === numInputs) {\r\n const hasInvalidInput = value.split('').some((cellInput) => !isInputValueValid(cellInput));\r\n if (!hasInvalidInput) {\r\n handleOTPChange(value.split(''));\r\n focusInput(numInputs - 1);\r\n }\r\n }\r\n\r\n // @ts-expect-error - This was added previously to handle and edge case\r\n // for dealing with keyCode \"229 Unidentified\" on Android. Check if this is\r\n // still needed.\r\n if (nativeEvent.data === null && nativeEvent.inputType === 'deleteContentBackward') {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n focusInput(activeInput - 1);\r\n }\r\n\r\n // Clear the input if it's not valid value because firefox allows\r\n // pasting non-numeric characters in a number type input\r\n event.target.value = '';\r\n }\r\n };\r\n\r\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => (index: number) => {\r\n setActiveInput(index);\r\n event.target.select();\r\n };\r\n\r\n const handleBlur = () => {\r\n setActiveInput(activeInput - 1);\r\n };\r\n\r\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\r\n const otp = getOTPValue();\r\n if ([event.code, event.key].includes('Backspace')) {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n focusInput(activeInput - 1);\r\n } else if (event.code === 'Delete') {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n } else if (event.code === 'ArrowLeft') {\r\n event.preventDefault();\r\n focusInput(activeInput - 1);\r\n } else if (event.code === 'ArrowRight') {\r\n event.preventDefault();\r\n focusInput(activeInput + 1);\r\n }\r\n // React does not trigger onChange when the same value is entered\r\n // again. So we need to focus the next input manually in this case.\r\n else if (event.key === otp[activeInput]) {\r\n event.preventDefault();\r\n focusInput(activeInput + 1);\r\n } else if (\r\n event.code === 'Spacebar' ||\r\n event.code === 'Space' ||\r\n event.code === 'ArrowUp' ||\r\n event.code === 'ArrowDown'\r\n ) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n const focusInput = (index: number) => {\r\n const activeInput = Math.max(Math.min(numInputs - 1, index), 0);\r\n\r\n if (inputRefs.current[activeInput]) {\r\n inputRefs.current[activeInput]?.focus();\r\n inputRefs.current[activeInput]?.select();\r\n setActiveInput(activeInput);\r\n }\r\n };\r\n\r\n const changeCodeAtFocus = (value: string) => {\r\n const otp = getOTPValue();\r\n otp[activeInput] = value[0];\r\n handleOTPChange(otp);\r\n };\r\n\r\n const handleOTPChange = (otp: Array<string>) => {\r\n const otpValue = otp.join('');\r\n onChange(otpValue);\r\n };\r\n\r\n const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\r\n event.preventDefault();\r\n\r\n const otp = getOTPValue();\r\n let nextActiveInput = activeInput;\r\n\r\n // Get pastedData in an array of max size (num of inputs - current position)\r\n const pastedData = event.clipboardData\r\n .getData('text/plain')\r\n .slice(0, numInputs - activeInput)\r\n .split('');\r\n\r\n // Prevent pasting if the clipboard data contains non-numeric values for number inputs\r\n if (isInputNum && pastedData.some((value) => isNaN(Number(value)))) {\r\n return;\r\n }\r\n\r\n // Paste data from focused input onwards\r\n for (let pos = 0; pos < numInputs; ++pos) {\r\n if (pos >= activeInput && pastedData.length > 0) {\r\n otp[pos] = pastedData.shift() ?? '';\r\n nextActiveInput++;\r\n }\r\n }\r\n\r\n focusInput(nextActiveInput);\r\n handleOTPChange(otp);\r\n };\r\n\r\n return (\r\n <div\r\n style={Object.assign({ display: 'flex', alignItems: 'center' }, isStyleObject(containerStyle) && containerStyle)}\r\n className={typeof containerStyle === 'string' ? containerStyle : undefined}\r\n onPaste={onPaste}\r\n >\r\n {Array.from({ length: numInputs }, (_, index) => index).map((index) => (\r\n <React.Fragment key={index}>\r\n {renderInput(\r\n {\r\n value: getOTPValue()[index] ?? '',\r\n placeholder: getPlaceholderValue()?.[index] ?? undefined,\r\n ref: (element) => (inputRefs.current[index] = element),\r\n onChange: handleChange,\r\n onFocus: (event) => handleFocus(event)(index),\r\n onBlur: handleBlur,\r\n onKeyDown: handleKeyDown,\r\n onPaste: handlePaste,\r\n autoComplete: 'off',\r\n 'aria-label': `Please enter OTP character ${index + 1}`,\r\n style: Object.assign(\r\n !skipDefaultStyles ? ({ width: '1em', textAlign: 'center' } as const) : {},\r\n isStyleObject(inputStyle) ? inputStyle : {}\r\n ),\r\n className: typeof inputStyle === 'string' ? inputStyle : undefined,\r\n type: inputType,\r\n inputMode: isInputNum ? 'numeric' : 'text',\r\n onInput: handleInputChange,\r\n },\r\n index\r\n )}\r\n {index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator)}\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\nexport type { OTPInputProps, InputProps, AllowedInputTypes };\r\nexport default OTPInput;\r\n"],"names":["React"],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ type AllowedInputTypes = 'password' | 'text' | 'number' | 'tel';
3
+ type InputProps = Required<Pick<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'onFocus' | 'onBlur' | 'onKeyDown' | 'onPaste' | 'aria-label' | 'autoComplete' | 'style' | 'inputMode' | 'onInput'> & {
4
+ ref: React.RefCallback<HTMLInputElement>;
5
+ placeholder: string | undefined;
6
+ className: string | undefined;
7
+ type: AllowedInputTypes;
8
+ }>;
9
+ interface OTPInputProps {
10
+ /** Value of the OTP input */
11
+ value?: string;
12
+ /** Number of OTP inputs to be rendered */
13
+ numInputs?: number;
14
+ /** Blur after last char entered (close keyboard on mobile) */
15
+ shouldBlurOnFinish?: boolean;
16
+ /** Callback to be called when the OTP value changes */
17
+ onChange: (otp: string) => void;
18
+ /** Callback to be called when pasting content into the component */
19
+ onPaste?: (event: React.ClipboardEvent<HTMLDivElement>) => void;
20
+ /** Function to render the input */
21
+ renderInput: (inputProps: InputProps, index: number) => React.ReactNode;
22
+ /** Whether the first input should be auto focused */
23
+ shouldAutoFocus?: boolean;
24
+ /** Placeholder for the inputs */
25
+ placeholder?: string;
26
+ /** Function to render the separator */
27
+ renderSeparator?: ((index: number) => React.ReactNode) | React.ReactNode;
28
+ /** Style for the container */
29
+ containerStyle?: React.CSSProperties | string;
30
+ /** Style for the input */
31
+ inputStyle?: React.CSSProperties | string;
32
+ /** The type that will be passed to the input being rendered */
33
+ inputType?: AllowedInputTypes;
34
+ /** Do not apply the default styles to the inputs, will be removed in future versions */
35
+ skipDefaultStyles?: boolean;
36
+ }
37
+ declare const OTPInput: ({ value, numInputs, onChange, onPaste, shouldBlurOnFinish, renderInput, shouldAutoFocus, inputType, renderSeparator, placeholder, containerStyle, inputStyle, skipDefaultStyles, }: OTPInputProps) => JSX.Element;
38
+ export type { OTPInputProps, InputProps, AllowedInputTypes };
39
+ export default OTPInput;
@@ -0,0 +1,180 @@
1
+ import React from 'react';
2
+
3
+ var isStyleObject = function (obj) { return typeof obj === 'object' && obj !== null; };
4
+ var OTPInput = function (_a) {
5
+ var _b = _a.value, value = _b === void 0 ? '' : _b, _c = _a.numInputs, numInputs = _c === void 0 ? 4 : _c, onChange = _a.onChange, onPaste = _a.onPaste, shouldBlurOnFinish = _a.shouldBlurOnFinish, renderInput = _a.renderInput, _d = _a.shouldAutoFocus, shouldAutoFocus = _d === void 0 ? false : _d, _e = _a.inputType, inputType = _e === void 0 ? 'text' : _e, renderSeparator = _a.renderSeparator, placeholder = _a.placeholder, containerStyle = _a.containerStyle, inputStyle = _a.inputStyle, _f = _a.skipDefaultStyles, skipDefaultStyles = _f === void 0 ? false : _f;
6
+ var _g = React.useState(0), activeInput = _g[0], setActiveInput = _g[1];
7
+ var inputRefs = React.useRef([]);
8
+ var getOTPValue = function () { return (value ? value.toString().split('') : []); };
9
+ var isInputNum = inputType === 'number' || inputType === 'tel';
10
+ React.useEffect(function () {
11
+ inputRefs.current = inputRefs.current.slice(0, numInputs);
12
+ }, [numInputs]);
13
+ React.useEffect(function () {
14
+ var _a;
15
+ if (shouldAutoFocus) {
16
+ (_a = inputRefs.current[0]) === null || _a === void 0 ? void 0 : _a.focus();
17
+ }
18
+ }, [shouldAutoFocus]);
19
+ React.useEffect(function () {
20
+ var _a;
21
+ if (shouldBlurOnFinish && numInputs === (value === null || value === void 0 ? void 0 : value.length)) {
22
+ (_a = inputRefs.current[numInputs]) === null || _a === void 0 ? void 0 : _a.blur();
23
+ }
24
+ }, [shouldBlurOnFinish, numInputs, value]);
25
+ var getPlaceholderValue = function () {
26
+ if (typeof placeholder === 'string') {
27
+ if (placeholder.length === numInputs) {
28
+ return placeholder;
29
+ }
30
+ if (placeholder.length > 0) {
31
+ console.error('Length of the placeholder should be equal to the number of inputs.');
32
+ }
33
+ }
34
+ return undefined;
35
+ };
36
+ var isInputValueValid = function (value) {
37
+ var isTypeValid = isInputNum ? !isNaN(Number(value)) : typeof value === 'string';
38
+ return isTypeValid && value.trim().length === 1;
39
+ };
40
+ var handleChange = function (event) {
41
+ var value = event.target.value;
42
+ if (isInputValueValid(value)) {
43
+ changeCodeAtFocus(value);
44
+ focusInput(activeInput + 1);
45
+ }
46
+ };
47
+ var handleInputChange = function (event) {
48
+ var nativeEvent = event.nativeEvent;
49
+ var value = event.target.value;
50
+ if (!isInputValueValid(value)) {
51
+ // Pasting from the native autofill suggestion on a mobile device can pass
52
+ // the pasted string as one long input to one of the cells. This ensures
53
+ // that we handle the full input and not just the first character.
54
+ if (value.length === numInputs) {
55
+ var hasInvalidInput = value.split('').some(function (cellInput) { return !isInputValueValid(cellInput); });
56
+ if (!hasInvalidInput) {
57
+ handleOTPChange(value.split(''));
58
+ focusInput(numInputs - 1);
59
+ }
60
+ }
61
+ // @ts-expect-error - This was added previously to handle and edge case
62
+ // for dealing with keyCode "229 Unidentified" on Android. Check if this is
63
+ // still needed.
64
+ if (nativeEvent.data === null && nativeEvent.inputType === 'deleteContentBackward') {
65
+ event.preventDefault();
66
+ changeCodeAtFocus('');
67
+ focusInput(activeInput - 1);
68
+ }
69
+ // Clear the input if it's not valid value because firefox allows
70
+ // pasting non-numeric characters in a number type input
71
+ event.target.value = '';
72
+ }
73
+ };
74
+ var handleFocus = function (event) { return function (index) {
75
+ setActiveInput(index);
76
+ event.target.select();
77
+ }; };
78
+ var handleBlur = function () {
79
+ setActiveInput(activeInput - 1);
80
+ };
81
+ var handleKeyDown = function (event) {
82
+ var otp = getOTPValue();
83
+ if ([event.code, event.key].includes('Backspace')) {
84
+ event.preventDefault();
85
+ changeCodeAtFocus('');
86
+ focusInput(activeInput - 1);
87
+ }
88
+ else if (event.code === 'Delete') {
89
+ event.preventDefault();
90
+ changeCodeAtFocus('');
91
+ }
92
+ else if (event.code === 'ArrowLeft') {
93
+ event.preventDefault();
94
+ focusInput(activeInput - 1);
95
+ }
96
+ else if (event.code === 'ArrowRight') {
97
+ event.preventDefault();
98
+ focusInput(activeInput + 1);
99
+ }
100
+ // React does not trigger onChange when the same value is entered
101
+ // again. So we need to focus the next input manually in this case.
102
+ else if (event.key === otp[activeInput]) {
103
+ event.preventDefault();
104
+ focusInput(activeInput + 1);
105
+ }
106
+ else if (event.code === 'Spacebar' ||
107
+ event.code === 'Space' ||
108
+ event.code === 'ArrowUp' ||
109
+ event.code === 'ArrowDown') {
110
+ event.preventDefault();
111
+ }
112
+ };
113
+ var focusInput = function (index) {
114
+ var _a, _b;
115
+ var activeInput = Math.max(Math.min(numInputs - 1, index), 0);
116
+ if (inputRefs.current[activeInput]) {
117
+ (_a = inputRefs.current[activeInput]) === null || _a === void 0 ? void 0 : _a.focus();
118
+ (_b = inputRefs.current[activeInput]) === null || _b === void 0 ? void 0 : _b.select();
119
+ setActiveInput(activeInput);
120
+ }
121
+ };
122
+ var changeCodeAtFocus = function (value) {
123
+ var otp = getOTPValue();
124
+ otp[activeInput] = value[0];
125
+ handleOTPChange(otp);
126
+ };
127
+ var handleOTPChange = function (otp) {
128
+ var otpValue = otp.join('');
129
+ onChange(otpValue);
130
+ };
131
+ var handlePaste = function (event) {
132
+ var _a;
133
+ event.preventDefault();
134
+ var otp = getOTPValue();
135
+ var nextActiveInput = activeInput;
136
+ // Get pastedData in an array of max size (num of inputs - current position)
137
+ var pastedData = event.clipboardData
138
+ .getData('text/plain')
139
+ .slice(0, numInputs - activeInput)
140
+ .split('');
141
+ // Prevent pasting if the clipboard data contains non-numeric values for number inputs
142
+ if (isInputNum && pastedData.some(function (value) { return isNaN(Number(value)); })) {
143
+ return;
144
+ }
145
+ // Paste data from focused input onwards
146
+ for (var pos = 0; pos < numInputs; ++pos) {
147
+ if (pos >= activeInput && pastedData.length > 0) {
148
+ otp[pos] = (_a = pastedData.shift()) !== null && _a !== void 0 ? _a : '';
149
+ nextActiveInput++;
150
+ }
151
+ }
152
+ focusInput(nextActiveInput);
153
+ handleOTPChange(otp);
154
+ };
155
+ return (React.createElement("div", { style: Object.assign({ display: 'flex', alignItems: 'center' }, isStyleObject(containerStyle) && containerStyle), className: typeof containerStyle === 'string' ? containerStyle : undefined, onPaste: onPaste }, Array.from({ length: numInputs }, function (_, index) { return index; }).map(function (index) {
156
+ var _a, _b, _c;
157
+ return (React.createElement(React.Fragment, { key: index },
158
+ renderInput({
159
+ value: (_a = getOTPValue()[index]) !== null && _a !== void 0 ? _a : '',
160
+ placeholder: (_c = (_b = getPlaceholderValue()) === null || _b === void 0 ? void 0 : _b[index]) !== null && _c !== void 0 ? _c : undefined,
161
+ ref: function (element) { return (inputRefs.current[index] = element); },
162
+ onChange: handleChange,
163
+ onFocus: function (event) { return handleFocus(event)(index); },
164
+ onBlur: handleBlur,
165
+ onKeyDown: handleKeyDown,
166
+ onPaste: handlePaste,
167
+ autoComplete: 'off',
168
+ 'aria-label': "Please enter OTP character ".concat(index + 1),
169
+ style: Object.assign(!skipDefaultStyles ? { width: '1em', textAlign: 'center' } : {}, isStyleObject(inputStyle) ? inputStyle : {}),
170
+ className: typeof inputStyle === 'string' ? inputStyle : undefined,
171
+ type: inputType,
172
+ inputMode: isInputNum ? 'numeric' : 'text',
173
+ onInput: handleInputChange,
174
+ }, index),
175
+ index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator)));
176
+ })));
177
+ };
178
+
179
+ export { OTPInput as default };
180
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/index.tsx"],"sourcesContent":["import React from 'react';\r\n\r\ntype AllowedInputTypes = 'password' | 'text' | 'number' | 'tel';\r\n\r\ntype InputProps = Required<\r\n Pick<\r\n React.InputHTMLAttributes<HTMLInputElement>,\r\n | 'value'\r\n | 'onChange'\r\n | 'onFocus'\r\n | 'onBlur'\r\n | 'onKeyDown'\r\n | 'onPaste'\r\n | 'aria-label'\r\n | 'autoComplete'\r\n | 'style'\r\n | 'inputMode'\r\n | 'onInput'\r\n > & {\r\n ref: React.RefCallback<HTMLInputElement>;\r\n placeholder: string | undefined;\r\n className: string | undefined;\r\n type: AllowedInputTypes;\r\n }\r\n>;\r\n\r\ninterface OTPInputProps {\r\n /** Value of the OTP input */\r\n value?: string;\r\n /** Number of OTP inputs to be rendered */\r\n numInputs?: number;\r\n /** Blur after last char entered (close keyboard on mobile) */\r\n shouldBlurOnFinish?: boolean;\r\n /** Callback to be called when the OTP value changes */\r\n onChange: (otp: string) => void;\r\n /** Callback to be called when pasting content into the component */\r\n onPaste?: (event: React.ClipboardEvent<HTMLDivElement>) => void;\r\n /** Function to render the input */\r\n renderInput: (inputProps: InputProps, index: number) => React.ReactNode;\r\n /** Whether the first input should be auto focused */\r\n shouldAutoFocus?: boolean;\r\n /** Placeholder for the inputs */\r\n placeholder?: string;\r\n /** Function to render the separator */\r\n renderSeparator?: ((index: number) => React.ReactNode) | React.ReactNode;\r\n /** Style for the container */\r\n containerStyle?: React.CSSProperties | string;\r\n /** Style for the input */\r\n inputStyle?: React.CSSProperties | string;\r\n /** The type that will be passed to the input being rendered */\r\n inputType?: AllowedInputTypes;\r\n /** Do not apply the default styles to the inputs, will be removed in future versions */\r\n skipDefaultStyles?: boolean; // TODO: Remove in next major release\r\n}\r\n\r\nconst isStyleObject = (obj: unknown) => typeof obj === 'object' && obj !== null;\r\n\r\nconst OTPInput = ({\r\n value = '',\r\n numInputs = 4,\r\n onChange,\r\n onPaste,\r\n shouldBlurOnFinish,\r\n renderInput,\r\n shouldAutoFocus = false,\r\n inputType = 'text',\r\n renderSeparator,\r\n placeholder,\r\n containerStyle,\r\n inputStyle,\r\n skipDefaultStyles = false,\r\n}: OTPInputProps) => {\r\n const [activeInput, setActiveInput] = React.useState(0);\r\n const inputRefs = React.useRef<Array<HTMLInputElement | null>>([]);\r\n\r\n const getOTPValue = () => (value ? value.toString().split('') : []);\r\n\r\n const isInputNum = inputType === 'number' || inputType === 'tel';\r\n\r\n React.useEffect(() => {\r\n inputRefs.current = inputRefs.current.slice(0, numInputs);\r\n }, [numInputs]);\r\n\r\n React.useEffect(() => {\r\n if (shouldAutoFocus) {\r\n inputRefs.current[0]?.focus();\r\n }\r\n }, [shouldAutoFocus]);\r\n\r\n React.useEffect(() => {\r\n if (shouldBlurOnFinish && numInputs === value?.length) {\r\n inputRefs.current[numInputs]?.blur();\r\n }\r\n }, [shouldBlurOnFinish, numInputs, value]);\r\n\r\n const getPlaceholderValue = () => {\r\n if (typeof placeholder === 'string') {\r\n if (placeholder.length === numInputs) {\r\n return placeholder;\r\n }\r\n\r\n if (placeholder.length > 0) {\r\n console.error('Length of the placeholder should be equal to the number of inputs.');\r\n }\r\n }\r\n return undefined;\r\n };\r\n\r\n const isInputValueValid = (value: string) => {\r\n const isTypeValid = isInputNum ? !isNaN(Number(value)) : typeof value === 'string';\r\n return isTypeValid && value.trim().length === 1;\r\n };\r\n\r\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const { value } = event.target;\r\n\r\n if (isInputValueValid(value)) {\r\n changeCodeAtFocus(value);\r\n focusInput(activeInput + 1);\r\n }\r\n };\r\n\r\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n const { nativeEvent } = event;\r\n const value = event.target.value;\r\n\r\n if (!isInputValueValid(value)) {\r\n // Pasting from the native autofill suggestion on a mobile device can pass\r\n // the pasted string as one long input to one of the cells. This ensures\r\n // that we handle the full input and not just the first character.\r\n if (value.length === numInputs) {\r\n const hasInvalidInput = value.split('').some((cellInput) => !isInputValueValid(cellInput));\r\n if (!hasInvalidInput) {\r\n handleOTPChange(value.split(''));\r\n focusInput(numInputs - 1);\r\n }\r\n }\r\n\r\n // @ts-expect-error - This was added previously to handle and edge case\r\n // for dealing with keyCode \"229 Unidentified\" on Android. Check if this is\r\n // still needed.\r\n if (nativeEvent.data === null && nativeEvent.inputType === 'deleteContentBackward') {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n focusInput(activeInput - 1);\r\n }\r\n\r\n // Clear the input if it's not valid value because firefox allows\r\n // pasting non-numeric characters in a number type input\r\n event.target.value = '';\r\n }\r\n };\r\n\r\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => (index: number) => {\r\n setActiveInput(index);\r\n event.target.select();\r\n };\r\n\r\n const handleBlur = () => {\r\n setActiveInput(activeInput - 1);\r\n };\r\n\r\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\r\n const otp = getOTPValue();\r\n if ([event.code, event.key].includes('Backspace')) {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n focusInput(activeInput - 1);\r\n } else if (event.code === 'Delete') {\r\n event.preventDefault();\r\n changeCodeAtFocus('');\r\n } else if (event.code === 'ArrowLeft') {\r\n event.preventDefault();\r\n focusInput(activeInput - 1);\r\n } else if (event.code === 'ArrowRight') {\r\n event.preventDefault();\r\n focusInput(activeInput + 1);\r\n }\r\n // React does not trigger onChange when the same value is entered\r\n // again. So we need to focus the next input manually in this case.\r\n else if (event.key === otp[activeInput]) {\r\n event.preventDefault();\r\n focusInput(activeInput + 1);\r\n } else if (\r\n event.code === 'Spacebar' ||\r\n event.code === 'Space' ||\r\n event.code === 'ArrowUp' ||\r\n event.code === 'ArrowDown'\r\n ) {\r\n event.preventDefault();\r\n }\r\n };\r\n\r\n const focusInput = (index: number) => {\r\n const activeInput = Math.max(Math.min(numInputs - 1, index), 0);\r\n\r\n if (inputRefs.current[activeInput]) {\r\n inputRefs.current[activeInput]?.focus();\r\n inputRefs.current[activeInput]?.select();\r\n setActiveInput(activeInput);\r\n }\r\n };\r\n\r\n const changeCodeAtFocus = (value: string) => {\r\n const otp = getOTPValue();\r\n otp[activeInput] = value[0];\r\n handleOTPChange(otp);\r\n };\r\n\r\n const handleOTPChange = (otp: Array<string>) => {\r\n const otpValue = otp.join('');\r\n onChange(otpValue);\r\n };\r\n\r\n const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {\r\n event.preventDefault();\r\n\r\n const otp = getOTPValue();\r\n let nextActiveInput = activeInput;\r\n\r\n // Get pastedData in an array of max size (num of inputs - current position)\r\n const pastedData = event.clipboardData\r\n .getData('text/plain')\r\n .slice(0, numInputs - activeInput)\r\n .split('');\r\n\r\n // Prevent pasting if the clipboard data contains non-numeric values for number inputs\r\n if (isInputNum && pastedData.some((value) => isNaN(Number(value)))) {\r\n return;\r\n }\r\n\r\n // Paste data from focused input onwards\r\n for (let pos = 0; pos < numInputs; ++pos) {\r\n if (pos >= activeInput && pastedData.length > 0) {\r\n otp[pos] = pastedData.shift() ?? '';\r\n nextActiveInput++;\r\n }\r\n }\r\n\r\n focusInput(nextActiveInput);\r\n handleOTPChange(otp);\r\n };\r\n\r\n return (\r\n <div\r\n style={Object.assign({ display: 'flex', alignItems: 'center' }, isStyleObject(containerStyle) && containerStyle)}\r\n className={typeof containerStyle === 'string' ? containerStyle : undefined}\r\n onPaste={onPaste}\r\n >\r\n {Array.from({ length: numInputs }, (_, index) => index).map((index) => (\r\n <React.Fragment key={index}>\r\n {renderInput(\r\n {\r\n value: getOTPValue()[index] ?? '',\r\n placeholder: getPlaceholderValue()?.[index] ?? undefined,\r\n ref: (element) => (inputRefs.current[index] = element),\r\n onChange: handleChange,\r\n onFocus: (event) => handleFocus(event)(index),\r\n onBlur: handleBlur,\r\n onKeyDown: handleKeyDown,\r\n onPaste: handlePaste,\r\n autoComplete: 'off',\r\n 'aria-label': `Please enter OTP character ${index + 1}`,\r\n style: Object.assign(\r\n !skipDefaultStyles ? ({ width: '1em', textAlign: 'center' } as const) : {},\r\n isStyleObject(inputStyle) ? inputStyle : {}\r\n ),\r\n className: typeof inputStyle === 'string' ? inputStyle : undefined,\r\n type: inputType,\r\n inputMode: isInputNum ? 'numeric' : 'text',\r\n onInput: handleInputChange,\r\n },\r\n index\r\n )}\r\n {index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator)}\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n );\r\n};\r\n\r\nexport type { OTPInputProps, InputProps, AllowedInputTypes };\r\nexport default OTPInput;\r\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@matin_mortazavi/react-otp-input",
3
+ "version": "1.0.0",
4
+ "description": "A fully customizable, one-time password input component for the web built with React",
5
+ "main": "lib/index.js",
6
+ "module": "lib/index.esm.js",
7
+ "types": "lib/index.d.ts",
8
+ "scripts": {
9
+ "build": "rollup -c",
10
+ "format": "prettier --write \"**/*.{html,css,js,jsx}\"",
11
+ "lint": "eslint 'src/**/*.{js,jsx}' --quiet",
12
+ "lint:fix": "eslint 'src/**/*.{js,jsx}' --fix",
13
+ "prepublishOnly": "rm -rf dist && npm run build",
14
+ "example:build": "cd example && yarn && yarn build"
15
+ },
16
+ "keywords": [
17
+ "otp",
18
+ "input",
19
+ "code",
20
+ "passcode",
21
+ "component"
22
+ ],
23
+ "peerDependencies": {
24
+ "react": ">=16.8.6 || ^17.0.0 || ^18.0.0",
25
+ "react-dom": ">=16.8.6 || ^17.0.0 || ^18.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@rollup/plugin-typescript": "11.0.0",
29
+ "@types/react": "18.0.28",
30
+ "@types/react-dom": "18.0.11",
31
+ "@typescript-eslint/eslint-plugin": "5.55.0",
32
+ "@typescript-eslint/parser": "5.55.0",
33
+ "concurrently": "6.2.0",
34
+ "eslint": "7.27.0",
35
+ "eslint-config-prettier": "8.3.0",
36
+ "eslint-plugin-import": "2.23.3",
37
+ "eslint-plugin-jsx-a11y": "6.4.1",
38
+ "eslint-plugin-prettier": "3.4.0",
39
+ "eslint-plugin-react": "7.23.2",
40
+ "eslint-plugin-react-hooks": "4.2.0",
41
+ "gh-pages": "3.2.3",
42
+ "prettier": "2.3.0",
43
+ "react": "18.2.0",
44
+ "react-dom": "18.2.0",
45
+ "rollup": "2.79.1",
46
+ "rollup-plugin-peer-deps-external": "2.2.4",
47
+ "typescript": "5.0.2"
48
+ },
49
+ "author": "Matin Mortazavi",
50
+ "license": "MIT",
51
+ "homepage": "https://github.com/matin-mortazavi/react-otp-input",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/matin-mortazavi/react-otp-input"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/matin-mortazavi/react-otp-input/issues"
58
+ }
59
+ }
@@ -0,0 +1,19 @@
1
+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';
2
+ import typescript from '@rollup/plugin-typescript';
3
+
4
+ export default {
5
+ input: 'src/index.tsx',
6
+ output: [
7
+ {
8
+ file: 'lib/index.cjs',
9
+ format: 'cjs',
10
+ sourcemap: true,
11
+ },
12
+ {
13
+ file: 'lib/index.esm.js',
14
+ format: 'esm',
15
+ sourcemap: true,
16
+ },
17
+ ],
18
+ plugins: [peerDepsExternal(), typescript()],
19
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "lib/esm",
4
+ "module": "esnext",
5
+ "declaration": true,
6
+ "target": "es5",
7
+ "lib": ["es6", "dom", "es2016", "es2017"],
8
+ "jsx": "react",
9
+ "moduleResolution": "node",
10
+ "noUnusedLocals": true,
11
+ "noUnusedParameters": true,
12
+ "esModuleInterop": true,
13
+ "noImplicitReturns": true,
14
+ "noImplicitThis": true,
15
+ "noImplicitAny": true,
16
+ "strictNullChecks": true,
17
+ "allowSyntheticDefaultImports": true
18
+ },
19
+ "include": ["src"],
20
+ "exclude": ["node_modules"]
21
+ }