@matin_mortazavi/react-otp-input 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +251 -0
- package/example/index.html +14 -0
- package/example/package.json +23 -0
- package/example/src/App.tsx +137 -0
- package/example/src/index.css +216 -0
- package/example/src/main.tsx +10 -0
- package/example/src/vite-env.d.ts +1 -0
- package/example/tsconfig.json +21 -0
- package/example/tsconfig.node.json +9 -0
- package/example/vite.config.ts +8 -0
- package/example/yarn.lock +787 -0
- package/lib/index.cjs +186 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.ts +39 -0
- package/lib/index.esm.js +180 -0
- package/lib/index.esm.js.map +1 -0
- package/package.json +59 -0
- package/rollup.config.js +19 -0
- package/tsconfig.json +21 -0
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;
|
package/lib/index.esm.js
ADDED
@@ -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
|
+
}
|
package/rollup.config.js
ADDED
@@ -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
|
+
}
|