@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.
Files changed (187) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +12 -326
  3. package/dist/cjs/components/index.d.ts +0 -2
  4. package/dist/cjs/components/index.js +0 -2
  5. package/dist/esm/components/index.d.ts +0 -2
  6. package/dist/esm/components/index.js +0 -2
  7. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  8. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  9. package/package.json +3 -9
  10. package/src/components/index.ts +0 -2
  11. package/dist/cjs/components/FieldAi/FieldAi.d.ts +0 -24
  12. package/dist/cjs/components/FieldAi/FieldAi.js +0 -92
  13. package/dist/cjs/components/FieldAi/components/AlertButton/AlertButton.d.ts +0 -5
  14. package/dist/cjs/components/FieldAi/components/AlertButton/AlertButton.js +0 -12
  15. package/dist/cjs/components/FieldAi/components/AlertButton/index.d.ts +0 -1
  16. package/dist/cjs/components/FieldAi/components/AlertButton/index.js +0 -17
  17. package/dist/cjs/components/FieldAi/components/AlertButton/styles.module.css +0 -17
  18. package/dist/cjs/components/FieldAi/components/CheckItem/CheckItem.d.ts +0 -9
  19. package/dist/cjs/components/FieldAi/components/CheckItem/CheckItem.js +0 -28
  20. package/dist/cjs/components/FieldAi/components/CheckItem/index.d.ts +0 -1
  21. package/dist/cjs/components/FieldAi/components/CheckItem/index.js +0 -17
  22. package/dist/cjs/components/FieldAi/components/CheckItem/styles.module.css +0 -36
  23. package/dist/cjs/components/FieldAi/components/MobileFieldAi/MobileFieldAi.d.ts +0 -5
  24. package/dist/cjs/components/FieldAi/components/MobileFieldAi/MobileFieldAi.js +0 -31
  25. package/dist/cjs/components/FieldAi/components/MobileFieldAi/index.d.ts +0 -1
  26. package/dist/cjs/components/FieldAi/components/MobileFieldAi/index.js +0 -17
  27. package/dist/cjs/components/FieldAi/components/MobileFieldAi/styles.module.css +0 -78
  28. package/dist/cjs/components/FieldAi/components/PasswordValidation/PasswordValidation.d.ts +0 -7
  29. package/dist/cjs/components/FieldAi/components/PasswordValidation/PasswordValidation.js +0 -23
  30. package/dist/cjs/components/FieldAi/components/PasswordValidation/index.d.ts +0 -1
  31. package/dist/cjs/components/FieldAi/components/PasswordValidation/index.js +0 -17
  32. package/dist/cjs/components/FieldAi/components/PasswordValidation/styles.module.css +0 -36
  33. package/dist/cjs/components/FieldAi/components/TextArea/TextArea.d.ts +0 -39
  34. package/dist/cjs/components/FieldAi/components/TextArea/TextArea.js +0 -33
  35. package/dist/cjs/components/FieldAi/components/TextArea/index.d.ts +0 -1
  36. package/dist/cjs/components/FieldAi/components/TextArea/index.js +0 -17
  37. package/dist/cjs/components/FieldAi/components/TextArea/styles.module.css +0 -32
  38. package/dist/cjs/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.d.ts +0 -10
  39. package/dist/cjs/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.js +0 -23
  40. package/dist/cjs/components/FieldAi/components/WithPasswordValidation/index.d.ts +0 -1
  41. package/dist/cjs/components/FieldAi/components/WithPasswordValidation/index.js +0 -17
  42. package/dist/cjs/components/FieldAi/components/WithPasswordValidation/styles.module.css +0 -6
  43. package/dist/cjs/components/FieldAi/index.d.ts +0 -1
  44. package/dist/cjs/components/FieldAi/index.js +0 -17
  45. package/dist/cjs/components/FieldAi/styles.module.css +0 -61
  46. package/dist/cjs/components/FieldAi/utils.d.ts +0 -10
  47. package/dist/cjs/components/FieldAi/utils.js +0 -19
  48. package/dist/cjs/components/FieldCode/FieldCode.d.ts +0 -33
  49. package/dist/cjs/components/FieldCode/FieldCode.js +0 -48
  50. package/dist/cjs/components/FieldCode/components/Cell/Cell.d.ts +0 -5
  51. package/dist/cjs/components/FieldCode/components/Cell/Cell.js +0 -27
  52. package/dist/cjs/components/FieldCode/components/Cell/index.d.ts +0 -1
  53. package/dist/cjs/components/FieldCode/components/Cell/index.js +0 -17
  54. package/dist/cjs/components/FieldCode/components/Cell/styles.module.css +0 -3
  55. package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.d.ts +0 -8
  56. package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.js +0 -28
  57. package/dist/cjs/components/FieldCode/components/ResendCode/index.d.ts +0 -1
  58. package/dist/cjs/components/FieldCode/components/ResendCode/index.js +0 -17
  59. package/dist/cjs/components/FieldCode/components/ResendCode/utils.d.ts +0 -1
  60. package/dist/cjs/components/FieldCode/components/ResendCode/utils.js +0 -8
  61. package/dist/cjs/components/FieldCode/components/index.d.ts +0 -2
  62. package/dist/cjs/components/FieldCode/components/index.js +0 -18
  63. package/dist/cjs/components/FieldCode/constants.d.ts +0 -14
  64. package/dist/cjs/components/FieldCode/constants.js +0 -10
  65. package/dist/cjs/components/FieldCode/hooks/index.d.ts +0 -4
  66. package/dist/cjs/components/FieldCode/hooks/index.js +0 -20
  67. package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +0 -22
  68. package/dist/cjs/components/FieldCode/hooks/useCodeInput.js +0 -98
  69. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.d.ts +0 -8
  70. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +0 -24
  71. package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.d.ts +0 -13
  72. package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.js +0 -34
  73. package/dist/cjs/components/FieldCode/hooks/useFocusCell.d.ts +0 -5
  74. package/dist/cjs/components/FieldCode/hooks/useFocusCell.js +0 -22
  75. package/dist/cjs/components/FieldCode/index.d.ts +0 -2
  76. package/dist/cjs/components/FieldCode/index.js +0 -20
  77. package/dist/cjs/components/FieldCode/styles.module.css +0 -30
  78. package/dist/cjs/components/FieldCode/utils.d.ts +0 -6
  79. package/dist/cjs/components/FieldCode/utils.js +0 -21
  80. package/dist/esm/components/FieldAi/FieldAi.d.ts +0 -24
  81. package/dist/esm/components/FieldAi/FieldAi.js +0 -86
  82. package/dist/esm/components/FieldAi/components/AlertButton/AlertButton.d.ts +0 -5
  83. package/dist/esm/components/FieldAi/components/AlertButton/AlertButton.js +0 -6
  84. package/dist/esm/components/FieldAi/components/AlertButton/index.d.ts +0 -1
  85. package/dist/esm/components/FieldAi/components/AlertButton/index.js +0 -1
  86. package/dist/esm/components/FieldAi/components/AlertButton/styles.module.css +0 -17
  87. package/dist/esm/components/FieldAi/components/CheckItem/CheckItem.d.ts +0 -9
  88. package/dist/esm/components/FieldAi/components/CheckItem/CheckItem.js +0 -22
  89. package/dist/esm/components/FieldAi/components/CheckItem/index.d.ts +0 -1
  90. package/dist/esm/components/FieldAi/components/CheckItem/index.js +0 -1
  91. package/dist/esm/components/FieldAi/components/CheckItem/styles.module.css +0 -36
  92. package/dist/esm/components/FieldAi/components/MobileFieldAi/MobileFieldAi.d.ts +0 -5
  93. package/dist/esm/components/FieldAi/components/MobileFieldAi/MobileFieldAi.js +0 -25
  94. package/dist/esm/components/FieldAi/components/MobileFieldAi/index.d.ts +0 -1
  95. package/dist/esm/components/FieldAi/components/MobileFieldAi/index.js +0 -1
  96. package/dist/esm/components/FieldAi/components/MobileFieldAi/styles.module.css +0 -78
  97. package/dist/esm/components/FieldAi/components/PasswordValidation/PasswordValidation.d.ts +0 -7
  98. package/dist/esm/components/FieldAi/components/PasswordValidation/PasswordValidation.js +0 -17
  99. package/dist/esm/components/FieldAi/components/PasswordValidation/index.d.ts +0 -1
  100. package/dist/esm/components/FieldAi/components/PasswordValidation/index.js +0 -1
  101. package/dist/esm/components/FieldAi/components/PasswordValidation/styles.module.css +0 -36
  102. package/dist/esm/components/FieldAi/components/TextArea/TextArea.d.ts +0 -39
  103. package/dist/esm/components/FieldAi/components/TextArea/TextArea.js +0 -27
  104. package/dist/esm/components/FieldAi/components/TextArea/index.d.ts +0 -1
  105. package/dist/esm/components/FieldAi/components/TextArea/index.js +0 -1
  106. package/dist/esm/components/FieldAi/components/TextArea/styles.module.css +0 -32
  107. package/dist/esm/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.d.ts +0 -10
  108. package/dist/esm/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.js +0 -17
  109. package/dist/esm/components/FieldAi/components/WithPasswordValidation/index.d.ts +0 -1
  110. package/dist/esm/components/FieldAi/components/WithPasswordValidation/index.js +0 -1
  111. package/dist/esm/components/FieldAi/components/WithPasswordValidation/styles.module.css +0 -6
  112. package/dist/esm/components/FieldAi/index.d.ts +0 -1
  113. package/dist/esm/components/FieldAi/index.js +0 -1
  114. package/dist/esm/components/FieldAi/styles.module.css +0 -61
  115. package/dist/esm/components/FieldAi/utils.d.ts +0 -10
  116. package/dist/esm/components/FieldAi/utils.js +0 -15
  117. package/dist/esm/components/FieldCode/FieldCode.d.ts +0 -33
  118. package/dist/esm/components/FieldCode/FieldCode.js +0 -41
  119. package/dist/esm/components/FieldCode/components/Cell/Cell.d.ts +0 -5
  120. package/dist/esm/components/FieldCode/components/Cell/Cell.js +0 -21
  121. package/dist/esm/components/FieldCode/components/Cell/index.d.ts +0 -1
  122. package/dist/esm/components/FieldCode/components/Cell/index.js +0 -1
  123. package/dist/esm/components/FieldCode/components/Cell/styles.module.css +0 -3
  124. package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.d.ts +0 -8
  125. package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.js +0 -25
  126. package/dist/esm/components/FieldCode/components/ResendCode/index.d.ts +0 -1
  127. package/dist/esm/components/FieldCode/components/ResendCode/index.js +0 -1
  128. package/dist/esm/components/FieldCode/components/ResendCode/utils.d.ts +0 -1
  129. package/dist/esm/components/FieldCode/components/ResendCode/utils.js +0 -5
  130. package/dist/esm/components/FieldCode/components/index.d.ts +0 -2
  131. package/dist/esm/components/FieldCode/components/index.js +0 -2
  132. package/dist/esm/components/FieldCode/constants.d.ts +0 -14
  133. package/dist/esm/components/FieldCode/constants.js +0 -7
  134. package/dist/esm/components/FieldCode/hooks/index.d.ts +0 -4
  135. package/dist/esm/components/FieldCode/hooks/index.js +0 -4
  136. package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +0 -22
  137. package/dist/esm/components/FieldCode/hooks/useCodeInput.js +0 -95
  138. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.d.ts +0 -8
  139. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +0 -21
  140. package/dist/esm/components/FieldCode/hooks/useFieldHelpers.d.ts +0 -13
  141. package/dist/esm/components/FieldCode/hooks/useFieldHelpers.js +0 -31
  142. package/dist/esm/components/FieldCode/hooks/useFocusCell.d.ts +0 -5
  143. package/dist/esm/components/FieldCode/hooks/useFocusCell.js +0 -19
  144. package/dist/esm/components/FieldCode/index.d.ts +0 -2
  145. package/dist/esm/components/FieldCode/index.js +0 -2
  146. package/dist/esm/components/FieldCode/styles.module.css +0 -30
  147. package/dist/esm/components/FieldCode/utils.d.ts +0 -6
  148. package/dist/esm/components/FieldCode/utils.js +0 -13
  149. package/src/components/FieldAi/FieldAi.tsx +0 -201
  150. package/src/components/FieldAi/components/AlertButton/AlertButton.tsx +0 -16
  151. package/src/components/FieldAi/components/AlertButton/index.ts +0 -1
  152. package/src/components/FieldAi/components/AlertButton/styles.module.scss +0 -20
  153. package/src/components/FieldAi/components/CheckItem/CheckItem.tsx +0 -45
  154. package/src/components/FieldAi/components/CheckItem/index.ts +0 -1
  155. package/src/components/FieldAi/components/CheckItem/styles.module.scss +0 -44
  156. package/src/components/FieldAi/components/MobileFieldAi/MobileFieldAi.tsx +0 -57
  157. package/src/components/FieldAi/components/MobileFieldAi/index.ts +0 -1
  158. package/src/components/FieldAi/components/MobileFieldAi/styles.module.scss +0 -90
  159. package/src/components/FieldAi/components/PasswordValidation/PasswordValidation.tsx +0 -85
  160. package/src/components/FieldAi/components/PasswordValidation/index.ts +0 -1
  161. package/src/components/FieldAi/components/PasswordValidation/styles.module.scss +0 -34
  162. package/src/components/FieldAi/components/TextArea/TextArea.tsx +0 -113
  163. package/src/components/FieldAi/components/TextArea/index.ts +0 -1
  164. package/src/components/FieldAi/components/TextArea/styles.module.scss +0 -35
  165. package/src/components/FieldAi/components/WithPasswordValidation/WithPasswordValidation.tsx +0 -63
  166. package/src/components/FieldAi/components/WithPasswordValidation/index.ts +0 -1
  167. package/src/components/FieldAi/components/WithPasswordValidation/styles.module.scss +0 -8
  168. package/src/components/FieldAi/index.ts +0 -1
  169. package/src/components/FieldAi/styles.module.scss +0 -85
  170. package/src/components/FieldAi/utils.ts +0 -27
  171. package/src/components/FieldCode/FieldCode.tsx +0 -125
  172. package/src/components/FieldCode/components/Cell/Cell.tsx +0 -32
  173. package/src/components/FieldCode/components/Cell/index.ts +0 -1
  174. package/src/components/FieldCode/components/Cell/styles.module.scss +0 -5
  175. package/src/components/FieldCode/components/ResendCode/ResendCode.tsx +0 -33
  176. package/src/components/FieldCode/components/ResendCode/index.ts +0 -1
  177. package/src/components/FieldCode/components/ResendCode/utils.ts +0 -5
  178. package/src/components/FieldCode/components/index.ts +0 -2
  179. package/src/components/FieldCode/constants.ts +0 -20
  180. package/src/components/FieldCode/hooks/index.ts +0 -4
  181. package/src/components/FieldCode/hooks/useCodeInput.ts +0 -147
  182. package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +0 -35
  183. package/src/components/FieldCode/hooks/useFieldHelpers.ts +0 -52
  184. package/src/components/FieldCode/hooks/useFocusCell.ts +0 -29
  185. package/src/components/FieldCode/index.ts +0 -2
  186. package/src/components/FieldCode/styles.module.scss +0 -40
  187. 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,5 +0,0 @@
1
- .cell {
2
- input {
3
- text-align: center;
4
- }
5
- }
@@ -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,5 +0,0 @@
1
- export function formatSecondsAsMmSs(totalSeconds: number): string {
2
- const minutes = Math.floor(totalSeconds / 60);
3
- const seconds = totalSeconds % 60;
4
- return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
5
- }
@@ -1,2 +0,0 @@
1
- export * from './Cell';
2
- 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,4 +0,0 @@
1
- export * from './useCodeInput';
2
- export * from './useFieldCodeValidate';
3
- export * from './useFocusCell';
4
- export * from './useFieldHelpers';
@@ -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,2 +0,0 @@
1
- export * from './FieldCode';
2
- export { useFieldCodeValidate, type UseFieldCodeValidateParams } from './hooks/useFieldCodeValidate';
@@ -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
- };