mimir-ui-kit 0.0.17 → 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,12 @@
|
|
1
1
|
import { TInputProps } from '../Input';
|
2
2
|
|
3
|
-
|
3
|
+
/**
|
4
|
+
* Компонент ввода одноразового пароля (OTP).
|
5
|
+
*
|
6
|
+
* Компонент представляет собой набор вводов, каждый из которых может содержать только цифры.
|
7
|
+
* Пользователь может вводить цифры в каждый ввод, и при вводе каждой цифры происходит автоматическое переключение на следующий ввод.
|
8
|
+
*/
|
9
|
+
export declare const OtpInput: import('react').ForwardRefExoticComponent<Omit<TInputProps, "label" | "onChange"> & {
|
4
10
|
value?: string;
|
5
11
|
/**
|
6
12
|
* Количество полей ввода.
|
@@ -14,15 +20,4 @@ type TProps = Omit<TInputProps, 'onChange' | 'label'> & {
|
|
14
20
|
* Флаг, показывающий нужно ли отображать разделитель между вводами.
|
15
21
|
*/
|
16
22
|
needSeparator?: boolean;
|
17
|
-
}
|
18
|
-
/**
|
19
|
-
* Компонент ввода одноразового пароля (OTP).
|
20
|
-
*
|
21
|
-
* Компонент представляет собой набор вводов, каждый из которых может содержать только цифры.
|
22
|
-
* Пользователь может вводить цифры в каждый ввод, и при вводе каждой цифры происходит автоматическое переключение на следующий ввод.
|
23
|
-
*/
|
24
|
-
export declare const OtpInput: {
|
25
|
-
({ value, valueLength, needSeparator, onChange, ...props }: TProps): import("react/jsx-runtime").JSX.Element;
|
26
|
-
displayName: string;
|
27
|
-
};
|
28
|
-
export {};
|
23
|
+
} & import('react').RefAttributes<unknown>>;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
2
|
-
import { useRef, useMemo, Fragment } from "react";
|
2
|
+
import { forwardRef, useRef, useMemo, Fragment } from "react";
|
3
3
|
import { c as classNames } from "../../index-CweZ_OcN.js";
|
4
4
|
import { Input } from "../Input/Input.js";
|
5
5
|
import { RE_DIGIT, ITEMS_PER_SEPARATOR, DEFAULT_VALUE_LENGTH } from "./constants.js";
|
@@ -12,121 +12,123 @@ const cls = {
|
|
12
12
|
input,
|
13
13
|
separator
|
14
14
|
};
|
15
|
-
const OtpInput = (
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
const
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
15
|
+
const OtpInput = forwardRef(
|
16
|
+
({
|
17
|
+
value = "",
|
18
|
+
valueLength = DEFAULT_VALUE_LENGTH,
|
19
|
+
needSeparator = true,
|
20
|
+
onChange,
|
21
|
+
...props
|
22
|
+
}) => {
|
23
|
+
const inputRefs = useRef([]);
|
24
|
+
const valueItems = useMemo(() => {
|
25
|
+
const valueArray = value.split("");
|
26
|
+
const items = [];
|
27
|
+
for (let i = 0; i < valueLength; i++) {
|
28
|
+
const char = valueArray[i];
|
29
|
+
if (RE_DIGIT.test(char)) {
|
30
|
+
items.push(char);
|
31
|
+
} else {
|
32
|
+
items.push("");
|
33
|
+
}
|
32
34
|
}
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
}
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
(_a = inputRefs.current[index - 1]) == null ? void 0 : _a.focus();
|
46
|
-
}
|
47
|
-
};
|
48
|
-
const handleChange = (e, index) => {
|
49
|
-
const target = e.target;
|
50
|
-
let targetValue = target.value.trim();
|
51
|
-
const isTargetValueDigit = RE_DIGIT.test(targetValue);
|
52
|
-
if (!isTargetValueDigit && targetValue !== "") {
|
53
|
-
return;
|
54
|
-
}
|
55
|
-
const nextInputEl = inputRefs.current[index + 1];
|
56
|
-
if (!isTargetValueDigit && nextInputEl && nextInputEl.value !== "") {
|
57
|
-
return;
|
58
|
-
}
|
59
|
-
targetValue = isTargetValueDigit ? targetValue : " ";
|
60
|
-
const targetValueLength = targetValue.length;
|
61
|
-
if (targetValueLength === 1) {
|
62
|
-
const newValue = value.substring(0, index) + targetValue + value.substring(index + 1);
|
63
|
-
onChange == null ? void 0 : onChange(newValue);
|
64
|
-
if (isTargetValueDigit) {
|
65
|
-
handleFocusToNextInput(index);
|
35
|
+
return items;
|
36
|
+
}, [value, valueLength]);
|
37
|
+
const handleFocusToNextInput = (index) => {
|
38
|
+
var _a;
|
39
|
+
if (index < valueLength - 1) {
|
40
|
+
(_a = inputRefs.current[index + 1]) == null ? void 0 : _a.focus();
|
41
|
+
}
|
42
|
+
};
|
43
|
+
const handleFocusToPrevInput = (index) => {
|
44
|
+
var _a;
|
45
|
+
if (index > 0) {
|
46
|
+
(_a = inputRefs.current[index - 1]) == null ? void 0 : _a.focus();
|
66
47
|
}
|
67
|
-
}
|
68
|
-
|
69
|
-
target.
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
const target = e.target;
|
75
|
-
switch (key) {
|
76
|
-
case "ArrowRight":
|
77
|
-
case "ArrowDown": {
|
78
|
-
e.preventDefault();
|
79
|
-
return handleFocusToNextInput(index);
|
48
|
+
};
|
49
|
+
const handleChange = (e, index) => {
|
50
|
+
const target = e.target;
|
51
|
+
let targetValue = target.value.trim();
|
52
|
+
const isTargetValueDigit = RE_DIGIT.test(targetValue);
|
53
|
+
if (!isTargetValueDigit && targetValue !== "") {
|
54
|
+
return;
|
80
55
|
}
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
return handleFocusToPrevInput(index);
|
56
|
+
const nextInputEl = inputRefs.current[index + 1];
|
57
|
+
if (!isTargetValueDigit && nextInputEl && nextInputEl.value !== "") {
|
58
|
+
return;
|
85
59
|
}
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
onChange == null ? void 0 : onChange(newValue);
|
94
|
-
handleFocusToPrevInput(index);
|
95
|
-
};
|
96
|
-
const handleFocus = (e, index) => {
|
97
|
-
const target = e.target;
|
98
|
-
const prevInputEl = inputRefs.current[index - 1];
|
99
|
-
if (prevInputEl && prevInputEl.value === "") {
|
100
|
-
prevInputEl.focus();
|
101
|
-
}
|
102
|
-
target.setSelectionRange(0, target.value.length);
|
103
|
-
};
|
104
|
-
return /* @__PURE__ */ jsx("div", { className: classNames(cls.otp), children: valueItems.map((digit, idx) => {
|
105
|
-
const nextIndex = idx + 1;
|
106
|
-
const showSeparator = needSeparator && nextIndex % ITEMS_PER_SEPARATOR === 0 && nextIndex !== valueItems.length;
|
107
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
108
|
-
/* @__PURE__ */ jsx(
|
109
|
-
Input,
|
110
|
-
{
|
111
|
-
ref: (el) => inputRefs.current[idx] = el,
|
112
|
-
type: "text",
|
113
|
-
inputMode: "numeric",
|
114
|
-
autoComplete: "one-time-code",
|
115
|
-
pattern: "\\d{1}",
|
116
|
-
maxLength: 1,
|
117
|
-
value: digit,
|
118
|
-
className: cls.input,
|
119
|
-
wrapperClassName: cls["input-wrapper"],
|
120
|
-
onChange: (e) => handleChange(e, idx),
|
121
|
-
onKeyDown: (e) => handleKeyDown(e, idx),
|
122
|
-
onFocus: (e) => handleFocus(e, idx),
|
123
|
-
...props
|
60
|
+
targetValue = isTargetValueDigit ? targetValue : " ";
|
61
|
+
const targetValueLength = targetValue.length;
|
62
|
+
if (targetValueLength === 1) {
|
63
|
+
const newValue = value.substring(0, index) + targetValue + value.substring(index + 1);
|
64
|
+
onChange == null ? void 0 : onChange(newValue);
|
65
|
+
if (isTargetValueDigit) {
|
66
|
+
handleFocusToNextInput(index);
|
124
67
|
}
|
125
|
-
)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
};
|
68
|
+
} else if (targetValueLength === valueLength) {
|
69
|
+
onChange == null ? void 0 : onChange(targetValue);
|
70
|
+
target.blur();
|
71
|
+
}
|
72
|
+
};
|
73
|
+
const handleKeyDown = (e, index) => {
|
74
|
+
const { key } = e;
|
75
|
+
const target = e.target;
|
76
|
+
switch (key) {
|
77
|
+
case "ArrowRight":
|
78
|
+
case "ArrowDown": {
|
79
|
+
e.preventDefault();
|
80
|
+
return handleFocusToNextInput(index);
|
81
|
+
}
|
82
|
+
case "ArrowLeft":
|
83
|
+
case "ArrowUp": {
|
84
|
+
e.preventDefault();
|
85
|
+
return handleFocusToPrevInput(index);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
const targetValue = target.value;
|
89
|
+
target.setSelectionRange(0, targetValue.length);
|
90
|
+
if (e.key !== "Backspace" || targetValue !== "") {
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
const newValue = `${value.substring(0, index - 1)} ${value.substring(index)}`;
|
94
|
+
onChange == null ? void 0 : onChange(newValue);
|
95
|
+
handleFocusToPrevInput(index);
|
96
|
+
};
|
97
|
+
const handleFocus = (e, index) => {
|
98
|
+
const target = e.target;
|
99
|
+
const prevInputEl = inputRefs.current[index - 1];
|
100
|
+
if (prevInputEl && prevInputEl.value === "") {
|
101
|
+
prevInputEl.focus();
|
102
|
+
}
|
103
|
+
target.setSelectionRange(0, target.value.length);
|
104
|
+
};
|
105
|
+
return /* @__PURE__ */ jsx("div", { className: classNames(cls.otp), children: valueItems.map((digit, idx) => {
|
106
|
+
const nextIndex = idx + 1;
|
107
|
+
const showSeparator = needSeparator && nextIndex % ITEMS_PER_SEPARATOR === 0 && nextIndex !== valueItems.length;
|
108
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
109
|
+
/* @__PURE__ */ jsx(
|
110
|
+
Input,
|
111
|
+
{
|
112
|
+
ref: (el) => inputRefs.current[idx] = el,
|
113
|
+
type: "text",
|
114
|
+
inputMode: "numeric",
|
115
|
+
autoComplete: "one-time-code",
|
116
|
+
pattern: "\\d{1}",
|
117
|
+
maxLength: 1,
|
118
|
+
value: digit,
|
119
|
+
className: cls.input,
|
120
|
+
wrapperClassName: cls["input-wrapper"],
|
121
|
+
onChange: (e) => handleChange(e, idx),
|
122
|
+
onKeyDown: (e) => handleKeyDown(e, idx),
|
123
|
+
onFocus: (e) => handleFocus(e, idx),
|
124
|
+
...props
|
125
|
+
}
|
126
|
+
),
|
127
|
+
showSeparator && /* @__PURE__ */ jsx("span", { className: classNames(cls.separator) })
|
128
|
+
] }, idx);
|
129
|
+
}) });
|
130
|
+
}
|
131
|
+
);
|
130
132
|
OtpInput.displayName = "OtpInput";
|
131
133
|
export {
|
132
134
|
OtpInput
|