@ozen-ui/kit 0.63.0 → 0.64.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/InputOTP/package.json +5 -0
- package/__inner__/cjs/components/InputOTP/InputOTP.css +60 -0
- package/__inner__/cjs/components/InputOTP/InputOTP.d.ts +4 -0
- package/__inner__/cjs/components/InputOTP/InputOTP.js +179 -0
- package/__inner__/cjs/components/InputOTP/constants.d.ts +8 -0
- package/__inner__/cjs/components/InputOTP/constants.js +13 -0
- package/__inner__/cjs/components/InputOTP/helper.d.ts +13 -0
- package/__inner__/cjs/components/InputOTP/helper.js +87 -0
- package/__inner__/cjs/components/InputOTP/hooks/index.d.ts +1 -0
- package/__inner__/cjs/components/InputOTP/hooks/index.js +4 -0
- package/__inner__/cjs/components/InputOTP/hooks/useInputOTPEvents.d.ts +20 -0
- package/__inner__/cjs/components/InputOTP/hooks/useInputOTPEvents.js +183 -0
- package/__inner__/cjs/components/InputOTP/index.d.ts +3 -0
- package/__inner__/cjs/components/InputOTP/index.js +6 -0
- package/__inner__/cjs/components/InputOTP/presets.d.ts +12 -0
- package/__inner__/cjs/components/InputOTP/presets.js +27 -0
- package/__inner__/cjs/components/InputOTP/types.d.ts +101 -0
- package/__inner__/cjs/components/InputOTP/types.js +7 -0
- package/__inner__/cjs/components/Tabs/Tabs.js +6 -2
- package/__inner__/cjs/components/ThemeProvider/types.d.ts +1 -0
- package/__inner__/cjs/hooks/useStoredValue/index.d.ts +3 -0
- package/__inner__/cjs/hooks/useStoredValue/index.js +6 -0
- package/__inner__/cjs/hooks/useStoredValue/types.d.ts +2 -0
- package/__inner__/cjs/hooks/useStoredValue/types.js +2 -0
- package/__inner__/cjs/hooks/useStoredValue/useStoredValue.d.ts +4 -0
- package/__inner__/cjs/hooks/useStoredValue/useStoredValue.js +16 -0
- package/__inner__/cjs/hooks/useStoredValue/utils.d.ts +2 -0
- package/__inner__/cjs/hooks/useStoredValue/utils.js +8 -0
- package/__inner__/cjs/utils/array/create-empty/createEmptyArray.d.ts +1 -0
- package/__inner__/cjs/utils/array/create-empty/createEmptyArray.js +8 -0
- package/__inner__/cjs/utils/array/create-empty/index.d.ts +1 -0
- package/__inner__/cjs/utils/array/create-empty/index.js +4 -0
- package/__inner__/cjs/utils/array/create-filled/createFilledArray.d.ts +1 -0
- package/__inner__/cjs/utils/array/create-filled/createFilledArray.js +7 -0
- package/__inner__/cjs/utils/array/create-filled/index.d.ts +1 -0
- package/__inner__/cjs/utils/array/create-filled/index.js +4 -0
- package/__inner__/cjs/utils/array/index.d.ts +2 -0
- package/__inner__/cjs/utils/array/index.js +5 -0
- package/__inner__/cjs/utils/isFunction.d.ts +1 -0
- package/__inner__/cjs/utils/isFunction.js +8 -0
- package/__inner__/esm/components/InputOTP/InputOTP.css +60 -0
- package/__inner__/esm/components/InputOTP/InputOTP.d.ts +4 -0
- package/__inner__/esm/components/InputOTP/InputOTP.js +176 -0
- package/__inner__/esm/components/InputOTP/constants.d.ts +8 -0
- package/__inner__/esm/components/InputOTP/constants.js +10 -0
- package/__inner__/esm/components/InputOTP/helper.d.ts +13 -0
- package/__inner__/esm/components/InputOTP/helper.js +79 -0
- package/__inner__/esm/components/InputOTP/hooks/index.d.ts +1 -0
- package/__inner__/esm/components/InputOTP/hooks/index.js +1 -0
- package/__inner__/esm/components/InputOTP/hooks/useInputOTPEvents.d.ts +20 -0
- package/__inner__/esm/components/InputOTP/hooks/useInputOTPEvents.js +179 -0
- package/__inner__/esm/components/InputOTP/index.d.ts +3 -0
- package/__inner__/esm/components/InputOTP/index.js +3 -0
- package/__inner__/esm/components/InputOTP/presets.d.ts +12 -0
- package/__inner__/esm/components/InputOTP/presets.js +24 -0
- package/__inner__/esm/components/InputOTP/types.d.ts +101 -0
- package/__inner__/esm/components/InputOTP/types.js +4 -0
- package/__inner__/esm/components/Tabs/Tabs.js +6 -2
- package/__inner__/esm/components/ThemeProvider/types.d.ts +1 -0
- package/__inner__/esm/hooks/useStoredValue/index.d.ts +3 -0
- package/__inner__/esm/hooks/useStoredValue/index.js +3 -0
- package/__inner__/esm/hooks/useStoredValue/types.d.ts +2 -0
- package/__inner__/esm/hooks/useStoredValue/types.js +1 -0
- package/__inner__/esm/hooks/useStoredValue/useStoredValue.d.ts +4 -0
- package/__inner__/esm/hooks/useStoredValue/useStoredValue.js +13 -0
- package/__inner__/esm/hooks/useStoredValue/utils.d.ts +2 -0
- package/__inner__/esm/hooks/useStoredValue/utils.js +5 -0
- package/__inner__/esm/utils/array/create-empty/createEmptyArray.d.ts +1 -0
- package/__inner__/esm/utils/array/create-empty/createEmptyArray.js +4 -0
- package/__inner__/esm/utils/array/create-empty/index.d.ts +1 -0
- package/__inner__/esm/utils/array/create-empty/index.js +1 -0
- package/__inner__/esm/utils/array/create-filled/createFilledArray.d.ts +1 -0
- package/__inner__/esm/utils/array/create-filled/createFilledArray.js +3 -0
- package/__inner__/esm/utils/array/create-filled/index.d.ts +1 -0
- package/__inner__/esm/utils/array/create-filled/index.js +1 -0
- package/__inner__/esm/utils/array/index.d.ts +2 -0
- package/__inner__/esm/utils/array/index.js +2 -0
- package/__inner__/esm/utils/isFunction.d.ts +1 -0
- package/__inner__/esm/utils/isFunction.js +4 -0
- package/package.json +4 -4
- package/useStoredValue/package.json +5 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { ComponentPropsWithRef, ElementType } from 'react';
|
|
2
|
+
import type { PolymorphicComponentPropsWithRef } from '../../utils/polymorphicComponentWithRef';
|
|
3
|
+
import type { FIELD_CONTROL_DEFAULT_TAG, FieldControlBaseProps } from '../FieldControl';
|
|
4
|
+
import type { FieldInputProps } from '../FieldInput';
|
|
5
|
+
import type { INPUT_OTP_DEFAULT_TAG } from './constants';
|
|
6
|
+
export declare const inputOTPAutoCompleteMode: readonly ["firstOnly", "all"];
|
|
7
|
+
export type InputOTPAutoCompleteMode = (typeof inputOTPAutoCompleteMode)[number];
|
|
8
|
+
export declare const inputOTPSizeVariant: readonly ["s", "m"];
|
|
9
|
+
export type InputOTPSizeVariant = (typeof inputOTPSizeVariant)[number];
|
|
10
|
+
export type InputOTPValidate = (value: string) => boolean;
|
|
11
|
+
export type InputOTPRawValue = string[];
|
|
12
|
+
export type InputOTPValue = InputOTPRawValue | string;
|
|
13
|
+
export type InputOTPOnChange = (value: string, rawValue: InputOTPRawValue, maskedValue: string, maskedRawValue: InputOTPRawValue) => void;
|
|
14
|
+
export type InputOTPOnFinish = (value: string, rawValue: InputOTPRawValue, maskedValue: string, maskedRawValue: InputOTPRawValue) => void;
|
|
15
|
+
export type InputOTPInputs = HTMLInputElement[];
|
|
16
|
+
export type InputOTPInputProps = FieldInputProps;
|
|
17
|
+
export type InputOTPCalculatedInput = {
|
|
18
|
+
/** Значение input */
|
|
19
|
+
value: string;
|
|
20
|
+
/** Необработанное input */
|
|
21
|
+
rawValue: string;
|
|
22
|
+
/** Флаг: это предыдущий input */
|
|
23
|
+
isPrevious: boolean;
|
|
24
|
+
/** Флаг: это следующий input */
|
|
25
|
+
isNext: boolean;
|
|
26
|
+
/** Флаг: это текущий input */
|
|
27
|
+
isCurrentInput: boolean;
|
|
28
|
+
/** Флаг: это последний input */
|
|
29
|
+
isLast: boolean;
|
|
30
|
+
/** Флаг: input отключен */
|
|
31
|
+
isDisabled: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type InputOTPMask = string | ((value: string, index: number) => string);
|
|
34
|
+
export type InputOTPFinishBehaviorContext = {
|
|
35
|
+
/** Флаг: Поле полностью заполнено */
|
|
36
|
+
isFullFilled: boolean;
|
|
37
|
+
/** Значение */
|
|
38
|
+
value: string;
|
|
39
|
+
/** Необработанное значение */
|
|
40
|
+
rawValue: InputOTPRawValue;
|
|
41
|
+
/** Значение с маской */
|
|
42
|
+
maskedValue: string;
|
|
43
|
+
/** Необработанное значение с маской */
|
|
44
|
+
maskedRawValue: InputOTPRawValue;
|
|
45
|
+
/** Флаг: Это изменение на последнем input'е */
|
|
46
|
+
isChangeOnLastInput: boolean;
|
|
47
|
+
/** index input'а, на котором произошло изменение */
|
|
48
|
+
inputIndex: number;
|
|
49
|
+
/** Флаг: Был нажат enter */
|
|
50
|
+
isEnter: boolean;
|
|
51
|
+
};
|
|
52
|
+
export type InputOTPFinishBehavior = (context: InputOTPFinishBehaviorContext) => boolean;
|
|
53
|
+
export type InputOTPDynamicInputParameter<Parameter> = Parameter | ((calculatedInput: InputOTPCalculatedInput, index: number) => Parameter);
|
|
54
|
+
export type InputOTPBaseProps = {
|
|
55
|
+
/** Длина кода */
|
|
56
|
+
length: number;
|
|
57
|
+
/** Значение */
|
|
58
|
+
value?: InputOTPValue;
|
|
59
|
+
/** Значение по умолчанию */
|
|
60
|
+
defaultValue?: InputOTPValue;
|
|
61
|
+
/** Обработчик события на изменение значения поля */
|
|
62
|
+
onChange?: InputOTPOnChange;
|
|
63
|
+
/** Обработчик события на завершение ввода */
|
|
64
|
+
onFinish?: InputOTPOnFinish;
|
|
65
|
+
/** Маска значения */
|
|
66
|
+
mask?: InputOTPMask;
|
|
67
|
+
/** autoComplete */
|
|
68
|
+
autoComplete?: InputOTPInputProps['autoComplete'];
|
|
69
|
+
/**
|
|
70
|
+
* Мод autoComplete.
|
|
71
|
+
* В зависимости от режима, autoComplete будет устанавливаться разным input
|
|
72
|
+
*/
|
|
73
|
+
autoCompleteMode?: InputOTPAutoCompleteMode;
|
|
74
|
+
/** Если `true` переводит поле в состояние ошибки */
|
|
75
|
+
error?: boolean;
|
|
76
|
+
/** Если `true` делает элемент неактивным */
|
|
77
|
+
disabled?: boolean;
|
|
78
|
+
/** Функция-валидатор */
|
|
79
|
+
validate?: InputOTPValidate;
|
|
80
|
+
/** Размер */
|
|
81
|
+
size?: InputOTPSizeVariant;
|
|
82
|
+
/** Лейбл */
|
|
83
|
+
ariaLabel?: string;
|
|
84
|
+
/** Если `true` отключает обводку */
|
|
85
|
+
disableStroke?: boolean;
|
|
86
|
+
/** Подсказка. Отображается, когда значение не введено */
|
|
87
|
+
placeholder?: InputOTPDynamicInputParameter<string>;
|
|
88
|
+
/** Свойства Field */
|
|
89
|
+
fieldProps?: InputOTPDynamicInputParameter<PolymorphicComponentPropsWithRef<FieldControlBaseProps, typeof FIELD_CONTROL_DEFAULT_TAG>>;
|
|
90
|
+
/** Свойства Input */
|
|
91
|
+
inputProps?: InputOTPDynamicInputParameter<FieldInputProps>;
|
|
92
|
+
/** Свойства InputContainer */
|
|
93
|
+
inputContainerProps?: InputOTPDynamicInputParameter<ComponentPropsWithRef<'div'> & {
|
|
94
|
+
'data-testid'?: string;
|
|
95
|
+
}>;
|
|
96
|
+
/** Функция, которая определяет поведение финиша */
|
|
97
|
+
finishBehavior?: InputOTPFinishBehavior;
|
|
98
|
+
/** data-атрибут для тестирования */
|
|
99
|
+
'data-testid'?: string;
|
|
100
|
+
};
|
|
101
|
+
export type InputOTPProps<As extends ElementType = typeof INPUT_OTP_DEFAULT_TAG> = PolymorphicComponentPropsWithRef<InputOTPBaseProps, As>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.inputOTPSizeVariant = exports.inputOTPAutoCompleteMode = void 0;
|
|
4
|
+
// ---- AUTO-COMPLETE MODE ----
|
|
5
|
+
exports.inputOTPAutoCompleteMode = ['firstOnly', 'all'];
|
|
6
|
+
// ---- SIZE ----
|
|
7
|
+
exports.inputOTPSizeVariant = ['s', 'm'];
|
|
@@ -4,6 +4,7 @@ exports.Tabs = exports.cnTabs = void 0;
|
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
require("./Tabs.css");
|
|
6
6
|
var react_1 = tslib_1.__importStar(require("react"));
|
|
7
|
+
var react_is_1 = require("react-is");
|
|
7
8
|
var useDebounceCallback_1 = require("../../hooks/useDebounceCallback");
|
|
8
9
|
var useEventListener_1 = require("../../hooks/useEventListener");
|
|
9
10
|
var animateProperty_1 = require("../../utils/animateProperty");
|
|
@@ -31,9 +32,12 @@ exports.Tabs = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
31
32
|
* для более точного контроля
|
|
32
33
|
*/
|
|
33
34
|
var tabsValueToIndex = (0, react_1.useMemo)(function () { return new Map(); }, [children]);
|
|
35
|
+
var resolvedChildren = (0, react_is_1.isFragment)(children)
|
|
36
|
+
? children.props.children
|
|
37
|
+
: children;
|
|
34
38
|
/** Children только ноды Табов */
|
|
35
39
|
var onlyTabsChildren = (0, react_1.useMemo)(function () {
|
|
36
|
-
return react_1.default.Children.toArray(
|
|
40
|
+
return react_1.default.Children.toArray(resolvedChildren)
|
|
37
41
|
.filter(function (child) { return react_1.default.isValidElement(child) && (child === null || child === void 0 ? void 0 : child.type) === components_1.Tab; })
|
|
38
42
|
.map(function (child, index) {
|
|
39
43
|
if (!react_1.default.isValidElement(child))
|
|
@@ -42,7 +46,7 @@ exports.Tabs = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
42
46
|
tabsValueToIndex.set(childValue, index);
|
|
43
47
|
return react_1.default.cloneElement(child, { value: childValue });
|
|
44
48
|
});
|
|
45
|
-
}, [
|
|
49
|
+
}, [resolvedChildren]);
|
|
46
50
|
var isScrollButtonsActive = variant === 'scrollable' &&
|
|
47
51
|
!disableScrollButtons &&
|
|
48
52
|
tabsListRef.current &&
|
|
@@ -111,6 +111,7 @@ export type Theme = {
|
|
|
111
111
|
Indicator?: Partial<IndicatorProps>;
|
|
112
112
|
Input?: Partial<InputProps>;
|
|
113
113
|
InputNumber?: Partial<InputNumberProps>;
|
|
114
|
+
InputOTP?: Partial<InputProps>;
|
|
114
115
|
Link?: Partial<LinkProps>;
|
|
115
116
|
List?: Partial<ListProps>;
|
|
116
117
|
ListItem?: Partial<ListItemProps>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./utils"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./useStoredValue"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useStoredValue = useStoredValue;
|
|
4
|
+
var react_1 = require("react");
|
|
5
|
+
var isFunction_1 = require("../../utils/isFunction");
|
|
6
|
+
function useStoredValue(
|
|
7
|
+
/** Изначальное значение */
|
|
8
|
+
initialValue) {
|
|
9
|
+
var processedInitialValue = (0, react_1.useMemo)(function () {
|
|
10
|
+
if ((0, isFunction_1.isFunction)(initialValue)) {
|
|
11
|
+
return initialValue();
|
|
12
|
+
}
|
|
13
|
+
return initialValue;
|
|
14
|
+
}, []);
|
|
15
|
+
return (0, react_1.useRef)(processedInitialValue);
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isStoredValue = isStoredValue;
|
|
4
|
+
function isStoredValue(valueToCheck) {
|
|
5
|
+
return (!!valueToCheck &&
|
|
6
|
+
typeof valueToCheck === 'object' &&
|
|
7
|
+
Object.prototype.hasOwnProperty.call(valueToCheck, 'current'));
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const createEmptyArray: (length: number) => null[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createEmptyArray = void 0;
|
|
4
|
+
var create_filled_1 = require("../create-filled");
|
|
5
|
+
var createEmptyArray = function (length) {
|
|
6
|
+
return (0, create_filled_1.createFilledArray)(length, null);
|
|
7
|
+
};
|
|
8
|
+
exports.createEmptyArray = createEmptyArray;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createEmptyArray';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const createFilledArray: <Value>(length: number, value: Value) => Value[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './createFilledArray';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isFunction: (data: unknown) => data is (...args: any[]) => any;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFunction = void 0;
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
var isFunction = function (data) {
|
|
6
|
+
return typeof data === 'function';
|
|
7
|
+
};
|
|
8
|
+
exports.isFunction = isFunction;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* stylelint-disable */
|
|
2
|
+
.InputOTP-Field {
|
|
3
|
+
position: relative;
|
|
4
|
+
}
|
|
5
|
+
.InputOTP-Field_notAvailable {
|
|
6
|
+
pointer-events: none;
|
|
7
|
+
}
|
|
8
|
+
.InputOTP .FieldControl_error:not(.FieldControl_disabled) {
|
|
9
|
+
--textfield-color: var(--color-content-error);
|
|
10
|
+
--textfield-background-color: var(--color-background-primary);
|
|
11
|
+
}
|
|
12
|
+
.InputOTP:not(.InputOTP_disabled) .InputOTP-InputContainer {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
}
|
|
15
|
+
.InputOTP_size_s {
|
|
16
|
+
--otp-input-inline-size: 40px;
|
|
17
|
+
}
|
|
18
|
+
.InputOTP_size_s .InputOTP-Input {
|
|
19
|
+
font: var(--typography-text-s-font);
|
|
20
|
+
letter-spacing: var(--typography-text-s-letter_spacing, 0);
|
|
21
|
+
text-transform: var(--typography-text-s-text_transform, none);
|
|
22
|
+
}
|
|
23
|
+
.InputOTP_size_m {
|
|
24
|
+
--otp-input-inline-size: 44px;
|
|
25
|
+
}
|
|
26
|
+
.InputOTP_size_m .InputOTP-Input {
|
|
27
|
+
font: var(--typography-text-l-font);
|
|
28
|
+
letter-spacing: var(--typography-text-l-letter_spacing, 0);
|
|
29
|
+
text-transform: var(--typography-text-l-text_transform, none);
|
|
30
|
+
}
|
|
31
|
+
.InputOTP-Input {
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
padding: var(--textfield-input-padding);
|
|
34
|
+
background-color: var(--textfield-background-color);
|
|
35
|
+
transition: background-color box-shadow var(--transition-slow);
|
|
36
|
+
color: var(--textfield-color);
|
|
37
|
+
border-radius: var(--textfield-border-radius);
|
|
38
|
+
block-size: var(--textfield-input-height);
|
|
39
|
+
text-align: center;
|
|
40
|
+
border: none;
|
|
41
|
+
outline: none;
|
|
42
|
+
display: block;
|
|
43
|
+
inline-size: var(--otp-input-inline-size);
|
|
44
|
+
}
|
|
45
|
+
.InputOTP-Input:-webkit-autofill,
|
|
46
|
+
.InputOTP-Input:-webkit-autofill:hover,
|
|
47
|
+
.InputOTP-Input:-webkit-autofill:focus {
|
|
48
|
+
box-shadow: 0 0 0 1000px var(--textfield-background-color) inset !important;
|
|
49
|
+
background-color: transparent !important;
|
|
50
|
+
-webkit-text-fill-color: var(--textfield-color);
|
|
51
|
+
}
|
|
52
|
+
.InputOTP-Input::-webkit-outer-spin-button,
|
|
53
|
+
.InputOTP-Input::-webkit-inner-spin-button {
|
|
54
|
+
-webkit-appearance: none;
|
|
55
|
+
appearance: none;
|
|
56
|
+
margin: 0;
|
|
57
|
+
}
|
|
58
|
+
.InputOTP-Input:disabled {
|
|
59
|
+
opacity: 1;
|
|
60
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import './InputOTP.css';
|
|
2
|
+
import type { InputOTPBaseProps } from './types';
|
|
3
|
+
export declare const cnInputOTP: import("@bem-react/classname").ClassNameFormatter;
|
|
4
|
+
export declare const InputOTP: import("../../utils/polymorphicComponentWithRef").PolymorphicComponentWithRef<InputOTPBaseProps, "div">;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { __assign, __read, __rest } from "tslib";
|
|
2
|
+
import './InputOTP.css';
|
|
3
|
+
import React, { useImperativeHandle, useEffect, useMemo, useState, } from 'react';
|
|
4
|
+
import { useControlled } from '../../hooks/useControlled';
|
|
5
|
+
import { useStoredValue } from '../../hooks/useStoredValue';
|
|
6
|
+
import { useThemeProps } from '../../hooks/useThemeProps';
|
|
7
|
+
import { createEmptyArray } from '../../utils/array';
|
|
8
|
+
import { cn } from '../../utils/classname';
|
|
9
|
+
import { isFunction } from '../../utils/isFunction';
|
|
10
|
+
import { isString } from '../../utils/isString';
|
|
11
|
+
import { polymorphicComponentWithRef } from '../../utils/polymorphicComponentWithRef';
|
|
12
|
+
import { setRef } from '../../utils/setRef';
|
|
13
|
+
import { FieldControl } from '../FieldControl';
|
|
14
|
+
import { FieldInput } from '../FieldInput';
|
|
15
|
+
import { Fieldset } from '../Fieldset';
|
|
16
|
+
import { Stack } from '../Stack';
|
|
17
|
+
import { INPUT_OTP_DEFAULT_AUTO_COMPLETE_MODE, INPUT_OTP_DEFAULT_DISABLE_STROKE, INPUT_OTP_DEFAULT_FINISH_BEHAVIOR, INPUT_OTP_DEFAULT_SIZE, INPUT_OTP_DEFAULT_TAG, INPUT_OTP_SPACING_BY_SIZE, } from './constants';
|
|
18
|
+
import { maskValue, calculateInput as externalCalculateInput, valueToString, valueToArray, } from './helper';
|
|
19
|
+
import { useInputOTPEvents } from './hooks';
|
|
20
|
+
export var cnInputOTP = cn('InputOTP');
|
|
21
|
+
export var InputOTP = polymorphicComponentWithRef(function (inProps, ref) {
|
|
22
|
+
var props = useThemeProps({
|
|
23
|
+
props: inProps,
|
|
24
|
+
name: 'InputOTP',
|
|
25
|
+
});
|
|
26
|
+
var _a = props.as, as = _a === void 0 ? INPUT_OTP_DEFAULT_TAG : _a, className = props.className, length = props.length, autoComplete = props.autoComplete, _b = props.autoCompleteMode, autoCompleteMode = _b === void 0 ? INPUT_OTP_DEFAULT_AUTO_COMPLETE_MODE : _b, placeholder = props.placeholder, disabled = props.disabled, error = props.error, onChangeFromProps = props.onChange, ariaLabel = props.ariaLabel, value = props.value, defaultValue = props.defaultValue, mask = props.mask, autoFocus = props.autoFocus, onFinish = props.onFinish, onPasteFromProps = props.onPaste, onKeyDownFromProps = props.onKeyDown, _c = props.disableStroke, disableStroke = _c === void 0 ? INPUT_OTP_DEFAULT_DISABLE_STROKE : _c, validate = props.validate, _d = props.size, size = _d === void 0 ? INPUT_OTP_DEFAULT_SIZE : _d, inputProps = props.inputProps, fieldProps = props.fieldProps, _e = props.finishBehavior, finishBehavior = _e === void 0 ? INPUT_OTP_DEFAULT_FINISH_BEHAVIOR : _e, inputContainerProps = props.inputContainerProps, other = __rest(props, ["as", "className", "length", "autoComplete", "autoCompleteMode", "placeholder", "disabled", "error", "onChange", "ariaLabel", "value", "defaultValue", "mask", "autoFocus", "onFinish", "onPaste", "onKeyDown", "disableStroke", "validate", "size", "inputProps", "fieldProps", "finishBehavior", "inputContainerProps"]);
|
|
27
|
+
var _f = __read(useState(null), 2), focusedInputIndex = _f[0], setFocusedInputIndex = _f[1];
|
|
28
|
+
var _g = __read(useControlled({
|
|
29
|
+
value: isString(value) ? valueToArray(value) : value,
|
|
30
|
+
defaultValue: useMemo(function () {
|
|
31
|
+
if (isString(defaultValue)) {
|
|
32
|
+
return valueToArray(defaultValue);
|
|
33
|
+
}
|
|
34
|
+
return defaultValue !== null && defaultValue !== void 0 ? defaultValue : [];
|
|
35
|
+
}, []),
|
|
36
|
+
name: 'InputOtp',
|
|
37
|
+
}), 2), valueByIndex = _g[0], setValueByIndexState = _g[1];
|
|
38
|
+
var inputs = useStoredValue([]);
|
|
39
|
+
var setValueByIndex = function (valueByIndex) {
|
|
40
|
+
setValueByIndexState(valueByIndex);
|
|
41
|
+
if (onChangeFromProps) {
|
|
42
|
+
var maskedValueByIndex = maskValue(mask, valueByIndex);
|
|
43
|
+
onChangeFromProps(valueToString(valueByIndex), valueByIndex, valueToString(maskedValueByIndex), maskedValueByIndex);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var calculateInput = function (valueByIndex, index) {
|
|
47
|
+
return externalCalculateInput({
|
|
48
|
+
valueByIndex: valueByIndex,
|
|
49
|
+
mask: mask,
|
|
50
|
+
disabled: disabled,
|
|
51
|
+
index: index,
|
|
52
|
+
length: length,
|
|
53
|
+
focusedInputIndex: focusedInputIndex,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
var _h = useInputOTPEvents({
|
|
57
|
+
inputs: inputs,
|
|
58
|
+
valueByIndex: valueByIndex,
|
|
59
|
+
setValueByIndex: setValueByIndex,
|
|
60
|
+
validate: validate,
|
|
61
|
+
onFinish: onFinish,
|
|
62
|
+
onPaste: onPasteFromProps,
|
|
63
|
+
onKeyDown: onKeyDownFromProps,
|
|
64
|
+
length: length,
|
|
65
|
+
mask: mask,
|
|
66
|
+
finishBehavior: finishBehavior,
|
|
67
|
+
}), onInputSelect = _h.onInputSelect, onInputChange = _h.onInputChange, onKeyDown = _h.onKeyDown, onPaste = _h.onPaste;
|
|
68
|
+
var getFirstNonFilledInput = function () {
|
|
69
|
+
var firstNonFilledInputIndex = inputs.current.findIndex(function (_, index) {
|
|
70
|
+
var _a;
|
|
71
|
+
var inputValue = (_a = valueByIndex === null || valueByIndex === void 0 ? void 0 : valueByIndex[index]) !== null && _a !== void 0 ? _a : '';
|
|
72
|
+
return inputValue === '';
|
|
73
|
+
});
|
|
74
|
+
return inputs.current[firstNonFilledInputIndex];
|
|
75
|
+
};
|
|
76
|
+
var focusFirstNonFilledInput = function () {
|
|
77
|
+
var _a;
|
|
78
|
+
(_a = getFirstNonFilledInput()) === null || _a === void 0 ? void 0 : _a.focus();
|
|
79
|
+
};
|
|
80
|
+
useEffect(function () {
|
|
81
|
+
if (!autoFocus) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
focusFirstNonFilledInput();
|
|
85
|
+
}, []);
|
|
86
|
+
useImperativeHandle(ref, function () { return ({
|
|
87
|
+
focus: function () {
|
|
88
|
+
var _a;
|
|
89
|
+
if (getFirstNonFilledInput()) {
|
|
90
|
+
focusFirstNonFilledInput();
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
(_a = inputs.current[length - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
}); });
|
|
97
|
+
return (React.createElement(Stack, __assign({ as: as, className: cnInputOTP({
|
|
98
|
+
size: size,
|
|
99
|
+
disabled: disabled,
|
|
100
|
+
}, [className]), gap: INPUT_OTP_SPACING_BY_SIZE[size] }, other, { ref: ref }), createEmptyArray(length).map(function (_, index) {
|
|
101
|
+
var _a, _b;
|
|
102
|
+
var calculatedInput = calculateInput(valueByIndex, index);
|
|
103
|
+
var isInputDisabled = calculatedInput.isDisabled, value = calculatedInput.value;
|
|
104
|
+
var processedAutocomplete = (function () {
|
|
105
|
+
if (autoCompleteMode === 'firstOnly') {
|
|
106
|
+
return !!autoComplete && index === 0 ? autoComplete : 'off';
|
|
107
|
+
}
|
|
108
|
+
return autoComplete;
|
|
109
|
+
})();
|
|
110
|
+
var processedContainerProps = isFunction(inputContainerProps)
|
|
111
|
+
? inputContainerProps(calculatedInput, index)
|
|
112
|
+
: inputContainerProps;
|
|
113
|
+
var processedFieldProps = isFunction(fieldProps)
|
|
114
|
+
? fieldProps(calculatedInput, index)
|
|
115
|
+
: fieldProps;
|
|
116
|
+
var processedInputProps = isFunction(inputProps)
|
|
117
|
+
? inputProps(calculatedInput, index)
|
|
118
|
+
: inputProps;
|
|
119
|
+
var processedPlaceholder = isFunction(placeholder)
|
|
120
|
+
? placeholder(calculatedInput, index)
|
|
121
|
+
: placeholder;
|
|
122
|
+
return (
|
|
123
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
|
|
124
|
+
React.createElement("div", __assign({ key: index }, processedContainerProps, { className: cnInputOTP('InputContainer', [
|
|
125
|
+
processedContainerProps === null || processedContainerProps === void 0 ? void 0 : processedContainerProps.className,
|
|
126
|
+
]), onClick: function () {
|
|
127
|
+
if (isInputDisabled) {
|
|
128
|
+
focusFirstNonFilledInput();
|
|
129
|
+
}
|
|
130
|
+
} }),
|
|
131
|
+
React.createElement(FieldControl, __assign({ size: size, disabled: disabled, error: error, disableStroke: disableStroke }, processedFieldProps, { className: cnInputOTP('Field', {
|
|
132
|
+
notAvailable: isInputDisabled,
|
|
133
|
+
}, [processedFieldProps === null || processedFieldProps === void 0 ? void 0 : processedFieldProps.className]) }),
|
|
134
|
+
React.createElement(FieldInput, __assign({ inputMode: (_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.inputMode) !== null && _a !== void 0 ? _a : 'numeric', type: (_b = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.type) !== null && _b !== void 0 ? _b : 'text', value: value, autoComplete: processedAutocomplete, "aria-label": ariaLabel && "".concat(ariaLabel, ": ").concat(index + 1, "."), placeholder: processedPlaceholder, disabled: isInputDisabled }, processedInputProps, { onMouseDown: function (event) {
|
|
135
|
+
var _a;
|
|
136
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onMouseDown) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
137
|
+
onInputSelect(index);
|
|
138
|
+
}, onTouchStart: function (event) {
|
|
139
|
+
var _a;
|
|
140
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onTouchStart) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
141
|
+
onInputSelect(index);
|
|
142
|
+
}, onPointerDown: function (event) {
|
|
143
|
+
var _a;
|
|
144
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onPointerDown) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
145
|
+
onInputSelect(index);
|
|
146
|
+
}, onChange: function (event) {
|
|
147
|
+
var _a;
|
|
148
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onChange) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
149
|
+
onInputChange(event, index);
|
|
150
|
+
}, onKeyDown: function (event) {
|
|
151
|
+
var _a;
|
|
152
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
153
|
+
onKeyDown(event, index);
|
|
154
|
+
}, onPaste: function (event) {
|
|
155
|
+
var _a;
|
|
156
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onPaste) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
157
|
+
onPaste(event, index);
|
|
158
|
+
}, onFocus: function (event) {
|
|
159
|
+
var _a;
|
|
160
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onFocus) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
161
|
+
setFocusedInputIndex(index);
|
|
162
|
+
}, onBlur: function (event) {
|
|
163
|
+
var _a;
|
|
164
|
+
(_a = processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(processedInputProps, event);
|
|
165
|
+
setFocusedInputIndex(null);
|
|
166
|
+
}, className: cnInputOTP('Input', [
|
|
167
|
+
processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.className,
|
|
168
|
+
]), ref: function (instance) {
|
|
169
|
+
if (instance) {
|
|
170
|
+
inputs.current[index] = instance;
|
|
171
|
+
}
|
|
172
|
+
setRef(processedInputProps === null || processedInputProps === void 0 ? void 0 : processedInputProps.ref, instance);
|
|
173
|
+
} })),
|
|
174
|
+
React.createElement(Fieldset, null))));
|
|
175
|
+
})));
|
|
176
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StackGapVariant } from '../Stack';
|
|
2
|
+
import type { InputOTPAutoCompleteMode, InputOTPSizeVariant } from './types';
|
|
3
|
+
export declare const INPUT_OTP_DEFAULT_TAG = "div";
|
|
4
|
+
export declare const INPUT_OTP_DEFAULT_AUTO_COMPLETE_MODE: InputOTPAutoCompleteMode;
|
|
5
|
+
export declare const INPUT_OTP_DEFAULT_DISABLE_STROKE = false;
|
|
6
|
+
export declare const INPUT_OTP_DEFAULT_SIZE: InputOTPSizeVariant;
|
|
7
|
+
export declare const INPUT_OTP_SPACING_BY_SIZE: Readonly<Record<InputOTPSizeVariant, StackGapVariant>>;
|
|
8
|
+
export declare const INPUT_OTP_DEFAULT_FINISH_BEHAVIOR: ({ isFullFilled }: import("./types").InputOTPFinishBehaviorContext) => boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { INPUT_OTP_FINISH_BEHAVIOR_PRESET } from './presets';
|
|
2
|
+
export var INPUT_OTP_DEFAULT_TAG = 'div';
|
|
3
|
+
export var INPUT_OTP_DEFAULT_AUTO_COMPLETE_MODE = 'firstOnly';
|
|
4
|
+
export var INPUT_OTP_DEFAULT_DISABLE_STROKE = false;
|
|
5
|
+
export var INPUT_OTP_DEFAULT_SIZE = 's';
|
|
6
|
+
export var INPUT_OTP_SPACING_BY_SIZE = {
|
|
7
|
+
s: 's',
|
|
8
|
+
m: 's',
|
|
9
|
+
};
|
|
10
|
+
export var INPUT_OTP_DEFAULT_FINISH_BEHAVIOR = INPUT_OTP_FINISH_BEHAVIOR_PRESET.FULL_FILLED_NON_LAST_INPUT;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InputOTPMask, InputOTPRawValue, InputOTPCalculatedInput } from './types';
|
|
2
|
+
export declare const maskSymbol: (mask: InputOTPMask | undefined, value: string, index: number) => string;
|
|
3
|
+
export declare const maskValue: (mask: InputOTPMask | undefined, value: InputOTPRawValue | undefined) => string[];
|
|
4
|
+
export declare const calculateInput: ({ valueByIndex, index, mask, length, disabled: isDisabledGlobal, focusedInputIndex, }: {
|
|
5
|
+
valueByIndex: string[] | undefined;
|
|
6
|
+
index: number;
|
|
7
|
+
mask: InputOTPMask | undefined;
|
|
8
|
+
length: number;
|
|
9
|
+
disabled: boolean | undefined;
|
|
10
|
+
focusedInputIndex: number | null;
|
|
11
|
+
}) => InputOTPCalculatedInput;
|
|
12
|
+
export declare const valueToString: (value: InputOTPRawValue | undefined) => string;
|
|
13
|
+
export declare const valueToArray: (value: string) => string[];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isFunction } from '../../utils/isFunction';
|
|
2
|
+
import { isNumber } from '../../utils/isNumber';
|
|
3
|
+
import { isString } from '../../utils/isString';
|
|
4
|
+
export var maskSymbol = function (mask, value, index) {
|
|
5
|
+
if (value === '') {
|
|
6
|
+
return '';
|
|
7
|
+
}
|
|
8
|
+
if (isString(mask)) {
|
|
9
|
+
return mask;
|
|
10
|
+
}
|
|
11
|
+
if (isFunction(mask)) {
|
|
12
|
+
return mask(value, index);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
};
|
|
16
|
+
export var maskValue = function (mask, value) { var _a; return (_a = value === null || value === void 0 ? void 0 : value.map(function (value, index) { return maskSymbol(mask, value, index); })) !== null && _a !== void 0 ? _a : []; };
|
|
17
|
+
export var calculateInput = function (_a) {
|
|
18
|
+
var _b;
|
|
19
|
+
var valueByIndex = _a.valueByIndex, index = _a.index, mask = _a.mask, length = _a.length, isDisabledGlobal = _a.disabled, focusedInputIndex = _a.focusedInputIndex;
|
|
20
|
+
var requiredValueByIndex = valueByIndex !== null && valueByIndex !== void 0 ? valueByIndex : [];
|
|
21
|
+
var value = (_b = requiredValueByIndex[index]) !== null && _b !== void 0 ? _b : '';
|
|
22
|
+
var maskedValue = maskSymbol(mask, value, index);
|
|
23
|
+
var lastFilledInputIndex = requiredValueByIndex.findLastIndex(function (value) { return value !== '' && value !== undefined; });
|
|
24
|
+
var isBackward = index <= lastFilledInputIndex;
|
|
25
|
+
var isPrevious = index === lastFilledInputIndex;
|
|
26
|
+
var isNext = index === lastFilledInputIndex + 2;
|
|
27
|
+
var isCurrentInput = index === lastFilledInputIndex + 1;
|
|
28
|
+
var isLast = index === length - 1;
|
|
29
|
+
var isPreviousByFocusedInput = isNumber(focusedInputIndex) && index < focusedInputIndex;
|
|
30
|
+
var isFocusedInput = index === focusedInputIndex;
|
|
31
|
+
var isDisabled = (function () {
|
|
32
|
+
if (isDisabledGlobal) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (isFocusedInput) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (isPreviousByFocusedInput) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (isBackward) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (value !== '') {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return !isCurrentInput;
|
|
48
|
+
})();
|
|
49
|
+
return {
|
|
50
|
+
value: maskedValue,
|
|
51
|
+
rawValue: value,
|
|
52
|
+
isPrevious: isPrevious,
|
|
53
|
+
isNext: isNext,
|
|
54
|
+
isCurrentInput: isCurrentInput,
|
|
55
|
+
isLast: isLast,
|
|
56
|
+
isDisabled: isDisabled,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export var valueToString = function (value) {
|
|
60
|
+
if (!value) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
return value
|
|
64
|
+
.map(function (value) {
|
|
65
|
+
if (value === '') {
|
|
66
|
+
return ' ';
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
})
|
|
70
|
+
.join('');
|
|
71
|
+
};
|
|
72
|
+
export var valueToArray = function (value) {
|
|
73
|
+
return value.split('').map(function (value) {
|
|
74
|
+
if (value === ' ') {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
});
|
|
79
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useInputOTPEvents';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useInputOTPEvents';
|