@cloud-ru/uikit-product-fields-predefined 2.4.8-preview-04a474c4.0 → 3.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/CHANGELOG.md +11 -0
- package/README.md +12 -326
- package/dist/cjs/components/index.d.ts +0 -2
- package/dist/cjs/components/index.js +0 -2
- package/dist/esm/components/index.d.ts +0 -2
- package/dist/esm/components/index.js +0 -2
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +3 -9
- package/src/components/index.ts +0 -2
- package/dist/cjs/components/FieldAi/FieldAi.d.ts +0 -24
- package/dist/cjs/components/FieldAi/FieldAi.js +0 -92
- package/dist/cjs/components/FieldAi/components/AlertButton/AlertButton.d.ts +0 -5
- package/dist/cjs/components/FieldAi/components/AlertButton/AlertButton.js +0 -12
- package/dist/cjs/components/FieldAi/components/AlertButton/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/AlertButton/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/AlertButton/styles.module.css +0 -17
- package/dist/cjs/components/FieldAi/components/CheckItem/CheckItem.d.ts +0 -9
- package/dist/cjs/components/FieldAi/components/CheckItem/CheckItem.js +0 -28
- package/dist/cjs/components/FieldAi/components/CheckItem/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/CheckItem/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/CheckItem/styles.module.css +0 -36
- package/dist/cjs/components/FieldAi/components/MobileFieldAi/MobileFieldAi.d.ts +0 -5
- package/dist/cjs/components/FieldAi/components/MobileFieldAi/MobileFieldAi.js +0 -31
- package/dist/cjs/components/FieldAi/components/MobileFieldAi/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/MobileFieldAi/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/MobileFieldAi/styles.module.css +0 -78
- package/dist/cjs/components/FieldAi/components/PasswordValidation/PasswordValidation.d.ts +0 -7
- package/dist/cjs/components/FieldAi/components/PasswordValidation/PasswordValidation.js +0 -23
- package/dist/cjs/components/FieldAi/components/PasswordValidation/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/PasswordValidation/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/PasswordValidation/styles.module.css +0 -36
- package/dist/cjs/components/FieldAi/components/TextArea/TextArea.d.ts +0 -39
- package/dist/cjs/components/FieldAi/components/TextArea/TextArea.js +0 -33
- package/dist/cjs/components/FieldAi/components/TextArea/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/TextArea/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/TextArea/styles.module.css +0 -32
- package/dist/cjs/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.d.ts +0 -10
- package/dist/cjs/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.js +0 -23
- package/dist/cjs/components/FieldAi/components/WithPasswordValidation/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/components/WithPasswordValidation/index.js +0 -17
- package/dist/cjs/components/FieldAi/components/WithPasswordValidation/styles.module.css +0 -6
- package/dist/cjs/components/FieldAi/index.d.ts +0 -1
- package/dist/cjs/components/FieldAi/index.js +0 -17
- package/dist/cjs/components/FieldAi/styles.module.css +0 -61
- package/dist/cjs/components/FieldAi/utils.d.ts +0 -10
- package/dist/cjs/components/FieldAi/utils.js +0 -19
- package/dist/cjs/components/FieldCode/FieldCode.d.ts +0 -33
- package/dist/cjs/components/FieldCode/FieldCode.js +0 -48
- package/dist/cjs/components/FieldCode/components/Cell/Cell.d.ts +0 -5
- package/dist/cjs/components/FieldCode/components/Cell/Cell.js +0 -27
- package/dist/cjs/components/FieldCode/components/Cell/index.d.ts +0 -1
- package/dist/cjs/components/FieldCode/components/Cell/index.js +0 -17
- package/dist/cjs/components/FieldCode/components/Cell/styles.module.css +0 -3
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.d.ts +0 -8
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.js +0 -28
- package/dist/cjs/components/FieldCode/components/ResendCode/index.d.ts +0 -1
- package/dist/cjs/components/FieldCode/components/ResendCode/index.js +0 -17
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.d.ts +0 -1
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.js +0 -8
- package/dist/cjs/components/FieldCode/components/index.d.ts +0 -2
- package/dist/cjs/components/FieldCode/components/index.js +0 -18
- package/dist/cjs/components/FieldCode/constants.d.ts +0 -14
- package/dist/cjs/components/FieldCode/constants.js +0 -10
- package/dist/cjs/components/FieldCode/hooks/index.d.ts +0 -4
- package/dist/cjs/components/FieldCode/hooks/index.js +0 -20
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +0 -22
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.js +0 -98
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.d.ts +0 -8
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +0 -24
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.d.ts +0 -13
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.js +0 -34
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.d.ts +0 -5
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.js +0 -22
- package/dist/cjs/components/FieldCode/index.d.ts +0 -2
- package/dist/cjs/components/FieldCode/index.js +0 -20
- package/dist/cjs/components/FieldCode/styles.module.css +0 -30
- package/dist/cjs/components/FieldCode/utils.d.ts +0 -6
- package/dist/cjs/components/FieldCode/utils.js +0 -21
- package/dist/esm/components/FieldAi/FieldAi.d.ts +0 -24
- package/dist/esm/components/FieldAi/FieldAi.js +0 -86
- package/dist/esm/components/FieldAi/components/AlertButton/AlertButton.d.ts +0 -5
- package/dist/esm/components/FieldAi/components/AlertButton/AlertButton.js +0 -6
- package/dist/esm/components/FieldAi/components/AlertButton/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/AlertButton/index.js +0 -1
- package/dist/esm/components/FieldAi/components/AlertButton/styles.module.css +0 -17
- package/dist/esm/components/FieldAi/components/CheckItem/CheckItem.d.ts +0 -9
- package/dist/esm/components/FieldAi/components/CheckItem/CheckItem.js +0 -22
- package/dist/esm/components/FieldAi/components/CheckItem/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/CheckItem/index.js +0 -1
- package/dist/esm/components/FieldAi/components/CheckItem/styles.module.css +0 -36
- package/dist/esm/components/FieldAi/components/MobileFieldAi/MobileFieldAi.d.ts +0 -5
- package/dist/esm/components/FieldAi/components/MobileFieldAi/MobileFieldAi.js +0 -25
- package/dist/esm/components/FieldAi/components/MobileFieldAi/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/MobileFieldAi/index.js +0 -1
- package/dist/esm/components/FieldAi/components/MobileFieldAi/styles.module.css +0 -78
- package/dist/esm/components/FieldAi/components/PasswordValidation/PasswordValidation.d.ts +0 -7
- package/dist/esm/components/FieldAi/components/PasswordValidation/PasswordValidation.js +0 -17
- package/dist/esm/components/FieldAi/components/PasswordValidation/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/PasswordValidation/index.js +0 -1
- package/dist/esm/components/FieldAi/components/PasswordValidation/styles.module.css +0 -36
- package/dist/esm/components/FieldAi/components/TextArea/TextArea.d.ts +0 -39
- package/dist/esm/components/FieldAi/components/TextArea/TextArea.js +0 -27
- package/dist/esm/components/FieldAi/components/TextArea/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/TextArea/index.js +0 -1
- package/dist/esm/components/FieldAi/components/TextArea/styles.module.css +0 -32
- package/dist/esm/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.d.ts +0 -10
- package/dist/esm/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.js +0 -17
- package/dist/esm/components/FieldAi/components/WithPasswordValidation/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/components/WithPasswordValidation/index.js +0 -1
- package/dist/esm/components/FieldAi/components/WithPasswordValidation/styles.module.css +0 -6
- package/dist/esm/components/FieldAi/index.d.ts +0 -1
- package/dist/esm/components/FieldAi/index.js +0 -1
- package/dist/esm/components/FieldAi/styles.module.css +0 -61
- package/dist/esm/components/FieldAi/utils.d.ts +0 -10
- package/dist/esm/components/FieldAi/utils.js +0 -15
- package/dist/esm/components/FieldCode/FieldCode.d.ts +0 -33
- package/dist/esm/components/FieldCode/FieldCode.js +0 -41
- package/dist/esm/components/FieldCode/components/Cell/Cell.d.ts +0 -5
- package/dist/esm/components/FieldCode/components/Cell/Cell.js +0 -21
- package/dist/esm/components/FieldCode/components/Cell/index.d.ts +0 -1
- package/dist/esm/components/FieldCode/components/Cell/index.js +0 -1
- package/dist/esm/components/FieldCode/components/Cell/styles.module.css +0 -3
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.d.ts +0 -8
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.js +0 -25
- package/dist/esm/components/FieldCode/components/ResendCode/index.d.ts +0 -1
- package/dist/esm/components/FieldCode/components/ResendCode/index.js +0 -1
- package/dist/esm/components/FieldCode/components/ResendCode/utils.d.ts +0 -1
- package/dist/esm/components/FieldCode/components/ResendCode/utils.js +0 -5
- package/dist/esm/components/FieldCode/components/index.d.ts +0 -2
- package/dist/esm/components/FieldCode/components/index.js +0 -2
- package/dist/esm/components/FieldCode/constants.d.ts +0 -14
- package/dist/esm/components/FieldCode/constants.js +0 -7
- package/dist/esm/components/FieldCode/hooks/index.d.ts +0 -4
- package/dist/esm/components/FieldCode/hooks/index.js +0 -4
- package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +0 -22
- package/dist/esm/components/FieldCode/hooks/useCodeInput.js +0 -95
- package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.d.ts +0 -8
- package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +0 -21
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.d.ts +0 -13
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.js +0 -31
- package/dist/esm/components/FieldCode/hooks/useFocusCell.d.ts +0 -5
- package/dist/esm/components/FieldCode/hooks/useFocusCell.js +0 -19
- package/dist/esm/components/FieldCode/index.d.ts +0 -2
- package/dist/esm/components/FieldCode/index.js +0 -2
- package/dist/esm/components/FieldCode/styles.module.css +0 -30
- package/dist/esm/components/FieldCode/utils.d.ts +0 -6
- package/dist/esm/components/FieldCode/utils.js +0 -13
- package/src/components/FieldAi/FieldAi.tsx +0 -201
- package/src/components/FieldAi/components/AlertButton/AlertButton.tsx +0 -16
- package/src/components/FieldAi/components/AlertButton/index.ts +0 -1
- package/src/components/FieldAi/components/AlertButton/styles.module.scss +0 -20
- package/src/components/FieldAi/components/CheckItem/CheckItem.tsx +0 -45
- package/src/components/FieldAi/components/CheckItem/index.ts +0 -1
- package/src/components/FieldAi/components/CheckItem/styles.module.scss +0 -44
- package/src/components/FieldAi/components/MobileFieldAi/MobileFieldAi.tsx +0 -57
- package/src/components/FieldAi/components/MobileFieldAi/index.ts +0 -1
- package/src/components/FieldAi/components/MobileFieldAi/styles.module.scss +0 -90
- package/src/components/FieldAi/components/PasswordValidation/PasswordValidation.tsx +0 -85
- package/src/components/FieldAi/components/PasswordValidation/index.ts +0 -1
- package/src/components/FieldAi/components/PasswordValidation/styles.module.scss +0 -34
- package/src/components/FieldAi/components/TextArea/TextArea.tsx +0 -113
- package/src/components/FieldAi/components/TextArea/index.ts +0 -1
- package/src/components/FieldAi/components/TextArea/styles.module.scss +0 -35
- package/src/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.tsx +0 -63
- package/src/components/FieldAi/components/WithPasswordValidation/index.ts +0 -1
- package/src/components/FieldAi/components/WithPasswordValidation/styles.module.scss +0 -8
- package/src/components/FieldAi/index.ts +0 -1
- package/src/components/FieldAi/styles.module.scss +0 -85
- package/src/components/FieldAi/utils.ts +0 -27
- package/src/components/FieldCode/FieldCode.tsx +0 -125
- package/src/components/FieldCode/components/Cell/Cell.tsx +0 -32
- package/src/components/FieldCode/components/Cell/index.ts +0 -1
- package/src/components/FieldCode/components/Cell/styles.module.scss +0 -5
- package/src/components/FieldCode/components/ResendCode/ResendCode.tsx +0 -33
- package/src/components/FieldCode/components/ResendCode/index.ts +0 -1
- package/src/components/FieldCode/components/ResendCode/utils.ts +0 -5
- package/src/components/FieldCode/components/index.ts +0 -2
- package/src/components/FieldCode/constants.ts +0 -20
- package/src/components/FieldCode/hooks/index.ts +0 -4
- package/src/components/FieldCode/hooks/useCodeInput.ts +0 -147
- package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +0 -35
- package/src/components/FieldCode/hooks/useFieldHelpers.ts +0 -52
- package/src/components/FieldCode/hooks/useFocusCell.ts +0 -29
- package/src/components/FieldCode/index.ts +0 -2
- package/src/components/FieldCode/styles.module.scss +0 -40
- package/src/components/FieldCode/utils.ts +0 -23
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import cn from 'classnames';
|
|
2
|
-
import { forwardRef } from 'react';
|
|
3
|
-
|
|
4
|
-
import { FieldText, FieldTextProps } from '@snack-uikit/fields';
|
|
5
|
-
|
|
6
|
-
import { ZERO_WIDTH_SPACE } from '../../constants';
|
|
7
|
-
import styles from './styles.module.scss';
|
|
8
|
-
|
|
9
|
-
type CellProps = {
|
|
10
|
-
/** CSS-класс ячейки кода */
|
|
11
|
-
className?: string;
|
|
12
|
-
} & Pick<
|
|
13
|
-
FieldTextProps,
|
|
14
|
-
'size' | 'disabled' | 'value' | 'autoComplete' | 'onKeyDown' | 'onPaste' | 'onChange' | 'validationState'
|
|
15
|
-
>;
|
|
16
|
-
|
|
17
|
-
export const Cell = forwardRef<HTMLInputElement, CellProps>((props, ref) => {
|
|
18
|
-
const { className, size, value, ...fieldCellProps } = props;
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<FieldText
|
|
22
|
-
inputMode='numeric'
|
|
23
|
-
ref={ref}
|
|
24
|
-
className={cn(styles.cell, className)}
|
|
25
|
-
data-size={size}
|
|
26
|
-
showClearButton={false}
|
|
27
|
-
value={value === ZERO_WIDTH_SPACE ? '' : value}
|
|
28
|
-
size={size}
|
|
29
|
-
{...fieldCellProps}
|
|
30
|
-
/>
|
|
31
|
-
);
|
|
32
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Cell';
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { UpdateSVG } from '@cloud-ru/uikit-product-icons';
|
|
2
|
-
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
3
|
-
import { ButtonFunction, ButtonFunctionProps } from '@snack-uikit/button';
|
|
4
|
-
|
|
5
|
-
import { formatSecondsAsMmSs } from './utils';
|
|
6
|
-
|
|
7
|
-
export type ResendCodeProps = {
|
|
8
|
-
/** Колбек отправки нового кода */
|
|
9
|
-
onResend: () => void;
|
|
10
|
-
/** Количество секунд до следующего отправления кода */
|
|
11
|
-
secondsToNextResend: number;
|
|
12
|
-
} & Pick<ButtonFunctionProps, 'size' | 'disabled'>;
|
|
13
|
-
|
|
14
|
-
export function ResendCode(props: ResendCodeProps) {
|
|
15
|
-
const { onResend, secondsToNextResend, ...buttonProps } = props;
|
|
16
|
-
const { t } = useLocale('FieldsPredefined');
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ButtonFunction
|
|
20
|
-
label={
|
|
21
|
-
secondsToNextResend > 0
|
|
22
|
-
? t('FieldCode.resendCodeButtons.resendCodeWithVia', {
|
|
23
|
-
timer: formatSecondsAsMmSs(secondsToNextResend),
|
|
24
|
-
})
|
|
25
|
-
: t('FieldCode.resendCodeButtons.resendCode')
|
|
26
|
-
}
|
|
27
|
-
onClick={onResend}
|
|
28
|
-
icon={<UpdateSVG />}
|
|
29
|
-
iconPosition='before'
|
|
30
|
-
{...buttonProps}
|
|
31
|
-
/>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ResendCode';
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export const ZERO_WIDTH_SPACE = '\u200B';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Когда дергать `moveFocus` у `FieldCode` (массив `focusEffects`, порядок не важен).
|
|
5
|
-
* @see {@link FIELD_CODE_DEFAULT_FOCUS_EFFECTS}
|
|
6
|
-
*/
|
|
7
|
-
export type FieldCodeFocusEffect =
|
|
8
|
-
/** После монтирования — ячейка `0`. */
|
|
9
|
-
| 'firstCellOnMount'
|
|
10
|
-
/** После `ref.resetCode()` — ячейка `0`. */
|
|
11
|
-
| 'firstCellOnReset'
|
|
12
|
-
/** При включении `showEmptyChars` — первая пустая (все заполнены — последняя); не на каждый ввод. */
|
|
13
|
-
| 'firstCellWhenShowEmptyChars';
|
|
14
|
-
|
|
15
|
-
/** Дефолтный набор для `focusEffects`. */
|
|
16
|
-
export const FIELD_CODE_DEFAULT_FOCUS_EFFECTS: readonly FieldCodeFocusEffect[] = [
|
|
17
|
-
'firstCellOnMount',
|
|
18
|
-
'firstCellOnReset',
|
|
19
|
-
'firstCellWhenShowEmptyChars',
|
|
20
|
-
];
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { useRefState } from '@siberiacancode/reactuse';
|
|
2
|
-
import { ClipboardEvent, KeyboardEvent, useCallback, useEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
import { useValueControl } from '@snack-uikit/utils';
|
|
5
|
-
|
|
6
|
-
import { ZERO_WIDTH_SPACE } from '../constants';
|
|
7
|
-
import { isNumberChar, isStringCodeLength, isZeroWidthSpace } from '../utils';
|
|
8
|
-
|
|
9
|
-
export type UseCodeInputParams = {
|
|
10
|
-
/** Количество цифр в коде (ожидается целое ≥ 1) */
|
|
11
|
-
codeLength: number;
|
|
12
|
-
/** Значение кода */
|
|
13
|
-
value?: string;
|
|
14
|
-
/** Колбек изменения значения */
|
|
15
|
-
onChange?: (code: string) => void;
|
|
16
|
-
/** Функция фокуса */
|
|
17
|
-
moveFocus: (index: number) => void;
|
|
18
|
-
/** Колбек достижения ввода всех символов кода */
|
|
19
|
-
onComplete?: (code: string) => void;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const buildCodeArray = (str: string, codeLength: number) =>
|
|
23
|
-
Array.from({ length: codeLength }, (_, idx) => str[idx] || ZERO_WIDTH_SPACE);
|
|
24
|
-
|
|
25
|
-
export function useCodeInput(params: UseCodeInputParams) {
|
|
26
|
-
const { value: valueProp, onChange: onChangeProp, codeLength, moveFocus, onComplete } = params;
|
|
27
|
-
|
|
28
|
-
const [value = '', onChange] = useValueControl<string>({
|
|
29
|
-
value: valueProp,
|
|
30
|
-
onChange: onChangeProp,
|
|
31
|
-
defaultValue: '',
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const codeRef = useRefState<string[]>(buildCodeArray(value, codeLength));
|
|
35
|
-
|
|
36
|
-
const updateCodeByIndex = useCallback(
|
|
37
|
-
(index: number, newChar: string) => {
|
|
38
|
-
codeRef.current[index] = newChar;
|
|
39
|
-
onChange?.(codeRef.current.join(''));
|
|
40
|
-
},
|
|
41
|
-
[codeRef, onChange],
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
const updateFullCode = useCallback(
|
|
45
|
-
(newCode: string) => {
|
|
46
|
-
codeRef.current = newCode.split('');
|
|
47
|
-
|
|
48
|
-
onChange?.(newCode);
|
|
49
|
-
moveFocus(codeLength - 1);
|
|
50
|
-
onComplete?.(newCode);
|
|
51
|
-
},
|
|
52
|
-
[codeLength, codeRef, moveFocus, onChange, onComplete],
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
const handleAfterCellUpdate = useCallback(
|
|
56
|
-
(index: number) => {
|
|
57
|
-
const normalizedCode = codeRef.current.join('');
|
|
58
|
-
|
|
59
|
-
const isLastInput = index === codeLength - 1;
|
|
60
|
-
const isAllInputsFilled = isStringCodeLength(normalizedCode, codeLength);
|
|
61
|
-
if (!isLastInput) {
|
|
62
|
-
moveFocus(index + 1);
|
|
63
|
-
} else if (isAllInputsFilled) {
|
|
64
|
-
onComplete?.(normalizedCode);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
[codeLength, codeRef, moveFocus, onComplete],
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const deleteChar = useCallback(
|
|
71
|
-
(index: number) => {
|
|
72
|
-
if (codeRef.current[index] && !isZeroWidthSpace(codeRef.current[index])) {
|
|
73
|
-
updateCodeByIndex(index, ZERO_WIDTH_SPACE);
|
|
74
|
-
} else if (index > 0) {
|
|
75
|
-
moveFocus(index - 1);
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
[codeRef, moveFocus, updateCodeByIndex],
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const onAutoCompleteInput = useCallback(
|
|
82
|
-
(code: string, index: number) => {
|
|
83
|
-
if (isStringCodeLength(code, codeLength)) {
|
|
84
|
-
updateFullCode(code);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (!isNumberChar(code)) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
updateCodeByIndex(index, code);
|
|
93
|
-
handleAfterCellUpdate(index);
|
|
94
|
-
},
|
|
95
|
-
[codeLength, handleAfterCellUpdate, updateCodeByIndex, updateFullCode],
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const onKeyDown = useCallback(
|
|
99
|
-
(e: KeyboardEvent<HTMLInputElement>, index: number) => {
|
|
100
|
-
switch (e.key) {
|
|
101
|
-
case 'ArrowLeft':
|
|
102
|
-
moveFocus(index - 1);
|
|
103
|
-
break;
|
|
104
|
-
case 'ArrowRight':
|
|
105
|
-
moveFocus(index + 1);
|
|
106
|
-
break;
|
|
107
|
-
case 'Backspace':
|
|
108
|
-
deleteChar(index);
|
|
109
|
-
break;
|
|
110
|
-
default:
|
|
111
|
-
if (isNumberChar(e.key)) {
|
|
112
|
-
e.preventDefault();
|
|
113
|
-
updateCodeByIndex(index, e.key);
|
|
114
|
-
handleAfterCellUpdate(index);
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
[deleteChar, handleAfterCellUpdate, moveFocus, updateCodeByIndex],
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
const onPaste = useCallback(
|
|
123
|
-
(e: ClipboardEvent<HTMLInputElement>) => {
|
|
124
|
-
const codeInput = e?.clipboardData.getData('text') ?? '';
|
|
125
|
-
if (!isStringCodeLength(codeInput, codeLength)) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
updateFullCode(codeInput);
|
|
130
|
-
},
|
|
131
|
-
[codeLength, updateFullCode],
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
useEffect(() => {
|
|
135
|
-
codeRef.current = buildCodeArray(value, codeLength);
|
|
136
|
-
}, [codeLength, codeRef, value]);
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
code: codeRef.current,
|
|
140
|
-
cellHandlers: {
|
|
141
|
-
onKeyDown,
|
|
142
|
-
onPaste,
|
|
143
|
-
onChange: onAutoCompleteInput,
|
|
144
|
-
},
|
|
145
|
-
onChangeCode: onChange,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
|
|
3
|
-
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
4
|
-
|
|
5
|
-
import { isNumberChar } from '../utils';
|
|
6
|
-
|
|
7
|
-
export type UseFieldCodeValidateParams = {
|
|
8
|
-
/** Ожидаемая длина кода (цифр) */
|
|
9
|
-
codeLength: number;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Возвращает функцию валидации значения кода (пусто / неполный код).
|
|
14
|
-
*/
|
|
15
|
-
export function useFieldCodeValidate(params: UseFieldCodeValidateParams) {
|
|
16
|
-
const { codeLength } = params;
|
|
17
|
-
const { t } = useLocale('FieldsPredefined');
|
|
18
|
-
|
|
19
|
-
return useCallback(
|
|
20
|
-
(value?: string | number) => {
|
|
21
|
-
const str = value != null ? String(value) : '';
|
|
22
|
-
const digits = str.split('').filter(isNumberChar).join('');
|
|
23
|
-
if (digits.length === 0) {
|
|
24
|
-
return t('FieldCode.required');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (digits.length < codeLength) {
|
|
28
|
-
return t('FieldCode.minLength', { count: codeLength });
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return undefined;
|
|
32
|
-
},
|
|
33
|
-
[codeLength, t],
|
|
34
|
-
);
|
|
35
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { type FieldCodeFocusEffect } from '../constants';
|
|
4
|
-
import { getFirstEmptyCellIndex } from '../utils';
|
|
5
|
-
|
|
6
|
-
type UseFieldHelpersParams = {
|
|
7
|
-
onChangeCode: (code: string) => void;
|
|
8
|
-
moveFocus: (index: number) => void;
|
|
9
|
-
focusEffects: readonly FieldCodeFocusEffect[];
|
|
10
|
-
showEmptyChars?: boolean;
|
|
11
|
-
code: readonly string[];
|
|
12
|
-
codeLength: number;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export function useFieldHelpers(params: UseFieldHelpersParams) {
|
|
16
|
-
const { onChangeCode, moveFocus, focusEffects: focusEffectsProp, showEmptyChars, code, codeLength } = params;
|
|
17
|
-
|
|
18
|
-
const focusEffectsKey = [...focusEffectsProp].sort().join(',');
|
|
19
|
-
const focusEffects = useMemo(
|
|
20
|
-
() => [...focusEffectsProp],
|
|
21
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22
|
-
[focusEffectsKey],
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const resetCode = useCallback(() => {
|
|
26
|
-
onChangeCode('');
|
|
27
|
-
|
|
28
|
-
if (focusEffects.includes('firstCellOnReset')) {
|
|
29
|
-
moveFocus(0);
|
|
30
|
-
}
|
|
31
|
-
}, [focusEffects, moveFocus, onChangeCode]);
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (focusEffects.includes('firstCellOnMount')) {
|
|
35
|
-
moveFocus(0);
|
|
36
|
-
}
|
|
37
|
-
}, [focusEffects, moveFocus]);
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (!focusEffects.includes('firstCellWhenShowEmptyChars') || !showEmptyChars) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const emptyIndex = getFirstEmptyCellIndex(code);
|
|
45
|
-
if (emptyIndex >= 0) {
|
|
46
|
-
moveFocus(emptyIndex);
|
|
47
|
-
}
|
|
48
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
-
}, [showEmptyChars, focusEffects, moveFocus, codeLength]);
|
|
50
|
-
|
|
51
|
-
return { resetCode };
|
|
52
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
export function useFocusCell(codeLength: number) {
|
|
4
|
-
const inputsRef = useRef<HTMLInputElement[]>([]);
|
|
5
|
-
|
|
6
|
-
const focusInput = useCallback(
|
|
7
|
-
(index: number) => {
|
|
8
|
-
inputsRef.current[index]?.focus();
|
|
9
|
-
},
|
|
10
|
-
[inputsRef],
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
const moveFocus = useCallback(
|
|
14
|
-
(newIndex: number) => {
|
|
15
|
-
if (newIndex >= 0 && newIndex < codeLength) {
|
|
16
|
-
focusInput(newIndex);
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
[codeLength, focusInput],
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const blurFields = useCallback(() => {
|
|
23
|
-
inputsRef.current.forEach(input => {
|
|
24
|
-
input?.blur();
|
|
25
|
-
});
|
|
26
|
-
}, [inputsRef]);
|
|
27
|
-
|
|
28
|
-
return { inputsRef, moveFocus, blurFields };
|
|
29
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
@use '@cloud-ru/figma-tokens-web/build/scss/components/styles-tokens-element' as ste;
|
|
2
|
-
@use 'sass:map';
|
|
3
|
-
|
|
4
|
-
.fieldCode {
|
|
5
|
-
display: flex;
|
|
6
|
-
flex-direction: column;
|
|
7
|
-
align-items: center;
|
|
8
|
-
gap: 8px;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.codeContainer {
|
|
12
|
-
display: flex;
|
|
13
|
-
justify-content: center;
|
|
14
|
-
|
|
15
|
-
$container-gaps: (
|
|
16
|
-
's': 8px,
|
|
17
|
-
'm': 8px,
|
|
18
|
-
'l': 12px,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
@each $size, $gap in $container-gaps {
|
|
22
|
-
&[data-size='#{$size}'] {
|
|
23
|
-
gap: $gap;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.cellSpacing {
|
|
29
|
-
$spacing-sizes: (
|
|
30
|
-
's': 2px,
|
|
31
|
-
'm': 8px,
|
|
32
|
-
'l': 12px,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
@each $size, $margin-right in $spacing-sizes {
|
|
36
|
-
&[data-size='#{$size}'] {
|
|
37
|
-
margin-right: $margin-right;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { FieldTextProps } from '@snack-uikit/fields';
|
|
2
|
-
|
|
3
|
-
import { ZERO_WIDTH_SPACE } from './constants';
|
|
4
|
-
|
|
5
|
-
export const isNumberChar = (char: string) => /^\d$/.test(char);
|
|
6
|
-
export const isStringCodeLength = (input: string, codeLength: number) => new RegExp(`^\\d{${codeLength}}$`).test(input);
|
|
7
|
-
export const isZeroWidthSpace = (value: string) => value === ZERO_WIDTH_SPACE;
|
|
8
|
-
|
|
9
|
-
export function getFirstEmptyCellIndex(code: readonly string[]): number {
|
|
10
|
-
return code.findIndex(isZeroWidthSpace);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const getCellValidationState = (
|
|
14
|
-
value: string,
|
|
15
|
-
showEmptyChars?: boolean,
|
|
16
|
-
error?: boolean,
|
|
17
|
-
): FieldTextProps['validationState'] => {
|
|
18
|
-
if (showEmptyChars) {
|
|
19
|
-
return isZeroWidthSpace(value) ? 'error' : 'default';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return error ? 'error' : 'default';
|
|
23
|
-
};
|